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