1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.directory.api.ldap.model.entry;
20
21
22 import java.io.IOException;
23 import java.io.ObjectInput;
24 import java.io.ObjectOutput;
25 import java.util.Iterator;
26 import java.util.LinkedHashSet;
27 import java.util.Set;
28
29 import org.apache.directory.api.asn1.util.Oid;
30 import org.apache.directory.api.i18n.I18n;
31 import org.apache.directory.api.ldap.model.exception.LdapException;
32 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
33 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
34 import org.apache.directory.api.ldap.model.schema.AttributeType;
35 import org.apache.directory.api.ldap.model.schema.LdapSyntax;
36 import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
37 import org.apache.directory.api.util.Strings;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41
42
43
44
45
46
47
48 public class DefaultAttribute implements Attribute, Cloneable
49 {
50
51 private static final Logger LOG = LoggerFactory.getLogger( DefaultAttribute.class );
52
53
54 private AttributeType attributeType;
55
56
57 private Set<Value> values = new LinkedHashSet<>();
58
59
60 private String upId;
61
62
63 private String id;
64
65
66
67 private Boolean isHR;
68
69
70 private volatile int h;
71
72
73
74
75
76
77
78
79
80
81
82 DefaultAttribute()
83 {
84 }
85
86
87
88
89
90
91
92
93
94
95
96
97
98 DefaultAttribute( AttributeType attributeType, String upId, String normId, boolean isHR,
99 int hashCode, Value... values )
100 {
101 this.attributeType = attributeType;
102 this.upId = upId;
103 this.id = normId;
104 this.isHR = isHR;
105 this.h = hashCode;
106
107 if ( values != null )
108 {
109 for ( Value value : values )
110 {
111 this.values.add( value );
112 }
113 }
114 }
115
116
117
118
119
120
121
122 public DefaultAttribute( AttributeType attributeType )
123 {
124 if ( attributeType != null )
125 {
126 try
127 {
128 apply( attributeType );
129 }
130 catch ( LdapInvalidAttributeValueException liave )
131 {
132
133 liave.printStackTrace();
134 }
135 }
136 }
137
138
139
140
141
142
143 public DefaultAttribute( String upId )
144 {
145 setUpId( upId );
146 }
147
148
149
150
151
152
153 public DefaultAttribute( byte[] upId )
154 {
155 setUpId( upId );
156 }
157
158
159
160
161
162
163
164
165 public DefaultAttribute( String upId, AttributeType attributeType )
166 {
167 if ( attributeType == null )
168 {
169 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
170 LOG.error( message );
171 throw new IllegalArgumentException( message );
172 }
173
174 try
175 {
176 apply( attributeType );
177 }
178 catch ( LdapInvalidAttributeValueException liave )
179 {
180
181 }
182
183 setUpId( upId, attributeType );
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198 public DefaultAttribute( String upId, Value... vals )
199 {
200
201 if ( vals[0] == null )
202 {
203 add( new Value( ( String ) null ) );
204 }
205 else
206 {
207 for ( Value val : vals )
208 {
209 add( val );
210 }
211 }
212
213 setUpId( upId );
214 }
215
216
217
218
219
220
221
222
223
224
225 public DefaultAttribute( AttributeType attributeType, String... vals ) throws LdapInvalidAttributeValueException
226 {
227 this( null, attributeType, vals );
228 }
229
230
231
232
233
234
235
236
237
238
239
240 public DefaultAttribute( String upId, AttributeType attributeType, String... vals )
241 throws LdapInvalidAttributeValueException
242 {
243 if ( attributeType == null )
244 {
245 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
246 LOG.error( message );
247 throw new IllegalArgumentException( message );
248 }
249
250 apply( attributeType );
251
252 if ( ( vals != null ) && ( vals.length > 0 ) )
253 {
254 add( vals );
255 }
256
257 setUpId( upId, attributeType );
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 public DefaultAttribute( String upId, AttributeType attributeType, Value... vals )
276 throws LdapInvalidAttributeValueException
277 {
278 if ( attributeType == null )
279 {
280 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED );
281 LOG.error( message );
282 throw new IllegalArgumentException( message );
283 }
284
285 apply( attributeType );
286 setUpId( upId, attributeType );
287 add( vals );
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302 public DefaultAttribute( AttributeType attributeType, Value... vals ) throws LdapInvalidAttributeValueException
303 {
304 this( null, attributeType, vals );
305 }
306
307
308
309
310
311
312
313
314 public DefaultAttribute( String upId, String... vals )
315 {
316 try
317 {
318 add( vals );
319 }
320 catch ( LdapInvalidAttributeValueException liave )
321 {
322
323 }
324
325 setUpId( upId );
326 }
327
328
329
330
331
332
333
334
335 public DefaultAttribute( String upId, byte[]... vals )
336 {
337 try
338 {
339 add( vals );
340 }
341 catch ( LdapInvalidAttributeValueException liave )
342 {
343
344 }
345
346 setUpId( upId );
347 }
348
349
350
351
352
353
354
355
356
357
358 public DefaultAttribute( AttributeType attributeType, byte[]... vals ) throws LdapInvalidAttributeValueException
359 {
360 this( null, attributeType, vals );
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 public DefaultAttribute( String upId, AttributeType attributeType, byte[]... vals )
375 throws LdapInvalidAttributeValueException
376 {
377 if ( attributeType == null )
378 {
379 throw new IllegalArgumentException( I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ) );
380 }
381
382 apply( attributeType );
383 add( vals );
384 setUpId( upId, attributeType );
385 }
386
387
388
389
390
391
392
393
394
395
396
397 public DefaultAttribute( AttributeType attributeType, Attribute attribute ) throws LdapException
398 {
399
400 this.attributeType = attributeType;
401 this.id = attribute.getId();
402 this.upId = attribute.getUpId();
403
404 if ( attributeType == null )
405 {
406 isHR = attribute.isHumanReadable();
407
408
409 for ( Value value : attribute )
410 {
411 add( value.clone() );
412 }
413
414 if ( attribute.getAttributeType() != null )
415 {
416 apply( attribute.getAttributeType() );
417 }
418 }
419 else
420 {
421
422 isHR = attributeType.getSyntax().isHumanReadable();
423
424
425 for ( Value clientValue : attribute )
426 {
427 Value serverValue = null;
428
429 if ( isHR )
430 {
431 serverValue = new Value( attributeType, clientValue.getString() );
432 }
433 else
434 {
435
436 serverValue = new Value( attributeType,
437 clientValue.getBytes() );
438 }
439
440 add( serverValue );
441 }
442 }
443 }
444
445
446
447
448
449 private Value createStringValue( AttributeType attributeType, String value )
450 {
451 Value newValue;
452
453 if ( attributeType != null )
454 {
455 try
456 {
457 newValue = new Value( attributeType, value );
458 }
459 catch ( LdapInvalidAttributeValueException iae )
460 {
461 return null;
462 }
463 }
464 else
465 {
466 newValue = new Value( value );
467 }
468
469 return newValue;
470 }
471
472
473 private Value createBinaryValue( AttributeType attributeType, byte[] value )
474 throws LdapInvalidAttributeValueException
475 {
476 Value binaryValue;
477
478 if ( attributeType != null )
479 {
480 binaryValue = new Value( attributeType, value );
481 }
482 else
483 {
484 binaryValue = new Value( value );
485 }
486
487 return binaryValue;
488 }
489
490
491
492
493
494 @Override
495 public byte[] getBytes() throws LdapInvalidAttributeValueException
496 {
497 Value value = get();
498
499 if ( !isHumanReadable() && ( value != null ) )
500 {
501 return value.getBytes();
502 }
503
504 String message = I18n.err( I18n.ERR_13214_VALUE_EXPECT_BYTES );
505 LOG.error( message );
506 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
507 }
508
509
510
511
512
513 @Override
514 public String getString() throws LdapInvalidAttributeValueException
515 {
516 Value value = get();
517
518 if ( isHumanReadable() )
519 {
520 if ( value != null )
521 {
522 return value.getString();
523 }
524 else
525 {
526 return "";
527 }
528 }
529
530 if ( attributeType == null )
531 {
532
533
534 return Strings.utf8ToString( value.getBytes() );
535 }
536
537 String message = I18n.err( I18n.ERR_13215_VALUE_EXPECT_STRING );
538 LOG.error( message );
539 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, message );
540 }
541
542
543
544
545
546 @Override
547 public String getId()
548 {
549 return id;
550 }
551
552
553
554
555
556 @Override
557 public String getUpId()
558 {
559 return upId;
560 }
561
562
563
564
565
566 @Override
567 public void setUpId( String upId )
568 {
569 setUpId( upId, attributeType );
570 }
571
572
573
574
575
576
577
578 public void setUpId( byte[] upId )
579 {
580 setUpId( upId, attributeType );
581 }
582
583
584
585
586
587
588
589
590
591 private boolean areCompatible( String id, AttributeType attributeType )
592 {
593
594 int optPos = id.indexOf( ';' );
595 String idNoOption = id;
596
597 if ( optPos != -1 )
598 {
599 idNoOption = id.substring( 0, optPos );
600 }
601
602
603 for ( String name : attributeType.getNames() )
604 {
605 if ( name.equalsIgnoreCase( idNoOption ) )
606 {
607 return true;
608 }
609 }
610
611
612 return Oid.isOid( id ) && attributeType.getOid().equals( id );
613 }
614
615
616
617
618
619 @Override
620 public void setUpId( String upId, AttributeType attributeType )
621 {
622 String trimmed = Strings.trim( upId );
623
624 if ( Strings.isEmpty( trimmed ) && ( attributeType == null ) )
625 {
626 throw new IllegalArgumentException( I18n.err( I18n.ERR_13235_NULL_ID_WITH_NULL_AT_NOT_ALLOWED ) );
627 }
628
629 String newId = Strings.toLowerCaseAscii( trimmed );
630
631 setUpIdInternal( upId, newId, attributeType );
632 }
633
634
635
636
637
638
639
640
641 public void setUpId( byte[] upId, AttributeType attributeType )
642 {
643 byte[] trimmed = Strings.trim( upId );
644
645 if ( Strings.isEmpty( trimmed ) && ( attributeType == null ) )
646 {
647 throw new IllegalArgumentException( I18n.err( I18n.ERR_13235_NULL_ID_WITH_NULL_AT_NOT_ALLOWED ) );
648 }
649
650 String newId = Strings.toLowerCase( trimmed );
651
652 setUpIdInternal( Strings.utf8ToString( upId ), newId, attributeType );
653 }
654
655
656 private void setUpIdInternal( String upId, String newId, AttributeType attributeType )
657 {
658 if ( attributeType == null )
659 {
660 if ( this.attributeType == null )
661 {
662 this.upId = upId;
663 this.id = newId;
664
665
666 rehash();
667
668 return;
669 }
670 else
671 {
672 if ( areCompatible( newId, this.attributeType ) )
673 {
674 this.upId = upId;
675 this.id = this.attributeType.getOid();
676
677
678 rehash();
679
680 return;
681 }
682 else
683 {
684 return;
685 }
686 }
687 }
688
689 if ( Strings.isEmpty( newId ) )
690 {
691 this.attributeType = attributeType;
692 this.upId = attributeType.getName();
693 this.id = attributeType.getOid();
694
695
696 rehash();
697
698 return;
699 }
700
701 if ( areCompatible( newId, attributeType ) )
702 {
703 this.upId = upId;
704 this.id = attributeType.getOid();
705 this.attributeType = attributeType;
706
707
708 rehash();
709
710 return;
711 }
712
713 throw new IllegalArgumentException( I18n.err( I18n.ERR_13244_ID_AT_NOT_COMPATIBLE, id, attributeType.getName() ) );
714 }
715
716
717
718
719
720 @Override
721 public boolean isHumanReadable()
722 {
723 return isHR != null && isHR;
724 }
725
726
727
728
729
730 @Override
731 public boolean isValid( AttributeType attributeType ) throws LdapInvalidAttributeValueException
732 {
733 LdapSyntax syntax = attributeType.getSyntax();
734
735 if ( syntax == null )
736 {
737 return false;
738 }
739
740 SyntaxChecker syntaxChecker = syntax.getSyntaxChecker();
741
742 if ( syntaxChecker == null )
743 {
744 return false;
745 }
746
747
748 if ( values.isEmpty() )
749 {
750 return syntaxChecker.isValidSyntax( null );
751 }
752
753
754 if ( ( attributeType.isSingleValued() ) && ( values.size() > 1 ) )
755 {
756 return false;
757 }
758
759
760 for ( Value value : values )
761 {
762 try
763 {
764 if ( !value.isValid( syntaxChecker ) )
765 {
766 return false;
767 }
768 }
769 catch ( LdapException le )
770 {
771 return false;
772 }
773 }
774
775 return true;
776 }
777
778
779
780
781
782 @Override
783 public int add( Value... vals )
784 {
785 int nbAdded = 0;
786 Value nullBinaryValue = null;
787 Value nullStringValue = null;
788 boolean nullValueAdded = false;
789 Value[] valArray = vals;
790
791 if ( vals == null )
792 {
793 valArray = new Value[0];
794 }
795
796 if ( attributeType != null )
797 {
798 for ( Value val : valArray )
799 {
800 if ( attributeType.getSyntax().isHumanReadable() )
801 {
802 if ( ( val == null ) || val.isNull() )
803 {
804 try
805 {
806 Value nullSV = new Value( attributeType, ( String ) null );
807
808 if ( values.add( nullSV ) )
809 {
810 nbAdded++;
811 }
812 }
813 catch ( LdapInvalidAttributeValueException iae )
814 {
815 continue;
816 }
817 }
818 else if ( val.isHumanReadable() )
819 {
820 try
821 {
822 if ( val.getAttributeType() == null )
823 {
824 val = new Value( attributeType, val );
825 }
826
827 if ( values.contains( val ) )
828 {
829
830 values.remove( val );
831 values.add( val );
832 }
833 else if ( values.add( val ) )
834 {
835 nbAdded++;
836 }
837 }
838 catch ( LdapInvalidAttributeValueException iae )
839 {
840 continue;
841 }
842 }
843 else
844 {
845 String message = I18n.err( I18n.ERR_13213_VALUE_MUST_BE_A_STRING );
846 LOG.error( message );
847 }
848 }
849 else
850 {
851 if ( val == null )
852 {
853 if ( attributeType.getSyntax().getSyntaxChecker().isValidSyntax( val ) )
854 {
855 try
856 {
857 Value nullSV = new Value( attributeType, ( byte[] ) null );
858
859 if ( values.add( nullSV ) )
860 {
861 nbAdded++;
862 }
863 }
864 catch ( LdapInvalidAttributeValueException iae )
865 {
866 continue;
867 }
868 }
869 else
870 {
871 String message = I18n.err( I18n.ERR_13211_BYTE_VALUE_EXPECTED );
872 LOG.error( message );
873 }
874 }
875 else
876 {
877 if ( !val.isHumanReadable() )
878 {
879 try
880 {
881 if ( val.getAttributeType() == null )
882 {
883 val = new Value( attributeType, val.getBytes() );
884 }
885
886 if ( values.add( val ) )
887 {
888 nbAdded++;
889 }
890 }
891 catch ( LdapInvalidAttributeValueException iae )
892 {
893 continue;
894 }
895 }
896 else
897 {
898 String message = I18n.err( I18n.ERR_13211_BYTE_VALUE_EXPECTED );
899 LOG.error( message );
900 }
901 }
902 }
903 }
904 }
905 else
906 {
907 for ( Value val : valArray )
908 {
909 if ( val == null )
910 {
911
912
913 if ( isHR == null )
914 {
915
916
917
918
919
920 nullBinaryValue = new Value( ( byte[] ) null );
921 nullStringValue = new Value( ( String ) null );
922
923 values.add( nullBinaryValue );
924 values.add( nullStringValue );
925 nullValueAdded = true;
926 nbAdded++;
927 }
928 else if ( !isHR )
929 {
930
931 nullBinaryValue = new Value( ( byte[] ) null );
932
933
934 if ( !values.contains( nullBinaryValue ) )
935 {
936 values.add( nullBinaryValue );
937 nbAdded++;
938 }
939
940 }
941 else
942 {
943
944 nullStringValue = new Value( ( String ) null );
945
946
947 if ( !values.contains( nullStringValue ) )
948 {
949 values.add( nullStringValue );
950 }
951 }
952 }
953 else
954 {
955
956 if ( val.isHumanReadable() )
957 {
958
959 if ( isHR == null )
960 {
961
962 isHR = true;
963 values.add( val );
964 nbAdded++;
965 }
966 else if ( !isHR )
967 {
968
969
970 Value bv = new Value( val.getBytes() );
971
972 if ( !contains( bv ) )
973 {
974 values.add( bv );
975 nbAdded++;
976 }
977 }
978 else
979 {
980
981 if ( !contains( val ) )
982 {
983 values.add( val );
984 nbAdded++;
985 }
986 }
987 }
988 else
989 {
990
991 if ( isHR == null )
992 {
993
994 isHR = false;
995 values.add( val );
996 nbAdded++;
997 }
998 else if ( !isHR )
999 {
1000
1001 if ( !contains( val ) )
1002 {
1003 values.add( val );
1004 nbAdded++;
1005 }
1006 }
1007 else
1008 {
1009
1010
1011 Value sv = new Value( Strings.utf8ToString( val.getBytes() ) );
1012
1013 if ( !contains( sv ) )
1014 {
1015 values.add( sv );
1016 nbAdded++;
1017 }
1018 }
1019 }
1020 }
1021 }
1022 }
1023
1024
1025
1026
1027 if ( nullValueAdded )
1028 {
1029 if ( isHR )
1030 {
1031
1032 values.remove( nullBinaryValue );
1033 }
1034 else
1035 {
1036
1037 values.remove( nullStringValue );
1038 }
1039 }
1040
1041 return nbAdded;
1042 }
1043
1044
1045
1046
1047
1048 @Override
1049 public int add( String... vals ) throws LdapInvalidAttributeValueException
1050 {
1051 int nbAdded = 0;
1052 String[] valArray = vals;
1053
1054 if ( vals == null )
1055 {
1056 valArray = new String[0];
1057 }
1058
1059
1060
1061 if ( isHR == null )
1062 {
1063 isHR = true;
1064 }
1065
1066
1067 if ( attributeType == null )
1068 {
1069 if ( isHR )
1070 {
1071 for ( String val : valArray )
1072 {
1073 Value value = createStringValue( attributeType, val );
1074
1075 if ( value == null )
1076 {
1077
1078 LOG.error( I18n.err( I18n.ERR_13200_VALUE_CANT_BE_NORMALIZED, val ) );
1079 continue;
1080 }
1081
1082
1083 if ( add( value ) == 1 )
1084 {
1085 nbAdded++;
1086 }
1087 else
1088 {
1089 if ( LOG.isWarnEnabled() )
1090 {
1091 LOG.warn( I18n.err( I18n.ERR_13207_VALUE_ALREADY_EXISTS, val, upId ) );
1092 }
1093 }
1094 }
1095 }
1096 else
1097 {
1098
1099 for ( String val : valArray )
1100 {
1101 byte[] valBytes = null;
1102
1103 if ( val != null )
1104 {
1105 valBytes = Strings.getBytesUtf8( val );
1106 }
1107
1108 Value value = createBinaryValue( attributeType, valBytes );
1109
1110
1111 if ( add( value ) == 1 )
1112 {
1113 nbAdded++;
1114 }
1115 }
1116 }
1117 }
1118 else
1119 {
1120 if ( attributeType.isSingleValued() && ( values.size() + valArray.length > 1 ) )
1121 {
1122 LOG.error( I18n.err( I18n.ERR_13208_ATTRIBUTE_IS_SINGLE_VALUED, attributeType.getName() ) );
1123 return 0;
1124 }
1125
1126 if ( isHR )
1127 {
1128 for ( String val : valArray )
1129 {
1130 Value value = createStringValue( attributeType, val );
1131
1132 if ( value == null )
1133 {
1134
1135 LOG.error( I18n.err( I18n.ERR_13200_VALUE_CANT_BE_NORMALIZED, val ) );
1136 continue;
1137 }
1138
1139
1140 if ( add( value ) == 1 )
1141 {
1142 nbAdded++;
1143 }
1144 else
1145 {
1146 if ( LOG.isWarnEnabled() )
1147 {
1148 LOG.warn( I18n.err( I18n.ERR_13207_VALUE_ALREADY_EXISTS, val, upId ) );
1149 }
1150 }
1151 }
1152 }
1153 else
1154 {
1155
1156 for ( String val : valArray )
1157 {
1158 byte[] valBytes = null;
1159
1160 if ( val != null )
1161 {
1162 valBytes = Strings.getBytesUtf8( val );
1163 }
1164
1165 Value value = createBinaryValue( attributeType, valBytes );
1166
1167
1168 if ( add( value ) == 1 )
1169 {
1170 nbAdded++;
1171 }
1172 }
1173 }
1174 }
1175
1176 return nbAdded;
1177 }
1178
1179
1180
1181
1182
1183 public int add( byte[]... vals ) throws LdapInvalidAttributeValueException
1184 {
1185 int nbAdded = 0;
1186 byte[][] valArray = vals;
1187
1188 if ( vals == null )
1189 {
1190 valArray = new byte[0][];
1191 }
1192
1193
1194
1195 if ( isHR == null )
1196 {
1197 isHR = false;
1198 }
1199
1200 if ( !isHR )
1201 {
1202 for ( byte[] val : valArray )
1203 {
1204 Value value;
1205
1206 if ( attributeType == null )
1207 {
1208 value = new Value( val );
1209 }
1210 else
1211 {
1212 value = createBinaryValue( attributeType, val );
1213 }
1214
1215 if ( add( value ) != 0 )
1216 {
1217 nbAdded++;
1218 }
1219 else
1220 {
1221 if ( LOG.isWarnEnabled() )
1222 {
1223 LOG.warn( I18n.err( I18n.ERR_13207_VALUE_ALREADY_EXISTS, Strings.dumpBytes( val ), upId ) );
1224 }
1225 }
1226 }
1227 }
1228 else
1229 {
1230
1231 if ( LOG.isInfoEnabled() )
1232 {
1233 LOG.info( I18n.err( I18n.ERR_13213_VALUE_MUST_BE_A_STRING ) );
1234 }
1235
1236 return 0;
1237 }
1238
1239 return nbAdded;
1240 }
1241
1242
1243
1244
1245
1246 @Override
1247 public void clear()
1248 {
1249 values.clear();
1250 }
1251
1252
1253
1254
1255
1256 @Override
1257 public boolean contains( Value... vals )
1258 {
1259 if ( isHR == null )
1260 {
1261
1262 return false;
1263 }
1264
1265 if ( attributeType == null )
1266 {
1267 if ( isHR )
1268 {
1269
1270
1271
1272 for ( Value val : vals )
1273 {
1274 if ( val.isHumanReadable() )
1275 {
1276 if ( !values.contains( val ) )
1277 {
1278 return false;
1279 }
1280 }
1281 else
1282 {
1283 byte[] binaryVal = val.getBytes();
1284
1285
1286 if ( !values.contains( new Value( Strings.utf8ToString( binaryVal ) ) ) )
1287 {
1288 return false;
1289 }
1290 }
1291 }
1292 }
1293 else
1294 {
1295
1296
1297
1298 for ( Value val : vals )
1299 {
1300 if ( val.isHumanReadable() )
1301 {
1302 String stringVal = val.getString();
1303
1304
1305 if ( !values.contains( new Value( Strings.getBytesUtf8( stringVal ) ) ) )
1306 {
1307 return false;
1308 }
1309 }
1310 else
1311 {
1312 if ( !values.contains( val ) )
1313 {
1314 return false;
1315 }
1316 }
1317 }
1318 }
1319 }
1320 else
1321 {
1322
1323
1324
1325 if ( isHR )
1326 {
1327 for ( Value val : vals )
1328 {
1329 if ( val.isHumanReadable() )
1330 {
1331 try
1332 {
1333 if ( val.getAttributeType() == null )
1334 {
1335 val = new Value( attributeType, val );
1336 }
1337 }
1338 catch ( LdapInvalidAttributeValueException liave )
1339 {
1340 return false;
1341 }
1342
1343 if ( !values.contains( val ) )
1344 {
1345 return false;
1346 }
1347 }
1348 else
1349 {
1350
1351 return false;
1352 }
1353 }
1354 }
1355 else
1356 {
1357 for ( Value val : vals )
1358 {
1359 if ( !val.isHumanReadable() )
1360 {
1361 if ( !values.contains( val ) )
1362 {
1363 return false;
1364 }
1365 }
1366 else
1367 {
1368
1369 return false;
1370 }
1371 }
1372 }
1373 }
1374
1375 return true;
1376 }
1377
1378
1379
1380
1381
1382 @Override
1383 public boolean contains( String... vals )
1384 {
1385 if ( isHR == null )
1386 {
1387
1388 return false;
1389 }
1390
1391 if ( attributeType == null )
1392 {
1393 if ( isHR )
1394 {
1395 for ( String val : vals )
1396 {
1397 try
1398 {
1399 if ( !contains( new Value( val ) ) )
1400 {
1401 return false;
1402 }
1403 }
1404 catch ( IllegalArgumentException iae )
1405 {
1406 return false;
1407 }
1408 }
1409 }
1410 else
1411 {
1412
1413
1414
1415
1416 for ( String val : vals )
1417 {
1418 byte[] binaryVal = Strings.getBytesUtf8( val );
1419
1420 if ( !contains( new Value( binaryVal ) ) )
1421 {
1422 return false;
1423 }
1424 }
1425 }
1426 }
1427 else
1428 {
1429 if ( isHR )
1430 {
1431
1432
1433 for ( String val : vals )
1434 {
1435 try
1436 {
1437 Value value = new Value( attributeType, val );
1438
1439 if ( !values.contains( value ) )
1440 {
1441 return false;
1442 }
1443 }
1444 catch ( LdapInvalidAttributeValueException liave )
1445 {
1446 return false;
1447 }
1448 }
1449
1450 return true;
1451 }
1452 else
1453 {
1454 return false;
1455 }
1456 }
1457
1458 return true;
1459 }
1460
1461
1462
1463
1464
1465 public boolean contains( byte[]... vals )
1466 {
1467 if ( isHR == null )
1468 {
1469
1470 return false;
1471 }
1472
1473 if ( attributeType == null )
1474 {
1475 if ( !isHR )
1476 {
1477
1478
1479 for ( byte[] val : vals )
1480 {
1481 if ( !contains( new Value( val ) ) )
1482 {
1483 return false;
1484 }
1485 }
1486 }
1487 else
1488 {
1489
1490
1491
1492
1493 for ( byte[] val : vals )
1494 {
1495 String stringVal = Strings.utf8ToString( val );
1496
1497 if ( !contains( new Value( stringVal ) ) )
1498 {
1499 return false;
1500 }
1501 }
1502 }
1503 }
1504 else
1505 {
1506 if ( !isHR )
1507 {
1508
1509
1510 for ( byte[] val : vals )
1511 {
1512 try
1513 {
1514 Value value = new Value( attributeType, val );
1515
1516 if ( !values.contains( value ) )
1517 {
1518 return false;
1519 }
1520 }
1521 catch ( LdapInvalidAttributeValueException liave )
1522 {
1523 return false;
1524 }
1525 }
1526
1527 return true;
1528 }
1529 else
1530 {
1531 return false;
1532 }
1533 }
1534
1535 return true;
1536 }
1537
1538
1539
1540
1541
1542 @Override
1543 public Value get()
1544 {
1545 if ( values.isEmpty() )
1546 {
1547 return null;
1548 }
1549
1550 return values.iterator().next();
1551 }
1552
1553
1554
1555
1556
1557 @Override
1558 public int size()
1559 {
1560 return values.size();
1561 }
1562
1563
1564
1565
1566
1567 @Override
1568 public boolean remove( Value... vals )
1569 {
1570 if ( ( isHR == null ) || ( values.isEmpty() ) )
1571 {
1572
1573 return false;
1574 }
1575
1576 boolean removed = true;
1577
1578 if ( attributeType == null )
1579 {
1580 if ( isHR )
1581 {
1582 for ( Value val : vals )
1583 {
1584 if ( val.isHumanReadable() )
1585 {
1586 removed &= values.remove( val );
1587 }
1588 else
1589 {
1590
1591 byte[] binaryVal = val.getBytes();
1592 removed &= values.remove( new Value( Strings.utf8ToString( binaryVal ) ) );
1593 }
1594 }
1595 }
1596 else
1597 {
1598 for ( Value val : vals )
1599 {
1600 removed &= values.remove( val );
1601 }
1602 }
1603 }
1604 else
1605 {
1606
1607
1608
1609 if ( isHR )
1610 {
1611 for ( Value val : vals )
1612 {
1613 if ( val.isHumanReadable() )
1614 {
1615 try
1616 {
1617 if ( val.getAttributeType() == null )
1618 {
1619 val = new Value( attributeType, val );
1620 }
1621
1622 removed &= values.remove( val );
1623 }
1624 catch ( LdapInvalidAttributeValueException liave )
1625 {
1626 removed = false;
1627 }
1628 }
1629 else
1630 {
1631 removed = false;
1632 }
1633 }
1634 }
1635 else
1636 {
1637 for ( Value val : vals )
1638 {
1639 if ( !val.isHumanReadable() )
1640 {
1641 try
1642 {
1643 if ( val.getAttributeType() == null )
1644 {
1645 val = new Value( attributeType, val );
1646 }
1647
1648 removed &= values.remove( val );
1649 }
1650 catch ( LdapInvalidAttributeValueException liave )
1651 {
1652 removed = false;
1653 }
1654 }
1655 else
1656 {
1657 removed = false;
1658 }
1659 }
1660 }
1661 }
1662
1663 return removed;
1664 }
1665
1666
1667
1668
1669
1670 public boolean remove( byte[]... vals )
1671 {
1672 if ( ( isHR == null ) || ( values.isEmpty() ) )
1673 {
1674
1675 return false;
1676 }
1677
1678 boolean removed = true;
1679
1680 if ( attributeType == null )
1681 {
1682 if ( !isHR )
1683 {
1684
1685 for ( byte[] val : vals )
1686 {
1687 Value value = new Value( val );
1688 removed &= values.remove( value );
1689 }
1690 }
1691 else
1692 {
1693
1694
1695 for ( byte[] val : vals )
1696 {
1697 Value value = new Value( Strings.utf8ToString( val ) );
1698 removed &= values.remove( value );
1699 }
1700 }
1701 }
1702 else
1703 {
1704 if ( !isHR )
1705 {
1706 try
1707 {
1708 for ( byte[] val : vals )
1709 {
1710 Value value = new Value( attributeType, val );
1711 removed &= values.remove( value );
1712 }
1713 }
1714 catch ( LdapInvalidAttributeValueException liave )
1715 {
1716 removed = false;
1717 }
1718 }
1719 else
1720 {
1721 removed = false;
1722 }
1723 }
1724
1725 return removed;
1726 }
1727
1728
1729
1730
1731
1732 @Override
1733 public boolean remove( String... vals )
1734 {
1735 if ( ( isHR == null ) || ( values.isEmpty() ) )
1736 {
1737
1738 return false;
1739 }
1740
1741 boolean removed = true;
1742
1743 if ( attributeType == null )
1744 {
1745 if ( isHR )
1746 {
1747
1748 for ( String val : vals )
1749 {
1750 Value value = new Value( val );
1751 removed &= values.remove( value );
1752 }
1753 }
1754 else
1755 {
1756
1757
1758 for ( String val : vals )
1759 {
1760 Value value = new Value( Strings.getBytesUtf8( val ) );
1761 removed &= values.remove( value );
1762 }
1763 }
1764 }
1765 else
1766 {
1767 if ( isHR )
1768 {
1769 for ( String val : vals )
1770 {
1771 try
1772 {
1773 Value value = new Value( attributeType, val );
1774 removed &= values.remove( value );
1775 }
1776 catch ( LdapInvalidAttributeValueException liave )
1777 {
1778 removed = false;
1779 }
1780 }
1781 }
1782 else
1783 {
1784 removed = false;
1785 }
1786 }
1787
1788 return removed;
1789 }
1790
1791
1792
1793
1794
1795
1796
1797 @Override
1798 public Iterator<Value> iterator()
1799 {
1800 return values.iterator();
1801 }
1802
1803
1804
1805
1806
1807 @Override
1808 public AttributeType getAttributeType()
1809 {
1810 return attributeType;
1811 }
1812
1813
1814
1815
1816
1817 @Override
1818 public void apply( AttributeType attributeType ) throws LdapInvalidAttributeValueException
1819 {
1820 if ( attributeType == null )
1821 {
1822 throw new IllegalArgumentException( I18n.err( I18n.ERR_13245_AT_PARAMETER_NULL ) );
1823 }
1824
1825 this.attributeType = attributeType;
1826 this.id = attributeType.getOid();
1827
1828 if ( Strings.isEmpty( this.upId ) )
1829 {
1830 this.upId = attributeType.getName();
1831 }
1832 else
1833 {
1834 if ( !areCompatible( this.upId, attributeType ) )
1835 {
1836 this.upId = attributeType.getName();
1837 }
1838 }
1839
1840 if ( values != null )
1841 {
1842 Set<Value> newValues = new LinkedHashSet<>( values.size() );
1843
1844 for ( Value value : values )
1845 {
1846 if ( value.isSchemaAware() )
1847 {
1848 newValues.add( value );
1849 }
1850 else
1851 {
1852 if ( value.isHumanReadable() )
1853 {
1854 newValues.add( new Value( attributeType, value.getString() ) );
1855 }
1856 else
1857 {
1858 newValues.add( new Value( attributeType, value.getBytes() ) );
1859 }
1860 }
1861 }
1862
1863 values = newValues;
1864 }
1865
1866 isHR = attributeType.getSyntax().isHumanReadable();
1867
1868
1869 rehash();
1870 }
1871
1872
1873
1874
1875
1876 @Override
1877 public boolean isInstanceOf( AttributeType attributeType ) throws LdapInvalidAttributeValueException
1878 {
1879 return ( attributeType != null )
1880 && ( this.attributeType.equals( attributeType ) || this.attributeType.isDescendantOf( attributeType ) );
1881 }
1882
1883
1884
1885
1886
1887
1888
1889
1890 private void rehash()
1891 {
1892 int hTmp = 37;
1893
1894 if ( isHR != null )
1895 {
1896 hTmp = hTmp * 17 + isHR.hashCode();
1897 }
1898
1899 if ( id != null )
1900 {
1901 hTmp = hTmp * 17 + id.hashCode();
1902 }
1903
1904 if ( attributeType != null )
1905 {
1906 hTmp = hTmp * 17 + attributeType.hashCode();
1907 }
1908
1909 h = hTmp;
1910 }
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920 @Override
1921 public int hashCode()
1922 {
1923 if ( h == 0 )
1924 {
1925 rehash();
1926 }
1927
1928 return h;
1929 }
1930
1931
1932
1933
1934
1935 @Override
1936 public boolean equals( Object obj )
1937 {
1938 if ( obj == this )
1939 {
1940 return true;
1941 }
1942
1943 if ( !( obj instanceof Attribute ) )
1944 {
1945 return false;
1946 }
1947
1948 Attribute other = ( Attribute ) obj;
1949
1950 if ( id == null )
1951 {
1952 if ( other.getId() != null )
1953 {
1954 return false;
1955 }
1956 }
1957 else
1958 {
1959 if ( other.getId() == null )
1960 {
1961 return false;
1962 }
1963 else
1964 {
1965 if ( attributeType != null )
1966 {
1967 if ( !attributeType.equals( other.getAttributeType() ) )
1968 {
1969 return false;
1970 }
1971 }
1972 else if ( !id.equals( other.getId() ) )
1973 {
1974 return false;
1975 }
1976 }
1977 }
1978
1979 if ( isHumanReadable() != other.isHumanReadable() )
1980 {
1981 return false;
1982 }
1983
1984 if ( values.size() != other.size() )
1985 {
1986 return false;
1987 }
1988
1989 for ( Value val : values )
1990 {
1991 if ( !other.contains( val ) )
1992 {
1993 return false;
1994 }
1995 }
1996
1997 if ( attributeType == null )
1998 {
1999 return other.getAttributeType() == null;
2000 }
2001
2002 return attributeType.equals( other.getAttributeType() );
2003 }
2004
2005
2006
2007
2008
2009 @Override
2010 public Attribute clone()
2011 {
2012 try
2013 {
2014 DefaultAttribute attribute = ( DefaultAttribute ) super.clone();
2015
2016 if ( this.attributeType != null )
2017 {
2018 attribute.id = attributeType.getOid();
2019 attribute.attributeType = attributeType;
2020 }
2021
2022 attribute.values = new LinkedHashSet<>( values.size() );
2023
2024 for ( Value value : values )
2025 {
2026
2027 attribute.values.add( value );
2028 }
2029
2030 return attribute;
2031 }
2032 catch ( CloneNotSupportedException cnse )
2033 {
2034 return null;
2035 }
2036 }
2037
2038
2039
2040
2041
2042
2043
2044
2045 @Override
2046 public void writeExternal( ObjectOutput out ) throws IOException
2047 {
2048
2049 out.writeUTF( upId );
2050
2051
2052 out.writeUTF( id );
2053
2054
2055 if ( isHR != null )
2056 {
2057 out.writeBoolean( true );
2058 out.writeBoolean( isHR );
2059 }
2060 else
2061 {
2062 out.writeBoolean( false );
2063 }
2064
2065
2066 out.writeInt( size() );
2067
2068 if ( size() > 0 )
2069 {
2070
2071 for ( Value value : values )
2072 {
2073
2074 value.writeExternal( out );
2075 }
2076 }
2077
2078 out.flush();
2079 }
2080
2081
2082
2083
2084
2085 @Override
2086 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
2087 {
2088
2089 upId = in.readUTF();
2090
2091
2092 id = in.readUTF();
2093
2094
2095 if ( in.readBoolean() )
2096 {
2097 isHR = in.readBoolean();
2098 }
2099
2100
2101 int nbValues = in.readInt();
2102
2103 if ( nbValues > 0 )
2104 {
2105 for ( int i = 0; i < nbValues; i++ )
2106 {
2107 Value value = new Value( attributeType );
2108
2109 value.readExternal( in );
2110
2111 values.add( value );
2112 }
2113 }
2114 }
2115
2116
2117
2118
2119
2120 @Override
2121 public String toString()
2122 {
2123 return toString( "" );
2124 }
2125
2126
2127
2128
2129
2130 @Override
2131 public String toString( String tabs )
2132 {
2133 StringBuilder sb = new StringBuilder();
2134
2135 if ( ( values != null ) && ( !values.isEmpty() ) )
2136 {
2137 boolean isFirst = true;
2138
2139 for ( Value value : values )
2140 {
2141 if ( isFirst )
2142 {
2143 isFirst = false;
2144 }
2145 else
2146 {
2147 sb.append( '\n' );
2148 }
2149
2150 sb.append( tabs ).append( upId ).append( ": " );
2151
2152 if ( value.isNull() )
2153 {
2154 sb.append( "''" );
2155 }
2156 else
2157 {
2158 sb.append( value );
2159 }
2160 }
2161 }
2162 else
2163 {
2164 sb.append( tabs ).append( upId ).append( ": (null)" );
2165 }
2166
2167 return sb.toString();
2168 }
2169 }