1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.ldap.model.ldif;
21
22
23 import java.io.Externalizable;
24 import java.io.IOException;
25 import java.io.ObjectInput;
26 import java.io.ObjectOutput;
27 import java.nio.charset.StandardCharsets;
28 import java.util.Base64;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.concurrent.ConcurrentHashMap;
35
36 import org.apache.directory.api.i18n.I18n;
37 import org.apache.directory.api.ldap.model.entry.Attribute;
38 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
39 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
40 import org.apache.directory.api.ldap.model.entry.DefaultModification;
41 import org.apache.directory.api.ldap.model.entry.Entry;
42 import org.apache.directory.api.ldap.model.entry.Modification;
43 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
44 import org.apache.directory.api.ldap.model.entry.Value;
45 import org.apache.directory.api.ldap.model.exception.LdapException;
46 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
47 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
48 import org.apache.directory.api.ldap.model.message.Control;
49 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
50 import org.apache.directory.api.ldap.model.name.Dn;
51 import org.apache.directory.api.ldap.model.name.Rdn;
52 import org.apache.directory.api.ldap.model.schema.SchemaManager;
53 import org.apache.directory.api.util.Strings;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class LdifEntry implements Cloneable, Externalizable, Iterable<Attribute>
71 {
72
73 public static final Modification[] EMPTY_MODS = new Modification[0];
74
75
76 private ChangeType changeType;
77
78
79 private List<Modification> modificationList;
80
81
82 private Map<String, Modification> modifications;
83
84
85 private String newSuperior;
86
87
88 private String newRdn;
89
90
91 private boolean deleteOldRdn;
92
93
94 private Entry entry;
95
96
97 private Dn entryDn;
98
99
100 private Map<String, LdifControl> controls;
101
102
103
104
105
106
107 private int lengthBeforeParsing = 0;
108
109
110 private long offset = 0;
111
112
113
114
115
116 public LdifEntry()
117 {
118
119 changeType = ChangeType.None;
120 modificationList = new LinkedList<>();
121 modifications = new HashMap<>();
122 entry = new DefaultEntry( ( Dn ) null );
123 entryDn = null;
124 controls = null;
125 }
126
127
128
129
130
131
132
133 public LdifEntry( SchemaManager schemaManager )
134 {
135
136 changeType = ChangeType.None;
137 modificationList = new LinkedList<>();
138 modifications = new HashMap<>();
139 entry = new DefaultEntry( schemaManager, ( Dn ) null );
140 entryDn = null;
141 controls = null;
142 }
143
144
145
146
147
148
149
150 public LdifEntry( Entry entry )
151 {
152
153 changeType = ChangeType.None;
154 modificationList = new LinkedList<>();
155 modifications = new HashMap<>();
156 this.entry = entry;
157 entryDn = entry.getDn();
158 controls = null;
159 }
160
161
162
163
164
165
166
167
168
169
170
171 public LdifEntry( Dn dn, Object... avas ) throws LdapInvalidAttributeValueException, LdapLdifException
172 {
173
174 StringBuilder sb = new StringBuilder();
175 int pos = 0;
176 boolean valueExpected = false;
177 String dnStr = null;
178
179 if ( dn == null )
180 {
181 dnStr = "";
182 }
183 else
184 {
185 dnStr = dn.getName();
186 }
187
188 if ( LdifUtils.isLDIFSafe( dnStr ) )
189 {
190 sb.append( "dn: " ).append( dnStr ).append( '\n' );
191 }
192 else
193 {
194 sb.append( "dn:: " ).append( Base64.getEncoder().encode( Strings.getBytesUtf8( dnStr ) ) ).append( '\n' );
195 }
196
197 for ( Object ava : avas )
198 {
199 if ( !valueExpected )
200 {
201 if ( !( ava instanceof String ) )
202 {
203 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
204 I18n.ERR_13233_ATTRIBUTE_ID_MUST_BE_A_STRING, pos + 1 ) );
205 }
206
207 String attribute = ( String ) ava;
208 sb.append( attribute );
209
210 if ( attribute.indexOf( ':' ) != -1 )
211 {
212 sb.append( '\n' );
213 }
214 else
215 {
216 valueExpected = true;
217 }
218 }
219 else
220 {
221 if ( ava instanceof String )
222 {
223 sb.append( ": " ).append( ( String ) ava ).append( '\n' );
224 }
225 else if ( ava instanceof byte[] )
226 {
227 sb.append( ":: " );
228 sb.append( new String( Base64.getEncoder().encode( ( byte[] ) ava ), StandardCharsets.UTF_8 ) );
229 sb.append( '\n' );
230 }
231 else
232 {
233 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
234 I18n.ERR_13234_ATTRIBUTE_VAL_STRING_OR_BYTE, pos + 1 ) );
235 }
236
237 valueExpected = false;
238 }
239 }
240
241 if ( valueExpected )
242 {
243 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n
244 .err( I18n.ERR_13250_VALUE_MISSING_AT_THE_END ) );
245 }
246
247
248 List<LdifEntry> ldifEntries = null;
249
250 try ( LdifReader reader = new LdifReader() )
251 {
252 ldifEntries = reader.parseLdif( sb.toString() );
253 }
254 catch ( IOException e )
255 {
256 e.printStackTrace();
257 }
258
259 if ( ( ldifEntries != null ) && ( ldifEntries.size() == 1 ) )
260 {
261 LdifEntry ldifEntry = ldifEntries.get( 0 );
262
263 changeType = ldifEntry.getChangeType();
264 controls = ldifEntry.getControls();
265 entryDn = ldifEntry.getDn();
266
267 switch ( ldifEntry.getChangeType() )
268 {
269 case Add:
270
271 case None:
272 entry = ldifEntry.getEntry();
273 break;
274
275 case Delete:
276 break;
277
278 case ModDn:
279 case ModRdn:
280 newRdn = ldifEntry.getNewRdn();
281 newSuperior = ldifEntry.getNewSuperior();
282 deleteOldRdn = ldifEntry.isDeleteOldRdn();
283 break;
284
285 case Modify:
286 modificationList = ldifEntry.getModifications();
287 modifications = new HashMap<>();
288
289 for ( Modification modification : modificationList )
290 {
291 modifications.put( modification.getAttribute().getId(), modification );
292 }
293
294 break;
295
296 default:
297 throw new IllegalArgumentException( I18n.err( I18n.ERR_13431_UNEXPECTED_CHANGETYPE, changeType ) );
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313 public LdifEntry( String dn, Object... strings )
314 throws LdapInvalidAttributeValueException, LdapLdifException, LdapInvalidDnException
315 {
316 this( new Dn( dn ), strings );
317 }
318
319
320
321
322
323
324
325 public void setDn( Dn dn )
326 {
327 entryDn = dn;
328 entry.setDn( dn );
329 }
330
331
332
333
334
335
336
337
338 public void setDn( String dn ) throws LdapInvalidDnException
339 {
340 entryDn = new Dn( dn );
341 entry.setDn( entryDn );
342 }
343
344
345
346
347
348
349
350
351 public void setChangeType( ChangeType changeType )
352 {
353 this.changeType = changeType;
354 }
355
356
357
358
359
360
361
362 public void setChangeType( String changeType )
363 {
364 if ( "add".equals( changeType ) )
365 {
366 this.changeType = ChangeType.Add;
367 }
368 else if ( "modify".equals( changeType ) )
369 {
370 this.changeType = ChangeType.Modify;
371 }
372 else if ( "moddn".equals( changeType ) )
373 {
374 this.changeType = ChangeType.ModDn;
375 }
376 else if ( "modrdn".equals( changeType ) )
377 {
378 this.changeType = ChangeType.ModRdn;
379 }
380 else if ( "delete".equals( changeType ) )
381 {
382 this.changeType = ChangeType.Delete;
383 }
384 }
385
386
387
388
389
390
391
392 public void addModification( Modification modification )
393 {
394 if ( changeType == ChangeType.Modify )
395 {
396 modificationList.add( modification );
397 modifications.put( modification.getAttribute().getId(), modification );
398 }
399 }
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 public void addModification( ModificationOperation modOp, Attribute attr )
416 {
417 if ( changeType == ChangeType.Modify )
418 {
419 Modification item = new DefaultModification( modOp, attr );
420 modificationList.add( item );
421 modifications.put( attr.getId(), item );
422 }
423 }
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 public void addModification( ModificationOperation modOp, String id )
440 {
441 if ( changeType == ChangeType.Modify )
442 {
443 Attribute attr = new DefaultAttribute( id );
444
445 Modification item = new DefaultModification( modOp, attr );
446 modificationList.add( item );
447 modifications.put( id, item );
448 }
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 public void addModification( ModificationOperation modOp, String id, Object value )
467 {
468 if ( changeType == ChangeType.Modify )
469 {
470 Attribute attr;
471
472 if ( value == null )
473 {
474 value = new Value( ( String ) null );
475 attr = new DefaultAttribute( id, ( Value ) value );
476 }
477 else
478 {
479 attr = ( Attribute ) value;
480 }
481
482 Modification item = new DefaultModification( modOp, attr );
483 modificationList.add( item );
484 modifications.put( id, item );
485 }
486 }
487
488
489
490
491
492
493
494
495 public void addAttribute( Attribute attr ) throws LdapException
496 {
497 entry.put( attr );
498 }
499
500
501
502
503
504
505
506
507
508
509 public void addAttribute( String id, Object... values ) throws LdapException
510 {
511 Attribute attribute = entry.get( id );
512 Boolean isHR = null;
513
514 if ( attribute != null )
515 {
516 isHR = attribute.isHumanReadable();
517 }
518
519 if ( values != null )
520 {
521 for ( Object value : values )
522 {
523 if ( value instanceof String )
524 {
525 if ( isHR != null )
526 {
527 if ( isHR )
528 {
529 entry.add( id, ( String ) value );
530 }
531 else
532 {
533 entry.add( id, Strings.getBytesUtf8( ( String ) value ) );
534 }
535 }
536 else
537 {
538 entry.add( id, ( String ) value );
539 }
540 }
541 else
542 {
543 if ( isHR != null )
544 {
545 if ( isHR )
546 {
547 entry.add( id, Strings.utf8ToString( ( byte[] ) value ) );
548 }
549 else
550 {
551 entry.add( id, ( byte[] ) value );
552 }
553 }
554 else
555 {
556 entry.add( id, ( byte[] ) value );
557 }
558 }
559 }
560 }
561 else
562 {
563 entry.add( id, ( Value ) null );
564 }
565 }
566
567
568
569
570
571
572
573 public void removeAttribute( String... ids )
574 {
575 if ( entry.containsAttribute( ids ) )
576 {
577 entry.removeAttributes( ids );
578 }
579 }
580
581
582
583
584
585
586
587
588
589
590 public void putAttribute( String id, Object value ) throws LdapException
591 {
592 if ( value instanceof String )
593 {
594 entry.add( id, ( String ) value );
595 }
596 else
597 {
598 entry.add( id, ( byte[] ) value );
599 }
600 }
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616 public ChangeType getChangeType()
617 {
618 return changeType;
619 }
620
621
622
623
624
625 public List<Modification> getModifications()
626 {
627 return modificationList;
628 }
629
630
631
632
633
634
635
636 public Modification[] getModificationArray()
637 {
638 return modificationList.toArray( EMPTY_MODS );
639 }
640
641
642
643
644
645 public Dn getDn()
646 {
647 return entryDn;
648 }
649
650
651
652
653
654 public int size()
655 {
656 return modificationList.size();
657 }
658
659
660
661
662
663
664
665
666 public Attribute get( String attributeId )
667 {
668 if ( "dn".equalsIgnoreCase( attributeId ) )
669 {
670 return new DefaultAttribute( "dn", entry.getDn().getName() );
671 }
672
673 return entry.get( attributeId );
674 }
675
676
677
678
679
680
681
682 public Entry getEntry()
683 {
684 if ( isEntry() )
685 {
686 return entry;
687 }
688 else
689 {
690 return null;
691 }
692 }
693
694
695
696
697
698 public boolean isDeleteOldRdn()
699 {
700 return deleteOldRdn;
701 }
702
703
704
705
706
707
708
709 public void setDeleteOldRdn( boolean deleteOldRdn )
710 {
711 this.deleteOldRdn = deleteOldRdn;
712 }
713
714
715
716
717
718 public String getNewRdn()
719 {
720 return newRdn;
721 }
722
723
724
725
726
727
728
729 public void setNewRdn( String newRdn )
730 {
731 this.newRdn = newRdn;
732 }
733
734
735
736
737
738 public String getNewSuperior()
739 {
740 return newSuperior;
741 }
742
743
744
745
746
747
748
749 public void setNewSuperior( String newSuperior )
750 {
751 this.newSuperior = newSuperior;
752 }
753
754
755
756
757
758 public boolean isLdifContent()
759 {
760 return changeType == ChangeType.None;
761 }
762
763
764
765
766
767 public boolean isLdifChange()
768 {
769 return changeType != ChangeType.None;
770 }
771
772
773
774
775
776 public boolean isChangeAdd()
777 {
778 return changeType == ChangeType.Add;
779 }
780
781
782
783
784
785 public boolean isChangeDelete()
786 {
787 return changeType == ChangeType.Delete;
788 }
789
790
791
792
793
794 public boolean isChangeModDn()
795 {
796 return changeType == ChangeType.ModDn;
797 }
798
799
800
801
802
803 public boolean isChangeModRdn()
804 {
805 return changeType == ChangeType.ModRdn;
806 }
807
808
809
810
811
812 public boolean isChangeModify()
813 {
814 return changeType == ChangeType.Modify;
815 }
816
817
818
819
820
821
822
823 public boolean isEntry()
824 {
825 return ( changeType == ChangeType.None ) || ( changeType == ChangeType.Add );
826 }
827
828
829
830
831
832 public boolean hasControls()
833 {
834 return controls != null;
835 }
836
837
838
839
840
841 public Map<String, LdifControl> getControls()
842 {
843 return controls;
844 }
845
846
847
848
849
850
851 public LdifControl getControl( String oid )
852 {
853 if ( controls != null )
854 {
855 return controls.get( oid );
856 }
857
858 return null;
859 }
860
861
862
863
864
865
866
867 public void addControl( Control... controls )
868 {
869 if ( controls == null )
870 {
871 throw new IllegalArgumentException( I18n.err( I18n.ERR_13432_NULL_ADDED_CONTROL ) );
872 }
873
874 for ( Control control : controls )
875 {
876 if ( changeType == ChangeType.None )
877 {
878 changeType = ChangeType.Add;
879 }
880
881 if ( this.controls == null )
882 {
883 this.controls = new ConcurrentHashMap<>();
884 }
885
886 if ( control instanceof LdifControl )
887 {
888 this.controls.put( control.getOid(), ( LdifControl ) control );
889 }
890 else
891 {
892 LdifControl ldifControl = new LdifControl( control.getOid() );
893 ldifControl.setCritical( control.isCritical() );
894 this.controls.put( control.getOid(), new LdifControl( control.getOid() ) );
895 }
896 }
897 }
898
899
900
901
902
903
904
905 @Override
906 public LdifEntry clone() throws CloneNotSupportedException
907 {
908 LdifEntry clone = ( LdifEntry ) super.clone();
909
910 if ( modificationList != null )
911 {
912 for ( Modification modif : modificationList )
913 {
914 Modification modifClone = new DefaultModification( modif.getOperation(),
915 modif.getAttribute().clone() );
916 clone.modificationList.add( modifClone );
917 }
918 }
919
920 if ( modifications != null )
921 {
922 for ( Map.Entry<String, Modification> modificationEntry : modifications.entrySet() )
923 {
924 Modification modif = modificationEntry.getValue();
925 Modification modifClone = new DefaultModification( modif.getOperation(),
926 modif.getAttribute().clone() );
927 clone.modifications.put( modificationEntry.getKey(), modifClone );
928 }
929
930 }
931
932 if ( entry != null )
933 {
934 clone.entry = entry.clone();
935 }
936
937 return clone;
938 }
939
940
941
942
943
944
945
946
947
948
949 public int getLengthBeforeParsing()
950 {
951 return lengthBeforeParsing;
952 }
953
954
955
956
957
958 void setLengthBeforeParsing( int length )
959 {
960 this.lengthBeforeParsing = length;
961 }
962
963
964
965
966
967 public long getOffset()
968 {
969 return offset;
970 }
971
972
973
974
975
976 void setOffset( long offset )
977 {
978 this.offset = offset;
979 }
980
981
982
983
984
985
986
987
988
989 @Override
990 public Iterator<Attribute> iterator()
991 {
992 return entry.iterator();
993 }
994
995
996
997
998
999 @Override
1000 public String toString()
1001 {
1002 try
1003 {
1004 return LdifUtils.convertToLdif( this );
1005 }
1006 catch ( LdapException ne )
1007 {
1008 return "";
1009 }
1010 }
1011
1012
1013
1014
1015
1016
1017
1018 @Override
1019 public int hashCode()
1020 {
1021 int result = 37;
1022
1023 if ( entry != null && entry.getDn() != null )
1024 {
1025 result = result * 17 + entry.getDn().hashCode();
1026 }
1027
1028 if ( changeType != null )
1029 {
1030 result = result * 17 + changeType.hashCode();
1031
1032
1033 switch ( changeType )
1034 {
1035 case None:
1036
1037 case Add:
1038
1039 if ( entry != null )
1040 {
1041 result = result * 17 + entry.hashCode();
1042 }
1043
1044 break;
1045
1046 case Delete:
1047
1048 break;
1049
1050 case Modify:
1051 if ( modificationList != null )
1052 {
1053 result = result * 17 + modificationList.hashCode();
1054
1055 for ( Modification modification : modificationList )
1056 {
1057 result = result * 17 + modification.hashCode();
1058 }
1059 }
1060
1061 break;
1062
1063 case ModDn:
1064 case ModRdn:
1065 result = result * 17;
1066
1067 if ( deleteOldRdn )
1068 {
1069 result++;
1070 }
1071 else
1072 {
1073 result--;
1074 }
1075
1076 if ( newRdn != null )
1077 {
1078 result = result * 17 + newRdn.hashCode();
1079 }
1080
1081 if ( newSuperior != null )
1082 {
1083 result = result * 17 + newSuperior.hashCode();
1084 }
1085
1086 break;
1087
1088 default:
1089
1090 break;
1091 }
1092 }
1093
1094 if ( controls != null )
1095 {
1096 for ( String control : controls.keySet() )
1097 {
1098 result = result * 17 + control.hashCode();
1099 }
1100 }
1101
1102 return result;
1103 }
1104
1105
1106
1107
1108
1109 @Override
1110 public boolean equals( Object o )
1111 {
1112
1113 if ( this == o )
1114 {
1115 return true;
1116 }
1117
1118 if ( o == null )
1119 {
1120 return false;
1121 }
1122
1123 if ( !( o instanceof LdifEntry ) )
1124 {
1125 return false;
1126 }
1127
1128 LdifEntry otherEntry = ( LdifEntry ) o;
1129
1130
1131 Dn thisDn = entryDn;
1132 Dn dnEntry = otherEntry.getDn();
1133
1134 if ( !thisDn.equals( dnEntry ) )
1135 {
1136 return false;
1137 }
1138
1139
1140 if ( changeType != otherEntry.changeType )
1141 {
1142 return false;
1143 }
1144
1145
1146 switch ( changeType )
1147 {
1148 case None:
1149
1150 case Add:
1151
1152 if ( entry.size() != otherEntry.entry.size() )
1153 {
1154 return false;
1155 }
1156
1157 if ( !entry.equals( otherEntry.entry ) )
1158 {
1159 return false;
1160 }
1161
1162 break;
1163
1164 case Delete:
1165
1166 break;
1167
1168 case Modify:
1169
1170
1171
1172 if ( modificationList == null )
1173 {
1174 if ( otherEntry.modificationList != null )
1175 {
1176 return false;
1177 }
1178 else
1179 {
1180 break;
1181 }
1182 }
1183
1184 if ( otherEntry.modificationList == null )
1185 {
1186 return false;
1187 }
1188
1189 if ( modificationList.size() != otherEntry.modificationList.size() )
1190 {
1191 return false;
1192 }
1193
1194
1195 int i = 0;
1196
1197 for ( Modification modification : modificationList )
1198 {
1199 if ( !modification.equals( otherEntry.modificationList.get( i ) ) )
1200 {
1201 return false;
1202 }
1203
1204 i++;
1205 }
1206
1207 break;
1208
1209 case ModDn:
1210 case ModRdn:
1211
1212 if ( deleteOldRdn != otherEntry.deleteOldRdn )
1213 {
1214 return false;
1215 }
1216
1217
1218 try
1219 {
1220 Rdn thisNewRdn = new Rdn( newRdn );
1221 Rdn entryNewRdn = new Rdn( otherEntry.newRdn );
1222
1223 if ( !thisNewRdn.equals( entryNewRdn ) )
1224 {
1225 return false;
1226 }
1227 }
1228 catch ( LdapInvalidDnException ine )
1229 {
1230 return false;
1231 }
1232
1233
1234 try
1235 {
1236 Dn thisNewSuperior = new Dn( newSuperior );
1237 Dn entryNewSuperior = new Dn( otherEntry.newSuperior );
1238
1239 if ( !thisNewSuperior.equals( entryNewSuperior ) )
1240 {
1241 return false;
1242 }
1243 }
1244 catch ( LdapInvalidDnException ine )
1245 {
1246 return false;
1247 }
1248
1249 break;
1250
1251 default:
1252
1253 break;
1254 }
1255
1256 if ( controls != null )
1257 {
1258 Map<String, LdifControl> otherControls = otherEntry.controls;
1259
1260 if ( otherControls == null )
1261 {
1262 return false;
1263 }
1264
1265 if ( controls.size() != otherControls.size() )
1266 {
1267 return false;
1268 }
1269
1270 for ( Map.Entry<String, LdifControl> controlEntry : controls.entrySet() )
1271 {
1272 String controlOid = controlEntry.getKey();
1273
1274 if ( !otherControls.containsKey( controlOid ) )
1275 {
1276 return false;
1277 }
1278
1279 Control thisControl = controlEntry.getValue();
1280 Control otherControl = otherControls.get( controlOid );
1281
1282 if ( thisControl == null )
1283 {
1284 if ( otherControl != null )
1285 {
1286 return false;
1287 }
1288 }
1289 else
1290 {
1291 if ( !thisControl.equals( otherControl ) )
1292 {
1293 return false;
1294 }
1295 }
1296 }
1297
1298 return true;
1299 }
1300 else
1301 {
1302 return otherEntry.controls == null;
1303 }
1304 }
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 @Override
1315 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
1316 {
1317
1318 int type = in.readInt();
1319 changeType = ChangeType.getChangeType( type );
1320
1321
1322 switch ( changeType )
1323 {
1324 case Add:
1325 case None:
1326
1327 entry.readExternal( in );
1328 entryDn = entry.getDn();
1329
1330 break;
1331
1332 case Delete:
1333
1334 entryDn = new Dn();
1335 entryDn.readExternal( in );
1336
1337 break;
1338
1339 case ModDn:
1340
1341 case ModRdn:
1342
1343 entryDn = new Dn();
1344 entryDn.readExternal( in );
1345
1346 deleteOldRdn = in.readBoolean();
1347
1348 if ( in.readBoolean() )
1349 {
1350 newRdn = in.readUTF();
1351 }
1352
1353 if ( in.readBoolean() )
1354 {
1355 newSuperior = in.readUTF();
1356 }
1357
1358 break;
1359
1360 case Modify:
1361
1362 entryDn = new Dn();
1363 entryDn.readExternal( in );
1364
1365
1366 int nbModifs = in.readInt();
1367
1368 for ( int i = 0; i < nbModifs; i++ )
1369 {
1370 Modification modification = new DefaultModification();
1371 modification.readExternal( in );
1372
1373 addModification( modification );
1374 }
1375
1376 break;
1377
1378 default:
1379 throw new IllegalArgumentException( I18n.err( I18n.ERR_13431_UNEXPECTED_CHANGETYPE, changeType ) );
1380 }
1381
1382 int nbControls = in.readInt();
1383
1384
1385 if ( nbControls > 0 )
1386 {
1387 controls = new ConcurrentHashMap<>( nbControls );
1388
1389 for ( int i = 0; i < nbControls; i++ )
1390 {
1391 LdifControl control = new LdifControl();
1392
1393 control.readExternal( in );
1394
1395 controls.put( control.getOid(), control );
1396 }
1397 }
1398 }
1399
1400
1401
1402
1403
1404
1405
1406 @Override
1407 public void writeExternal( ObjectOutput out ) throws IOException
1408 {
1409
1410 out.writeInt( changeType.getChangeType() );
1411
1412
1413 switch ( changeType )
1414 {
1415 case Add:
1416 case None:
1417 entry.writeExternal( out );
1418 break;
1419
1420
1421 case Delete:
1422
1423 entryDn.writeExternal( out );
1424 break;
1425
1426 case ModDn:
1427
1428 case ModRdn:
1429
1430 entryDn.writeExternal( out );
1431
1432 out.writeBoolean( deleteOldRdn );
1433
1434 if ( newRdn == null )
1435 {
1436 out.writeBoolean( false );
1437 }
1438 else
1439 {
1440 out.writeBoolean( true );
1441 out.writeUTF( newRdn );
1442 }
1443
1444 if ( newSuperior != null )
1445 {
1446 out.writeBoolean( true );
1447 out.writeUTF( newSuperior );
1448 }
1449 else
1450 {
1451 out.writeBoolean( false );
1452 }
1453 break;
1454
1455 case Modify:
1456
1457 entryDn.writeExternal( out );
1458
1459
1460 out.writeInt( modificationList.size() );
1461
1462 for ( Modification modification : modificationList )
1463 {
1464 modification.writeExternal( out );
1465 }
1466
1467 break;
1468
1469 default:
1470 throw new IllegalArgumentException( I18n.err( I18n.ERR_13431_UNEXPECTED_CHANGETYPE, changeType ) );
1471 }
1472
1473
1474 if ( controls != null )
1475 {
1476
1477 out.writeInt( controls.size() );
1478
1479 for ( LdifControl control : controls.values() )
1480 {
1481 control.writeExternal( out );
1482 }
1483 }
1484 else
1485 {
1486
1487 out.writeInt( -1 );
1488 }
1489
1490
1491 out.flush();
1492 }
1493 }