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.Comparator;
26
27 import org.apache.directory.api.i18n.I18n;
28 import org.apache.directory.api.ldap.model.exception.LdapException;
29 import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
30 import org.apache.directory.api.ldap.model.schema.AttributeType;
31 import org.apache.directory.api.ldap.model.schema.MatchingRule;
32 import org.apache.directory.api.ldap.model.schema.Normalizer;
33 import org.apache.directory.api.util.Serialize;
34 import org.apache.directory.api.util.Strings;
35 import org.apache.directory.api.util.exception.NotImplementedException;
36
37
38
39
40
41
42
43
44
45
46 public class StringValue extends AbstractValue<String>
47 {
48
49 private static final long serialVersionUID = 2L;
50
51
52 private byte[] bytes;
53
54
55
56
57
58
59
60
61
62
63 public StringValue( AttributeType attributeType )
64 {
65 if ( attributeType != null )
66 {
67
68 if ( attributeType.getSyntax() == null )
69 {
70 throw new IllegalArgumentException( I18n.err( I18n.ERR_04445 ) );
71 }
72
73 if ( !attributeType.getSyntax().isHumanReadable() )
74 {
75 LOG.warn( "Treating a value of a binary attribute {} as a String: "
76 + "\nthis could cause data corruption!", attributeType.getName() );
77 }
78
79 this.attributeType = attributeType;
80 }
81 }
82
83
84
85
86
87
88
89 public StringValue( String value )
90 {
91 this.wrappedValue = value;
92 this.normalizedValue = value;
93 bytes = Strings.getBytesUtf8( value );
94 }
95
96
97
98
99
100
101
102
103
104
105 public StringValue( AttributeType attributeType, String value ) throws LdapInvalidAttributeValueException
106 {
107 this( value );
108 apply( attributeType );
109 }
110
111
112
113
114
115
116
117
118 public String getValue()
119 {
120
121
122 return wrappedValue;
123 }
124
125
126
127
128
129 public String getNormValue()
130 {
131 return normalizedValue;
132 }
133
134
135
136
137
138
139
140
141
142
143 public int compareTo( Value<String> value )
144 {
145 if ( isNull() )
146 {
147 if ( ( value == null ) || value.isNull() )
148 {
149 return 0;
150 }
151 else
152 {
153 return -1;
154 }
155 }
156 else if ( ( value == null ) || value.isNull() )
157 {
158 return 1;
159 }
160
161 if ( !( value instanceof StringValue ) )
162 {
163 String message = I18n.err( I18n.ERR_04128, toString(), value.getClass() );
164 LOG.error( message );
165 throw new NotImplementedException( message );
166 }
167
168 StringValue stringValue = ( StringValue ) value;
169
170 if ( attributeType != null )
171 {
172 if ( stringValue.getAttributeType() == null )
173 {
174 return getNormValue().compareTo( stringValue.getNormValue() );
175 }
176 else
177 {
178 if ( !attributeType.equals( stringValue.getAttributeType() ) )
179 {
180 String message = I18n.err( I18n.ERR_04128, toString(), value.getClass() );
181 LOG.error( message );
182 throw new NotImplementedException( message );
183 }
184 }
185 }
186 else
187 {
188 return getNormValue().compareTo( stringValue.getNormValue() );
189 }
190
191 try
192 {
193 return getLdapComparator().compare( getNormValue(), stringValue.getNormValue() );
194 }
195 catch ( LdapException e )
196 {
197 String msg = I18n.err( I18n.ERR_04443, this, value );
198 LOG.error( msg, e );
199 throw new IllegalStateException( msg, e );
200 }
201 }
202
203
204
205
206
207
208
209
210 public StringValue clone()
211 {
212 return ( StringValue ) super.clone();
213 }
214
215
216
217
218
219
220
221
222
223 public int hashCode()
224 {
225 if ( h == 0 )
226 {
227
228
229 if ( isNull() )
230 {
231 return 0;
232 }
233
234
235
236
237
238 String normalized = getNormValue();
239
240 if ( normalized != null )
241 {
242 h = normalized.hashCode();
243 }
244 else
245 {
246 h = 17;
247 }
248 }
249
250 return h;
251 }
252
253
254
255
256
257
258
259 public boolean equals( Object obj )
260 {
261 if ( this == obj )
262 {
263 return true;
264 }
265
266 if ( !( obj instanceof StringValue ) )
267 {
268 return false;
269 }
270
271 StringValue other = ( StringValue ) obj;
272
273
274 if ( attributeType != null )
275 {
276
277 if ( other.attributeType != null )
278 {
279 if ( attributeType.getOid().equals( other.getAttributeType().getOid() ) )
280 {
281
282
283
284
285 if ( isNull() )
286 {
287 return other.isNull();
288 }
289
290
291
292 if ( wrappedValue.equals( other.wrappedValue ) )
293 {
294 return true;
295 }
296
297
298 try
299 {
300 Comparator<String> comparator = getLdapComparator();
301
302
303 if ( comparator == null )
304 {
305 return getNormReference().equals( other.getNormReference() );
306 }
307 else
308 {
309 return comparator.compare( getNormReference(), other.getNormReference() ) == 0;
310 }
311 }
312 catch ( LdapException ne )
313 {
314 return false;
315 }
316 }
317 else
318 {
319
320 return false;
321 }
322 }
323 else
324 {
325
326
327
328 if ( isNull() )
329 {
330 return other.isNull();
331 }
332
333
334 try
335 {
336 Comparator<String> comparator = getLdapComparator();
337
338
339
340 MatchingRule equality = getAttributeType().getEquality();
341
342 if ( equality == null )
343 {
344
345 return getNormReference().equals( other.getNormReference() );
346 }
347
348 Normalizer normalizer = equality.getNormalizer();
349
350 StringValue otherValue = ( StringValue ) normalizer.normalize( other );
351
352 if ( comparator == null )
353 {
354 return getNormReference().equals( otherValue.getNormReference() );
355 }
356 else
357 {
358 return comparator.compare( getNormReference(), otherValue.getNormReference() ) == 0;
359 }
360 }
361 catch ( LdapException ne )
362 {
363 return false;
364 }
365 }
366 }
367 else
368 {
369
370 if ( other.attributeType != null )
371 {
372
373
374
375 if ( isNull() )
376 {
377 return other.isNull();
378 }
379
380 try
381 {
382 Comparator<String> comparator = other.getLdapComparator();
383
384
385
386 MatchingRule equality = other.getAttributeType().getEquality();
387
388 if ( equality == null )
389 {
390
391 return getNormReference().equals( other.getNormReference() );
392 }
393
394 Normalizer normalizer = equality.getNormalizer();
395
396 StringValue thisValue = ( StringValue ) normalizer.normalize( this );
397
398 if ( comparator == null )
399 {
400 return thisValue.getNormReference().equals( other.getNormReference() );
401 }
402 else
403 {
404 return comparator.compare( thisValue.getNormReference(), other.getNormReference() ) == 0;
405 }
406 }
407 catch ( LdapException ne )
408 {
409 return false;
410 }
411 }
412 else
413 {
414
415 if ( isNull() )
416 {
417 return other.isNull();
418 }
419
420
421 return getNormReference().equals( other.getNormReference() );
422 }
423 }
424 }
425
426
427
428
429
430 public boolean isHumanReadable()
431 {
432 return true;
433 }
434
435
436
437
438
439 public int length()
440 {
441 return wrappedValue != null ? wrappedValue.length() : 0;
442 }
443
444
445
446
447
448
449 public byte[] getBytes()
450 {
451 return bytes;
452 }
453
454
455
456
457
458
459
460 public String getString()
461 {
462 return wrappedValue != null ? wrappedValue : "";
463 }
464
465
466
467
468
469
470
471
472
473
474 public static StringValue deserialize( ObjectInput in ) throws IOException, ClassNotFoundException
475 {
476 StringValue value = new StringValue( ( AttributeType ) null );
477 value.readExternal( in );
478
479 return value;
480 }
481
482
483
484
485
486
487
488
489
490
491
492 public static StringValue deserialize( AttributeType attributeType, ObjectInput in ) throws IOException,
493 ClassNotFoundException
494 {
495 StringValue value = new StringValue( attributeType );
496 value.readExternal( in );
497
498 return value;
499 }
500
501
502
503
504
505 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException
506 {
507
508 boolean isHR = in.readBoolean();
509
510 if ( !isHR )
511 {
512 throw new IOException( "The serialized value is not a String value" );
513 }
514
515
516 if ( in.readBoolean() )
517 {
518 wrappedValue = in.readUTF();
519 bytes = Strings.getBytesUtf8( wrappedValue );
520 }
521
522
523 boolean normalized = in.readBoolean();
524
525 if ( normalized )
526 {
527
528 if ( in.readBoolean() )
529 {
530 normalizedValue = in.readUTF();
531 }
532 }
533 else
534 {
535 if ( attributeType != null )
536 {
537 try
538 {
539 MatchingRule equality = attributeType.getEquality();
540
541 if ( equality == null )
542 {
543 normalizedValue = wrappedValue;
544 }
545 else
546 {
547 Normalizer normalizer = equality.getNormalizer();
548
549 if ( normalizer != null )
550 {
551 normalizedValue = normalizer.normalize( wrappedValue );
552 }
553 else
554 {
555 normalizedValue = wrappedValue;
556 }
557 }
558 }
559 catch ( LdapException le )
560 {
561 normalizedValue = wrappedValue;
562 }
563 }
564 else
565 {
566 normalizedValue = wrappedValue;
567 }
568 }
569
570
571 h = in.readInt();
572 }
573
574
575
576
577
578
579
580
581
582 public int serialize( byte[] buffer, int pos )
583 {
584
585 int length = 1 + 1 + 1 + 4;
586
587
588 byte[] wrappedValueBytes = null;
589 byte[] normalizedValueBytes = null;
590
591 if ( wrappedValue != null )
592 {
593 wrappedValueBytes = Strings.getBytesUtf8( wrappedValue );
594 length += 4 + wrappedValueBytes.length;
595 }
596
597 if ( attributeType != null )
598 {
599 if ( normalizedValue != null )
600 {
601 normalizedValueBytes = Strings.getBytesUtf8( normalizedValue );
602 length += 1 + 4 + normalizedValueBytes.length;
603 }
604 else
605 {
606 length += 1;
607 }
608 }
609
610
611 if ( buffer.length - pos < length )
612 {
613 throw new ArrayIndexOutOfBoundsException();
614 }
615
616
617 buffer[pos] = Serialize.TRUE;
618 pos++;
619
620
621 if ( wrappedValue != null )
622 {
623 buffer[pos++] = Serialize.TRUE;
624 pos = Serialize.serialize( wrappedValueBytes, buffer, pos );
625 }
626 else
627 {
628 buffer[pos++] = Serialize.FALSE;
629 }
630
631
632 if ( attributeType != null )
633 {
634
635
636
637 buffer[pos++] = Serialize.TRUE;
638
639
640 if ( normalizedValue != null )
641 {
642 buffer[pos++] = Serialize.TRUE;
643 pos = Serialize.serialize( normalizedValueBytes, buffer, pos );
644 }
645 else
646 {
647 buffer[pos++] = Serialize.FALSE;
648 }
649 }
650 else
651 {
652
653 buffer[pos++] = Serialize.FALSE;
654 }
655
656
657 pos = Serialize.serialize( h, buffer, pos );
658
659 return pos;
660 }
661
662
663
664
665
666
667
668
669
670
671 public int deserialize( byte[] buffer, int pos ) throws IOException
672 {
673 if ( ( pos < 0 ) || ( pos >= buffer.length ) )
674 {
675 throw new ArrayIndexOutOfBoundsException();
676 }
677
678
679 boolean isHR = Serialize.deserializeBoolean( buffer, pos );
680 pos++;
681
682 if ( !isHR )
683 {
684 throw new IOException( "The serialized value is not a String value" );
685 }
686
687
688 boolean hasWrappedValue = Serialize.deserializeBoolean( buffer, pos );
689 pos++;
690
691 if ( hasWrappedValue )
692 {
693 byte[] wrappedValueBytes = Serialize.deserializeBytes( buffer, pos );
694 pos += 4 + wrappedValueBytes.length;
695 wrappedValue = Strings.utf8ToString( wrappedValueBytes );
696 }
697
698
699 boolean hasAttributeType = Serialize.deserializeBoolean( buffer, pos );
700 pos++;
701
702 if ( hasAttributeType )
703 {
704
705 boolean hasNormalizedValue = Serialize.deserializeBoolean( buffer, pos );
706 pos++;
707
708 if ( hasNormalizedValue )
709 {
710 byte[] normalizedValueBytes = Serialize.deserializeBytes( buffer, pos );
711 pos += 4 + normalizedValueBytes.length;
712 normalizedValue = Strings.utf8ToString( normalizedValueBytes );
713 }
714 }
715 else
716 {
717 if ( attributeType != null )
718 {
719 try
720 {
721 MatchingRule equality = attributeType.getEquality();
722
723 if ( equality == null )
724 {
725 normalizedValue = wrappedValue;
726 }
727 else
728 {
729 Normalizer normalizer = equality.getNormalizer();
730
731 if ( normalizer != null )
732 {
733 normalizedValue = normalizer.normalize( wrappedValue );
734 }
735 else
736 {
737 normalizedValue = wrappedValue;
738 }
739 }
740 }
741 catch ( LdapException le )
742 {
743 normalizedValue = wrappedValue;
744 }
745 }
746 else
747 {
748 normalizedValue = wrappedValue;
749 }
750 }
751
752
753 h = Serialize.deserializeInt( buffer, pos );
754 pos += 4;
755
756 return pos;
757 }
758
759
760
761
762
763 public void writeExternal( ObjectOutput out ) throws IOException
764 {
765
766 out.writeBoolean( STRING );
767
768
769 if ( wrappedValue != null )
770 {
771 out.writeBoolean( true );
772 out.writeUTF( wrappedValue );
773 }
774 else
775 {
776 out.writeBoolean( false );
777 }
778
779
780 if ( attributeType != null )
781 {
782
783
784 out.writeBoolean( true );
785
786
787 if ( normalizedValue != null )
788 {
789 out.writeBoolean( true );
790 out.writeUTF( normalizedValue );
791 }
792 else
793 {
794 out.writeBoolean( false );
795 }
796 }
797 else
798 {
799
800 out.writeBoolean( false );
801 }
802
803
804 out.writeInt( h );
805
806
807 out.flush();
808 }
809
810
811
812
813
814 public String toString()
815 {
816 return wrappedValue == null ? "null" : wrappedValue;
817 }
818 }