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