001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.util;
021
022
023 import java.lang.reflect.AccessibleObject;
024 import java.lang.reflect.Field;
025 import java.lang.reflect.Modifier;
026
027
028 /**
029 * <p>
030 * Assists in implementing {@link Object#hashCode()} methods.
031 * </p>
032 * <p>
033 * This class enables a good <code>hashCode</code> method to be built for any
034 * class. It follows the rules laid out in the book <a
035 * href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
036 * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually
037 * quite difficult. This class aims to simplify the process.
038 * </p>
039 * <p>
040 * All relevant fields from the object should be included in the
041 * <code>hashCode</code> method. Derived fields may be excluded. In general,
042 * any field used in the <code>equals</code> method must be used in the
043 * <code>hashCode</code> method.
044 * </p>
045 * <p>
046 * To use this class write code as follows:
047 * </p>
048 *
049 * <pre>
050 * public class Person {
051 * String name;
052 * int age;
053 * boolean isSmoker;
054 * ...
055 *
056 * public int hashCode() {
057 * // you pick a hard-coded, randomly chosen, non-zero, odd number
058 * // ideally different for each class
059 * return new HashCodeBuilder(17, 37).
060 * append(name).
061 * append(age).
062 * append(smoker).
063 * toHashCode();
064 * }
065 * }
066 * </pre>
067 *
068 * <p>
069 * If required, the superclass <code>hashCode()</code> can be added using
070 * {@link #appendSuper}.
071 * </p>
072 * <p>
073 * Alternatively, there is a method that uses reflection to determine the fields
074 * to test. Because these fields are usually private, the method,
075 * <code>reflectionHashCode</code>, uses
076 * <code>AccessibleObject.setAccessible</code> to change the visibility of the
077 * fields. This will fail under a security manager, unless the appropriate
078 * permissions are set up correctly. It is also slower than testing explicitly.
079 * </p>
080 * <p>
081 * A typical invocation for this method would look like:
082 * </p>
083 *
084 * <pre>
085 * public int hashCode()
086 * {
087 * return HashCodeBuilder.reflectionHashCode( this );
088 * }
089 * </pre>
090 *
091 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
092 */
093 public class HashCodeBuilder
094 {
095
096 /**
097 * Constant to use in building the hashCode.
098 */
099 private final int iConstant;
100
101 /**
102 * Running total of the hashCode.
103 */
104 private int iTotal = 0;
105
106
107 /**
108 * <p>
109 * Constructor.
110 * </p>
111 * <p>
112 * This constructor uses two hard coded choices for the constants needed to
113 * build a <code>hashCode</code>.
114 * </p>
115 */
116 public HashCodeBuilder()
117 {
118 super();
119 iConstant = 37;
120 iTotal = 17;
121 }
122
123
124 /**
125 * <p>
126 * Constructor.
127 * </p>
128 * <p>
129 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
130 * these should be different for each class, however this is not vital.
131 * </p>
132 * <p>
133 * Prime numbers are preferred, especially for the multiplier.
134 * </p>
135 *
136 * @param initialNonZeroOddNumber
137 * a non-zero, odd number used as the initial value
138 * @param multiplierNonZeroOddNumber
139 * a non-zero, odd number used as the multiplier
140 * @throws IllegalArgumentException
141 * if the number is zero or even
142 */
143 public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber)
144 {
145 super();
146 if ( initialNonZeroOddNumber == 0 )
147 {
148 throw new IllegalArgumentException( "HashCodeBuilder requires a non zero initial value" );
149 }
150 if ( initialNonZeroOddNumber % 2 == 0 )
151 {
152 throw new IllegalArgumentException( "HashCodeBuilder requires an odd initial value" );
153 }
154 if ( multiplierNonZeroOddNumber == 0 )
155 {
156 throw new IllegalArgumentException( "HashCodeBuilder requires a non zero multiplier" );
157 }
158 if ( multiplierNonZeroOddNumber % 2 == 0 )
159 {
160 throw new IllegalArgumentException( "HashCodeBuilder requires an odd multiplier" );
161 }
162 iConstant = multiplierNonZeroOddNumber;
163 iTotal = initialNonZeroOddNumber;
164 }
165
166
167 // -------------------------------------------------------------------------
168
169 /**
170 * <p>
171 * This method uses reflection to build a valid hash code.
172 * </p>
173 * <p>
174 * This constructor uses two hard coded choices for the constants needed to
175 * build a hash code.
176 * </p>
177 * <p>
178 * It uses <code>AccessibleObject.setAccessible</code> to gain access to
179 * private fields. This means that it will throw a security exception if run
180 * under a security manager, if the permissions are not set up correctly. It
181 * is also not as efficient as testing explicitly.
182 * </p>
183 * <p>
184 * Transient members will be not be used, as they are likely derived fields,
185 * and not part of the value of the <code>Object</code>.
186 * </p>
187 * <p>
188 * Static fields will not be tested. Superclass fields will be included.
189 * </p>
190 *
191 * @param object
192 * the Object to create a <code>hashCode</code> for
193 * @return int hash code
194 * @throws IllegalArgumentException
195 * if the object is <code>null</code>
196 */
197 public static int reflectionHashCode( Object object )
198 {
199 return reflectionHashCode( 17, 37, object, false, null );
200 }
201
202
203 /**
204 * <p>
205 * This method uses reflection to build a valid hash code.
206 * </p>
207 * <p>
208 * This constructor uses two hard coded choices for the constants needed to
209 * build a hash code.
210 * </p>
211 * <p>
212 * It uses <code>AccessibleObject.setAccessible</code> to gain access to
213 * private fields. This means that it will throw a security exception if run
214 * under a security manager, if the permissions are not set up correctly. It
215 * is also not as efficient as testing explicitly.
216 * </p>
217 * <P>
218 * If the TestTransients parameter is set to <code>true</code>, transient
219 * members will be tested, otherwise they are ignored, as they are likely
220 * derived fields, and not part of the value of the <code>Object</code>.
221 * </p>
222 * <p>
223 * Static fields will not be tested. Superclass fields will be included.
224 * </p>
225 *
226 * @param object
227 * the Object to create a <code>hashCode</code> for
228 * @param testTransients
229 * whether to include transient fields
230 * @return int hash code
231 * @throws IllegalArgumentException
232 * if the object is <code>null</code>
233 */
234 public static int reflectionHashCode( Object object, boolean testTransients )
235 {
236 return reflectionHashCode( 17, 37, object, testTransients, null );
237 }
238
239
240 /**
241 * <p>
242 * This method uses reflection to build a valid hash code.
243 * </p>
244 * <p>
245 * It uses <code>AccessibleObject.setAccessible</code> to gain access to
246 * private fields. This means that it will throw a security exception if run
247 * under a security manager, if the permissions are not set up correctly. It
248 * is also not as efficient as testing explicitly.
249 * </p>
250 * <p>
251 * Transient members will be not be used, as they are likely derived fields,
252 * and not part of the value of the <code>Object</code>.
253 * </p>
254 * <p>
255 * Static fields will not be tested. Superclass fields will be included.
256 * </p>
257 * <p>
258 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
259 * these should be different for each class, however this is not vital.
260 * Prime numbers are preferred, especially for the multiplier.
261 * </p>
262 *
263 * @param initialNonZeroOddNumber
264 * a non-zero, odd number used as the initial value
265 * @param multiplierNonZeroOddNumber
266 * a non-zero, odd number used as the multiplier
267 * @param object
268 * the Object to create a <code>hashCode</code> for
269 * @return int hash code
270 * @throws IllegalArgumentException
271 * if the Object is <code>null</code>
272 * @throws IllegalArgumentException
273 * if the number is zero or even
274 */
275 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object )
276 {
277 return reflectionHashCode( initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null );
278 }
279
280
281 /**
282 * <p>
283 * This method uses reflection to build a valid hash code.
284 * </p>
285 * <p>
286 * It uses <code>AccessibleObject.setAccessible</code> to gain access to
287 * private fields. This means that it will throw a security exception if run
288 * under a security manager, if the permissions are not set up correctly. It
289 * is also not as efficient as testing explicitly.
290 * </p>
291 * <p>
292 * If the TestTransients parameter is set to <code>true</code>, transient
293 * members will be tested, otherwise they are ignored, as they are likely
294 * derived fields, and not part of the value of the <code>Object</code>.
295 * </p>
296 * <p>
297 * Static fields will not be tested. Superclass fields will be included.
298 * </p>
299 * <p>
300 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
301 * these should be different for each class, however this is not vital.
302 * Prime numbers are preferred, especially for the multiplier.
303 * </p>
304 *
305 * @param initialNonZeroOddNumber
306 * a non-zero, odd number used as the initial value
307 * @param multiplierNonZeroOddNumber
308 * a non-zero, odd number used as the multiplier
309 * @param object
310 * the Object to create a <code>hashCode</code> for
311 * @param testTransients
312 * whether to include transient fields
313 * @return int hash code
314 * @throws IllegalArgumentException
315 * if the Object is <code>null</code>
316 * @throws IllegalArgumentException
317 * if the number is zero or even
318 */
319 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
320 boolean testTransients )
321 {
322 return reflectionHashCode( initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null );
323 }
324
325
326 /**
327 * <p>
328 * This method uses reflection to build a valid hash code.
329 * </p>
330 * <p>
331 * It uses <code>AccessibleObject.setAccessible</code> to gain access to
332 * private fields. This means that it will throw a security exception if run
333 * under a security manager, if the permissions are not set up correctly. It
334 * is also not as efficient as testing explicitly.
335 * </p>
336 * <p>
337 * If the TestTransients parameter is set to <code>true</code>, transient
338 * members will be tested, otherwise they are ignored, as they are likely
339 * derived fields, and not part of the value of the <code>Object</code>.
340 * </p>
341 * <p>
342 * Static fields will not be included. Superclass fields will be included up
343 * to and including the specified superclass. A null superclass is treated
344 * as java.lang.Object.
345 * </p>
346 * <p>
347 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
348 * these should be different for each class, however this is not vital.
349 * Prime numbers are preferred, especially for the multiplier.
350 * </p>
351 *
352 * @param initialNonZeroOddNumber
353 * a non-zero, odd number used as the initial value
354 * @param multiplierNonZeroOddNumber
355 * a non-zero, odd number used as the multiplier
356 * @param object
357 * the Object to create a <code>hashCode</code> for
358 * @param testTransients
359 * whether to include transient fields
360 * @param reflectUpToClass
361 * the superclass to reflect up to (inclusive), may be
362 * <code>null</code>
363 * @return int hash code
364 * @throws IllegalArgumentException
365 * if the Object is <code>null</code>
366 * @throws IllegalArgumentException
367 * if the number is zero or even
368 * @since 2.0
369 */
370 public static int reflectionHashCode( int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
371 boolean testTransients, Class reflectUpToClass )
372 {
373
374 if ( object == null )
375 {
376 throw new IllegalArgumentException( "The object to build a hash code for must not be null" );
377 }
378 HashCodeBuilder builder = new HashCodeBuilder( initialNonZeroOddNumber, multiplierNonZeroOddNumber );
379 Class clazz = object.getClass();
380 reflectionAppend( object, clazz, builder, testTransients );
381 while ( clazz.getSuperclass() != null && clazz != reflectUpToClass )
382 {
383 clazz = clazz.getSuperclass();
384 reflectionAppend( object, clazz, builder, testTransients );
385 }
386 return builder.toHashCode();
387 }
388
389
390 /**
391 * <p>
392 * Appends the fields and values defined by the given object of the given
393 * <code>Class</code>.
394 * </p>
395 *
396 * @param object
397 * the object to append details of
398 * @param clazz
399 * the class to append details of
400 * @param builder
401 * the builder to append to
402 * @param useTransients
403 * whether to use transient fields
404 */
405 private static void reflectionAppend( Object object, Class clazz, HashCodeBuilder builder, boolean useTransients )
406 {
407 Field[] fields = clazz.getDeclaredFields();
408 AccessibleObject.setAccessible( fields, true );
409 for ( int i = 0; i < fields.length; i++ )
410 {
411 Field f = fields[i];
412 if ( ( f.getName().indexOf( '$' ) == -1 ) && ( useTransients || !Modifier.isTransient( f.getModifiers() ) )
413 && ( !Modifier.isStatic( f.getModifiers() ) ) )
414 {
415 try
416 {
417 builder.append( f.get( object ) );
418 }
419 catch ( IllegalAccessException e )
420 {
421 // this can't happen. Would get a Security exception instead
422 // throw a runtime exception in case the impossible happens.
423 throw new InternalError( "Unexpected IllegalAccessException" );
424 }
425 }
426 }
427 }
428
429
430 // -------------------------------------------------------------------------
431
432 /**
433 * <p>
434 * Adds the result of super.hashCode() to this builder.
435 * </p>
436 *
437 * @param superHashCode
438 * the result of calling <code>super.hashCode()</code>
439 * @return this HashCodeBuilder, used to chain calls.
440 * @since 2.0
441 */
442 public HashCodeBuilder appendSuper( int superHashCode )
443 {
444 iTotal = iTotal * iConstant + superHashCode;
445 return this;
446 }
447
448
449 // -------------------------------------------------------------------------
450
451 /**
452 * <p>
453 * Append a <code>hashCode</code> for an <code>Object</code>.
454 * </p>
455 *
456 * @param object
457 * the Object to add to the <code>hashCode</code>
458 * @return this
459 */
460 public HashCodeBuilder append( Object object )
461 {
462 if ( object == null )
463 {
464 iTotal = iTotal * iConstant;
465
466 }
467 else
468 {
469 if ( object.getClass().isArray() == false )
470 {
471 // the simple case, not an array, just the element
472 iTotal = iTotal * iConstant + object.hashCode();
473
474 }
475 else
476 {
477 // 'Switch' on type of array, to dispatch to the correct handler
478 // This handles multi dimensional arrays
479 if ( object instanceof long[] )
480 {
481 append( ( long[] ) object );
482 }
483 else if ( object instanceof int[] )
484 {
485 append( ( int[] ) object );
486 }
487 else if ( object instanceof short[] )
488 {
489 append( ( short[] ) object );
490 }
491 else if ( object instanceof char[] )
492 {
493 append( ( char[] ) object );
494 }
495 else if ( object instanceof byte[] )
496 {
497 append( ( byte[] ) object );
498 }
499 else if ( object instanceof double[] )
500 {
501 append( ( double[] ) object );
502 }
503 else if ( object instanceof float[] )
504 {
505 append( ( float[] ) object );
506 }
507 else if ( object instanceof boolean[] )
508 {
509 append( ( boolean[] ) object );
510 }
511 else
512 {
513 // Not an array of primitives
514 append( ( Object[] ) object );
515 }
516 }
517 }
518 return this;
519 }
520
521
522 /**
523 * <p>
524 * Append a <code>hashCode</code> for a <code>long</code>.
525 * </p>
526 *
527 * @param value
528 * the long to add to the <code>hashCode</code>
529 * @return this
530 */
531 public HashCodeBuilder append( long value )
532 {
533 iTotal = iTotal * iConstant + ( ( int ) ( value ^ ( value >> 32 ) ) );
534 return this;
535 }
536
537
538 /**
539 * <p>
540 * Append a <code>hashCode</code> for an <code>int</code>.
541 * </p>
542 *
543 * @param value
544 * the int to add to the <code>hashCode</code>
545 * @return this
546 */
547 public HashCodeBuilder append( int value )
548 {
549 iTotal = iTotal * iConstant + value;
550 return this;
551 }
552
553
554 /**
555 * <p>
556 * Append a <code>hashCode</code> for a <code>short</code>.
557 * </p>
558 *
559 * @param value
560 * the short to add to the <code>hashCode</code>
561 * @return this
562 */
563 public HashCodeBuilder append( short value )
564 {
565 iTotal = iTotal * iConstant + value;
566 return this;
567 }
568
569
570 /**
571 * <p>
572 * Append a <code>hashCode</code> for a <code>char</code>.
573 * </p>
574 *
575 * @param value
576 * the char to add to the <code>hashCode</code>
577 * @return this
578 */
579 public HashCodeBuilder append( char value )
580 {
581 iTotal = iTotal * iConstant + value;
582 return this;
583 }
584
585
586 /**
587 * <p>
588 * Append a <code>hashCode</code> for a <code>byte</code>.
589 * </p>
590 *
591 * @param value
592 * the byte to add to the <code>hashCode</code>
593 * @return this
594 */
595 public HashCodeBuilder append( byte value )
596 {
597 iTotal = iTotal * iConstant + value;
598 return this;
599 }
600
601
602 /**
603 * <p>
604 * Append a <code>hashCode</code> for a <code>double</code>.
605 * </p>
606 *
607 * @param value
608 * the double to add to the <code>hashCode</code>
609 * @return this
610 */
611 public HashCodeBuilder append( double value )
612 {
613 return append( Double.doubleToLongBits( value ) );
614 }
615
616
617 /**
618 * <p>
619 * Append a <code>hashCode</code> for a <code>float</code>.
620 * </p>
621 *
622 * @param value
623 * the float to add to the <code>hashCode</code>
624 * @return this
625 */
626 public HashCodeBuilder append( float value )
627 {
628 iTotal = iTotal * iConstant + Float.floatToIntBits( value );
629 return this;
630 }
631
632
633 /**
634 * <p>
635 * Append a <code>hashCode</code> for a <code>boolean</code>.
636 * </p>
637 * <p>
638 * This adds <code>iConstant * 1</code> to the <code>hashCode</code> and
639 * not a <code>1231</code> or <code>1237</code> as done in
640 * java.lang.Boolean. This is in accordance with the Effective Java design.
641 * </p>
642 *
643 * @param value
644 * the boolean to add to the <code>hashCode</code>
645 * @return this
646 */
647 public HashCodeBuilder append( boolean value )
648 {
649 iTotal = iTotal * iConstant + ( value ? 0 : 1 );
650 return this;
651 }
652
653
654 /**
655 * <p>
656 * Append a <code>hashCode</code> for an <code>Object</code> array.
657 * </p>
658 *
659 * @param array
660 * the array to add to the <code>hashCode</code>
661 * @return this
662 */
663 public HashCodeBuilder append( Object[] array )
664 {
665 if ( array == null )
666 {
667 iTotal = iTotal * iConstant;
668 }
669 else
670 {
671 for ( int i = 0; i < array.length; i++ )
672 {
673 append( array[i] );
674 }
675 }
676 return this;
677 }
678
679
680 /**
681 * <p>
682 * Append a <code>hashCode</code> for a <code>long</code> array.
683 * </p>
684 *
685 * @param array
686 * the array to add to the <code>hashCode</code>
687 * @return this
688 */
689 public HashCodeBuilder append( long[] array )
690 {
691 if ( array == null )
692 {
693 iTotal = iTotal * iConstant;
694 }
695 else
696 {
697 for ( int i = 0; i < array.length; i++ )
698 {
699 append( array[i] );
700 }
701 }
702 return this;
703 }
704
705
706 /**
707 * <p>
708 * Append a <code>hashCode</code> for an <code>int</code> array.
709 * </p>
710 *
711 * @param array
712 * the array to add to the <code>hashCode</code>
713 * @return this
714 */
715 public HashCodeBuilder append( int[] array )
716 {
717 if ( array == null )
718 {
719 iTotal = iTotal * iConstant;
720 }
721 else
722 {
723 for ( int i = 0; i < array.length; i++ )
724 {
725 append( array[i] );
726 }
727 }
728 return this;
729 }
730
731
732 /**
733 * <p>
734 * Append a <code>hashCode</code> for a <code>short</code> array.
735 * </p>
736 *
737 * @param array
738 * the array to add to the <code>hashCode</code>
739 * @return this
740 */
741 public HashCodeBuilder append( short[] array )
742 {
743 if ( array == null )
744 {
745 iTotal = iTotal * iConstant;
746 }
747 else
748 {
749 for ( int i = 0; i < array.length; i++ )
750 {
751 append( array[i] );
752 }
753 }
754 return this;
755 }
756
757
758 /**
759 * <p>
760 * Append a <code>hashCode</code> for a <code>char</code> array.
761 * </p>
762 *
763 * @param array
764 * the array to add to the <code>hashCode</code>
765 * @return this
766 */
767 public HashCodeBuilder append( char[] array )
768 {
769 if ( array == null )
770 {
771 iTotal = iTotal * iConstant;
772 }
773 else
774 {
775 for ( int i = 0; i < array.length; i++ )
776 {
777 append( array[i] );
778 }
779 }
780 return this;
781 }
782
783
784 /**
785 * <p>
786 * Append a <code>hashCode</code> for a <code>byte</code> array.
787 * </p>
788 *
789 * @param array
790 * the array to add to the <code>hashCode</code>
791 * @return this
792 */
793 public HashCodeBuilder append( byte[] array )
794 {
795 if ( array == null )
796 {
797 iTotal = iTotal * iConstant;
798 }
799 else
800 {
801 for ( int i = 0; i < array.length; i++ )
802 {
803 append( array[i] );
804 }
805 }
806 return this;
807 }
808
809
810 /**
811 * <p>
812 * Append a <code>hashCode</code> for a <code>double</code> array.
813 * </p>
814 *
815 * @param array
816 * the array to add to the <code>hashCode</code>
817 * @return this
818 */
819 public HashCodeBuilder append( double[] array )
820 {
821 if ( array == null )
822 {
823 iTotal = iTotal * iConstant;
824 }
825 else
826 {
827 for ( int i = 0; i < array.length; i++ )
828 {
829 append( array[i] );
830 }
831 }
832 return this;
833 }
834
835
836 /**
837 * <p>
838 * Append a <code>hashCode</code> for a <code>float</code> array.
839 * </p>
840 *
841 * @param array
842 * the array to add to the <code>hashCode</code>
843 * @return this
844 */
845 public HashCodeBuilder append( float[] array )
846 {
847 if ( array == null )
848 {
849 iTotal = iTotal * iConstant;
850 }
851 else
852 {
853 for ( int i = 0; i < array.length; i++ )
854 {
855 append( array[i] );
856 }
857 }
858 return this;
859 }
860
861
862 /**
863 * <p>
864 * Append a <code>hashCode</code> for a <code>boolean</code> array.
865 * </p>
866 *
867 * @param array
868 * the array to add to the <code>hashCode</code>
869 * @return this
870 */
871 public HashCodeBuilder append( boolean[] array )
872 {
873 if ( array == null )
874 {
875 iTotal = iTotal * iConstant;
876 }
877 else
878 {
879 for ( int i = 0; i < array.length; i++ )
880 {
881 append( array[i] );
882 }
883 }
884 return this;
885 }
886
887
888 /**
889 * <p>
890 * Return the computed <code>hashCode</code>.
891 * </p>
892 *
893 * @return <code>hashCode</code> based on the fields appended
894 */
895 public int toHashCode()
896 {
897 return iTotal;
898 }
899
900 }