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.util.HashMap;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.concurrent.ConcurrentHashMap;
33
34 import org.apache.directory.api.i18n.I18n;
35 import org.apache.directory.api.ldap.model.entry.Attribute;
36 import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
37 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
38 import org.apache.directory.api.ldap.model.entry.DefaultModification;
39 import org.apache.directory.api.ldap.model.entry.Entry;
40 import org.apache.directory.api.ldap.model.entry.Modification;
41 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
42 import org.apache.directory.api.ldap.model.entry.StringValue;
43 import org.apache.directory.api.ldap.model.entry.Value;
44 import org.apache.directory.api.ldap.model.exception.LdapException;
45 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
46 import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
47 import org.apache.directory.api.ldap.model.message.Control;
48 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
49 import org.apache.directory.api.ldap.model.name.Dn;
50 import org.apache.directory.api.ldap.model.name.Rdn;
51 import org.apache.directory.api.ldap.model.schema.SchemaManager;
52 import org.apache.directory.api.util.Base64;
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.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_12085, 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.encode( ( byte[] ) ava ) ) );
229 sb.append( '\n' );
230 }
231 else
232 {
233 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err(
234 I18n.ERR_12086, 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_12087 ) );
245 }
246
247
248 LdifReader reader = new LdifReader();
249 List<LdifEntry> ldifEntries = reader.parseLdif( sb.toString() );
250
251 try
252 {
253 reader.close();
254 }
255 catch ( IOException e )
256 {
257 e.printStackTrace();
258 }
259
260 if ( ( ldifEntries != null ) && ( ldifEntries.size() == 1 ) )
261 {
262 LdifEntry ldifEntry = ldifEntries.get( 0 );
263
264 changeType = ldifEntry.getChangeType();
265 controls = ldifEntry.getControls();
266 entryDn = ldifEntry.getDn();
267
268 switch ( ldifEntry.getChangeType() )
269 {
270 case Add:
271
272 case None:
273 entry = ldifEntry.getEntry();
274 break;
275
276 case Delete:
277 break;
278
279 case ModDn:
280 case ModRdn:
281 newRdn = ldifEntry.getNewRdn();
282 newSuperior = ldifEntry.getNewSuperior();
283 deleteOldRdn = ldifEntry.isDeleteOldRdn();
284 break;
285
286 case Modify:
287 modificationList = ldifEntry.getModifications();
288 modifications = new HashMap<>();
289
290 for ( Modification modification : modificationList )
291 {
292 modifications.put( modification.getAttribute().getId(), modification );
293 }
294
295 break;
296
297 default:
298 throw new IllegalArgumentException( "Unexpected ChangeType: " + changeType );
299 }
300 }
301 }
302
303
304
305
306
307
308
309
310
311
312
313
314 public LdifEntry( String dn, Object... strings )
315 throws LdapInvalidAttributeValueException, LdapLdifException, LdapInvalidDnException
316 {
317 this( new Dn( dn ), strings );
318 }
319
320
321
322
323
324
325
326 public void setDn( Dn dn )
327 {
328 entryDn = dn;
329 entry.setDn( dn );
330 }
331
332
333
334
335
336
337
338
339 public void setDn( String dn ) throws LdapInvalidDnException
340 {
341 entryDn = new Dn( dn );
342 entry.setDn( entryDn );
343 }
344
345
346
347
348
349
350
351
352 public void setChangeType( ChangeType changeType )
353 {
354 this.changeType = changeType;
355 }
356
357
358
359
360
361
362
363 public void setChangeType( String changeType )
364 {
365 if ( "add".equals( changeType ) )
366 {
367 this.changeType = ChangeType.Add;
368 }
369 else if ( "modify".equals( changeType ) )
370 {
371 this.changeType = ChangeType.Modify;
372 }
373 else if ( "moddn".equals( changeType ) )
374 {
375 this.changeType = ChangeType.ModDn;
376 }
377 else if ( "modrdn".equals( changeType ) )
378 {
379 this.changeType = ChangeType.ModRdn;
380 }
381 else if ( "delete".equals( changeType ) )
382 {
383 this.changeType = ChangeType.Delete;
384 }
385 }
386
387
388
389
390
391
392
393 public void addModification( Modification modification )
394 {
395 if ( changeType == ChangeType.Modify )
396 {
397 modificationList.add( modification );
398 modifications.put( modification.getAttribute().getId(), modification );
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 public void addModification( ModificationOperation modOp, String id )
439 {
440 if ( changeType == ChangeType.Modify )
441 {
442 Attribute attr = new DefaultAttribute( id );
443
444 Modification item = new DefaultModification( modOp, attr );
445 modificationList.add( item );
446 modifications.put( id, item );
447 }
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 public void addModification( ModificationOperation modOp, String id, Object value )
465 {
466 if ( changeType == ChangeType.Modify )
467 {
468 Attribute attr;
469
470 if ( value == null )
471 {
472 value = new StringValue( ( String ) null );
473 attr = new DefaultAttribute( id, ( Value<?> ) value );
474 }
475 else
476 {
477 attr = ( Attribute ) value;
478 }
479
480 Modification item = new DefaultModification( modOp, attr );
481 modificationList.add( item );
482 modifications.put( id, item );
483 }
484 }
485
486
487
488
489
490
491
492
493 public void addAttribute( Attribute attr ) throws LdapException
494 {
495 entry.put( attr );
496 }
497
498
499
500
501
502
503
504
505
506
507 public void addAttribute( String id, Object... values ) throws LdapException
508 {
509 Attribute attribute = entry.get( id );
510 Boolean isHR = null;
511
512 if ( attribute != null )
513 {
514 isHR = attribute.isHumanReadable();
515 }
516
517 if ( values != null )
518 {
519 for ( Object value : values )
520 {
521 if ( value instanceof String )
522 {
523 if ( isHR != null )
524 {
525 if ( isHR )
526 {
527 entry.add( id, ( String ) value );
528 }
529 else
530 {
531 entry.add( id, Strings.getBytesUtf8( ( String ) value ) );
532 }
533 }
534 else
535 {
536 entry.add( id, ( String ) value );
537 }
538 }
539 else
540 {
541 if ( isHR != null )
542 {
543 if ( isHR )
544 {
545 entry.add( id, Strings.utf8ToString( ( byte[] ) value ) );
546 }
547 else
548 {
549 entry.add( id, ( byte[] ) value );
550 }
551 }
552 else
553 {
554 entry.add( id, ( byte[] ) value );
555 }
556 }
557 }
558 }
559 else
560 {
561 entry.add( id, ( Value<?> ) null );
562 }
563 }
564
565
566
567
568
569
570
571 public void removeAttribute( String... ids )
572 {
573 if ( entry.containsAttribute( ids ) )
574 {
575 entry.removeAttributes( ids );
576 }
577 }
578
579
580
581
582
583
584
585
586
587
588 public void putAttribute( String id, Object value ) throws LdapException
589 {
590 if ( value instanceof String )
591 {
592 entry.add( id, ( String ) value );
593 }
594 else
595 {
596 entry.add( id, ( byte[] ) value );
597 }
598 }
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 public ChangeType getChangeType()
615 {
616 return changeType;
617 }
618
619
620
621
622
623 public List<Modification> getModifications()
624 {
625 return modificationList;
626 }
627
628
629
630
631
632
633
634 public Modification[] getModificationArray()
635 {
636 return modificationList.toArray( EMPTY_MODS );
637 }
638
639
640
641
642
643 public Dn getDn()
644 {
645 return entryDn;
646 }
647
648
649
650
651
652 public int size()
653 {
654 return modificationList.size();
655 }
656
657
658
659
660
661
662
663
664 public Attribute get( String attributeId )
665 {
666 if ( "dn".equalsIgnoreCase( attributeId ) )
667 {
668 return new DefaultAttribute( "dn", entry.getDn().getName() );
669 }
670
671 return entry.get( attributeId );
672 }
673
674
675
676
677
678
679
680 public Entry getEntry()
681 {
682 if ( isEntry() )
683 {
684 return entry;
685 }
686 else
687 {
688 return null;
689 }
690 }
691
692
693
694
695
696 public boolean isDeleteOldRdn()
697 {
698 return deleteOldRdn;
699 }
700
701
702
703
704
705
706
707 public void setDeleteOldRdn( boolean deleteOldRdn )
708 {
709 this.deleteOldRdn = deleteOldRdn;
710 }
711
712
713
714
715
716 public String getNewRdn()
717 {
718 return newRdn;
719 }
720
721
722
723
724
725
726
727 public void setNewRdn( String newRdn )
728 {
729 this.newRdn = newRdn;
730 }
731
732
733
734
735
736 public String getNewSuperior()
737 {
738 return newSuperior;
739 }
740
741
742
743
744
745
746
747 public void setNewSuperior( String newSuperior )
748 {
749 this.newSuperior = newSuperior;
750 }
751
752
753
754
755
756 public boolean isLdifContent()
757 {
758 return changeType == ChangeType.None;
759 }
760
761
762
763
764
765 public boolean isLdifChange()
766 {
767 return changeType != ChangeType.None;
768 }
769
770
771
772
773
774 public boolean isChangeAdd()
775 {
776 return changeType == ChangeType.Add;
777 }
778
779
780
781
782
783 public boolean isChangeDelete()
784 {
785 return changeType == ChangeType.Delete;
786 }
787
788
789
790
791
792 public boolean isChangeModDn()
793 {
794 return changeType == ChangeType.ModDn;
795 }
796
797
798
799
800
801 public boolean isChangeModRdn()
802 {
803 return changeType == ChangeType.ModRdn;
804 }
805
806
807
808
809
810 public boolean isChangeModify()
811 {
812 return changeType == ChangeType.Modify;
813 }
814
815
816
817
818
819
820
821 public boolean isEntry()
822 {
823 return ( changeType == ChangeType.None ) || ( changeType == ChangeType.Add );
824 }
825
826
827
828
829
830 public boolean hasControls()
831 {
832 return controls != null;
833 }
834
835
836
837
838
839 public Map<String, LdifControl> getControls()
840 {
841 return controls;
842 }
843
844
845
846
847
848
849 public LdifControl getControl( String oid )
850 {
851 if ( controls != null )
852 {
853 return controls.get( oid );
854 }
855
856 return null;
857 }
858
859
860
861
862
863
864
865 public void addControl( Control... controls )
866 {
867 if ( controls == null )
868 {
869 throw new IllegalArgumentException( "The added control must not be null" );
870 }
871
872 for ( Control control : controls )
873 {
874 if ( changeType == ChangeType.None )
875 {
876 changeType = ChangeType.Add;
877 }
878
879 if ( this.controls == null )
880 {
881 this.controls = new ConcurrentHashMap<>();
882 }
883
884 if ( control instanceof LdifControl )
885 {
886 this.controls.put( control.getOid(), ( LdifControl ) control );
887 }
888 else
889 {
890 LdifControl ldifControl = new LdifControl( control.getOid() );
891 ldifControl.setCritical( control.isCritical() );
892 this.controls.put( control.getOid(), new LdifControl( control.getOid() ) );
893 }
894 }
895 }
896
897
898
899
900
901
902
903 @Override
904 public LdifEntry clone() throws CloneNotSupportedException
905 {
906 LdifEntry clone = ( LdifEntry ) super.clone();
907
908 if ( modificationList != null )
909 {
910 for ( Modification modif : modificationList )
911 {
912 Modification modifClone = new DefaultModification( modif.getOperation(),
913 modif.getAttribute().clone() );
914 clone.modificationList.add( modifClone );
915 }
916 }
917
918 if ( modifications != null )
919 {
920 for ( Map.Entry<String, Modification> mapEntry : modifications.entrySet() )
921 {
922 Modification modif = mapEntry.getValue();
923 Modification modifClone = new DefaultModification( modif.getOperation(),
924 modif.getAttribute().clone() );
925 clone.modifications.put( mapEntry.getKey(), modifClone );
926 }
927
928 }
929
930 if ( entry != null )
931 {
932 clone.entry = entry.clone();
933 }
934
935 return clone;
936 }
937
938
939
940
941
942
943
944
945
946
947 public int getLengthBeforeParsing()
948 {
949 return lengthBeforeParsing;
950 }
951
952
953
954
955
956
957 void setLengthBeforeParsing( int length )
958 {
959 this.lengthBeforeParsing = length;
960 }
961
962
963
964
965
966 public long getOffset()
967 {
968 return offset;
969 }
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> mapEntry : controls.entrySet() )
1271 {
1272 String controlOid = mapEntry.getKey();
1273
1274 if ( !otherControls.containsKey( controlOid ) )
1275 {
1276 return false;
1277 }
1278
1279 Control thisControl = mapEntry.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( "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( "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 }