View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3.builder;
19  
20  import java.lang.reflect.AccessibleObject;
21  import java.lang.reflect.Field;
22  import java.lang.reflect.Modifier;
23  import java.util.Collection;
24  import java.util.Comparator;
25  import java.util.HashSet;
26  import java.util.Set;
27  
28  import org.apache.commons.lang3.ArraySorter;
29  import org.apache.commons.lang3.ArrayUtils;
30  import org.apache.commons.lang3.Validate;
31  
32  /**
33   * <p>
34   * Assists in implementing {@link Object#hashCode()} methods.
35   * </p>
36   *
37   * <p>
38   * This class enables a good {@code hashCode} method to be built for any class. It follows the rules laid out in
39   * the book <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a
40   * good {@code hashCode} method is actually quite difficult. This class aims to simplify the process.
41   * </p>
42   *
43   * <p>
44   * The following is the approach taken. When appending a data field, the current total is multiplied by the
45   * multiplier then a relevant value
46   * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
47   * appending the integer 45 will create a hash code of 674, namely 17 * 37 + 45.
48   * </p>
49   *
50   * <p>
51   * All relevant fields from the object should be included in the {@code hashCode} method. Derived fields may be
52   * excluded. In general, any field used in the {@code equals} method must be used in the {@code hashCode}
53   * method.
54   * </p>
55   *
56   * <p>
57   * To use this class write code as follows:
58   * </p>
59   *
60   * <pre>
61   * public class Person {
62   *   String name;
63   *   int age;
64   *   boolean smoker;
65   *   ...
66   *
67   *   public int hashCode() {
68   *     // you pick a hard-coded, randomly chosen, non-zero, odd number
69   *     // ideally different for each class
70   *     return new HashCodeBuilder(17, 37).
71   *       append(name).
72   *       append(age).
73   *       append(smoker).
74   *       toHashCode();
75   *   }
76   * }
77   * </pre>
78   *
79   * <p>
80   * If required, the superclass {@code hashCode()} can be added using {@link #appendSuper}.
81   * </p>
82   *
83   * <p>
84   * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
85   * usually private, the method, {@code reflectionHashCode}, uses {@code AccessibleObject.setAccessible}
86   * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
87   * are set up correctly. It is also slower than testing explicitly.
88   * </p>
89   *
90   * <p>
91   * A typical invocation for this method would look like:
92   * </p>
93   *
94   * <pre>
95   * public int hashCode() {
96   *   return HashCodeBuilder.reflectionHashCode(this);
97   * }
98   * </pre>
99   *
100  * <p>The {@link HashCodeExclude} annotation can be used to exclude fields from being
101  * used by the {@code reflectionHashCode} methods.</p>
102  *
103  * @since 1.0
104  */
105 public class HashCodeBuilder implements Builder<Integer> {
106     /**
107      * The default initial value to use in reflection hash code building.
108      */
109     private static final int DEFAULT_INITIAL_VALUE = 17;
110 
111     /**
112      * The default multiplier value to use in reflection hash code building.
113      */
114     private static final int DEFAULT_MULTIPLIER_VALUE = 37;
115 
116     /**
117      * <p>
118      * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
119      * </p>
120      *
121      * @since 2.3
122      */
123     private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<>();
124 
125     /*
126      * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
127      * we are in the process of calculating.
128      *
129      * So we generate a one-to-one mapping from the original object to a new object.
130      *
131      * Now HashSet uses equals() to determine if two elements with the same hash code really
132      * are equal, so we also need to ensure that the replacement objects are only equal
133      * if the original objects are identical.
134      *
135      * The original implementation (2.4 and before) used the System.identityHashCode()
136      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
137      *
138      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
139      * to disambiguate the duplicate ids.
140      */
141 
142     /**
143      * <p>
144      * Returns the registry of objects being traversed by the reflection methods in the current thread.
145      * </p>
146      *
147      * @return Set the registry of objects being traversed
148      * @since 2.3
149      */
150     static Set<IDKey> getRegistry() {
151         return REGISTRY.get();
152     }
153 
154     /**
155      * <p>
156      * Returns {@code true} if the registry contains the given object. Used by the reflection methods to avoid
157      * infinite loops.
158      * </p>
159      *
160      * @param value
161      *            The object to lookup in the registry.
162      * @return boolean {@code true} if the registry contains the given object.
163      * @since 2.3
164      */
165     static boolean isRegistered(final Object value) {
166         final Set<IDKey> registry = getRegistry();
167         return registry != null && registry.contains(new IDKey(value));
168     }
169 
170     /**
171      * <p>
172      * Appends the fields and values defined by the given object of the given {@code Class}.
173      * </p>
174      *
175      * @param object
176      *            the object to append details of
177      * @param clazz
178      *            the class to append details of
179      * @param builder
180      *            the builder to append to
181      * @param useTransients
182      *            whether to use transient fields
183      * @param excludeFields
184      *            Collection of String field names to exclude from use in calculation of hash code
185      */
186     private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients,
187             final String[] excludeFields) {
188         if (isRegistered(object)) {
189             return;
190         }
191         try {
192             register(object);
193             // The elements in the returned array are not sorted and are not in any particular order.
194             final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
195             AccessibleObject.setAccessible(fields, true);
196             for (final Field field : fields) {
197                 if (!ArrayUtils.contains(excludeFields, field.getName())
198                     && !field.getName().contains("$")
199                     && (useTransients || !Modifier.isTransient(field.getModifiers()))
200                     && !Modifier.isStatic(field.getModifiers())
201                     && !field.isAnnotationPresent(HashCodeExclude.class)) {
202                     try {
203                         final Object fieldValue = field.get(object);
204                         builder.append(fieldValue);
205                     } catch (final IllegalAccessException e) {
206                         // this can't happen. Would get a Security exception instead
207                         // throw a runtime exception in case the impossible happens.
208                         throw new InternalError("Unexpected IllegalAccessException");
209                     }
210                 }
211             }
212         } finally {
213             unregister(object);
214         }
215     }
216 
217     /**
218      * <p>
219      * Uses reflection to build a valid hash code from the fields of {@code object}.
220      * </p>
221      *
222      * <p>
223      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
224      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
225      * also not as efficient as testing explicitly.
226      * </p>
227      *
228      * <p>
229      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
230      * {@code Object}.
231      * </p>
232      *
233      * <p>
234      * Static fields will not be tested. Superclass fields will be included.
235      * </p>
236      *
237      * <p>
238      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
239      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
240      * </p>
241      *
242      * @param initialNonZeroOddNumber
243      *            a non-zero, odd number used as the initial value. This will be the returned
244      *            value if no fields are found to include in the hash code
245      * @param multiplierNonZeroOddNumber
246      *            a non-zero, odd number used as the multiplier
247      * @param object
248      *            the Object to create a {@code hashCode} for
249      * @return int hash code
250      * @throws IllegalArgumentException
251      *             if the Object is {@code null}
252      * @throws IllegalArgumentException
253      *             if the number is zero or even
254      *
255      * @see HashCodeExclude
256      */
257     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
258         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
259     }
260 
261     /**
262      * <p>
263      * Uses reflection to build a valid hash code from the fields of {@code object}.
264      * </p>
265      *
266      * <p>
267      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
268      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
269      * also not as efficient as testing explicitly.
270      * </p>
271      *
272      * <p>
273      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
274      * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}.
275      * </p>
276      *
277      * <p>
278      * Static fields will not be tested. Superclass fields will be included.
279      * </p>
280      *
281      * <p>
282      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
283      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
284      * </p>
285      *
286      * @param initialNonZeroOddNumber
287      *            a non-zero, odd number used as the initial value. This will be the returned
288      *            value if no fields are found to include in the hash code
289      * @param multiplierNonZeroOddNumber
290      *            a non-zero, odd number used as the multiplier
291      * @param object
292      *            the Object to create a {@code hashCode} for
293      * @param testTransients
294      *            whether to include transient fields
295      * @return int hash code
296      * @throws IllegalArgumentException
297      *             if the Object is {@code null}
298      * @throws IllegalArgumentException
299      *             if the number is zero or even
300      *
301      * @see HashCodeExclude
302      */
303     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
304             final boolean testTransients) {
305         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
306     }
307 
308     /**
309      * <p>
310      * Uses reflection to build a valid hash code from the fields of {@code object}.
311      * </p>
312      *
313      * <p>
314      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
315      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
316      * also not as efficient as testing explicitly.
317      * </p>
318      *
319      * <p>
320      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
321      * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}.
322      * </p>
323      *
324      * <p>
325      * Static fields will not be included. Superclass fields will be included up to and including the specified
326      * superclass. A null superclass is treated as java.lang.Object.
327      * </p>
328      *
329      * <p>
330      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
331      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
332      * </p>
333      *
334      * @param <T>
335      *            the type of the object involved
336      * @param initialNonZeroOddNumber
337      *            a non-zero, odd number used as the initial value. This will be the returned
338      *            value if no fields are found to include in the hash code
339      * @param multiplierNonZeroOddNumber
340      *            a non-zero, odd number used as the multiplier
341      * @param object
342      *            the Object to create a {@code hashCode} for
343      * @param testTransients
344      *            whether to include transient fields
345      * @param reflectUpToClass
346      *            the superclass to reflect up to (inclusive), may be {@code null}
347      * @param excludeFields
348      *            array of field names to exclude from use in calculation of hash code
349      * @return int hash code
350      * @throws IllegalArgumentException
351      *             if the Object is {@code null}
352      * @throws IllegalArgumentException
353      *             if the number is zero or even
354      *
355      * @see HashCodeExclude
356      * @since 2.0
357      */
358     public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
359             final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
360         Validate.notNull(object, "object");
361         final HashCodeBuildershCodeBuilder.html#HashCodeBuilder">HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
362         Class<?> clazz = object.getClass();
363         reflectionAppend(object, clazz, builder, testTransients, excludeFields);
364         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
365             clazz = clazz.getSuperclass();
366             reflectionAppend(object, clazz, builder, testTransients, excludeFields);
367         }
368         return builder.toHashCode();
369     }
370 
371     /**
372      * <p>
373      * Uses reflection to build a valid hash code from the fields of {@code object}.
374      * </p>
375      *
376      * <p>
377      * This constructor uses two hard coded choices for the constants needed to build a hash code.
378      * </p>
379      *
380      * <p>
381      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
382      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
383      * also not as efficient as testing explicitly.
384      * </p>
385      *
386      * <P>
387      * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
388      * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}.
389      * </p>
390      *
391      * <p>
392      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
393      * in the hash code, the result of this method will be constant.
394      * </p>
395      *
396      * @param object
397      *            the Object to create a {@code hashCode} for
398      * @param testTransients
399      *            whether to include transient fields
400      * @return int hash code
401      * @throws IllegalArgumentException
402      *             if the object is {@code null}
403      *
404      * @see HashCodeExclude
405      */
406     public static int reflectionHashCode(final Object object, final boolean testTransients) {
407         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
408                 testTransients, null);
409     }
410 
411     /**
412      * <p>
413      * Uses reflection to build a valid hash code from the fields of {@code object}.
414      * </p>
415      *
416      * <p>
417      * This constructor uses two hard coded choices for the constants needed to build a hash code.
418      * </p>
419      *
420      * <p>
421      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
422      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
423      * also not as efficient as testing explicitly.
424      * </p>
425      *
426      * <p>
427      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
428      * {@code Object}.
429      * </p>
430      *
431      * <p>
432      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
433      * in the hash code, the result of this method will be constant.
434      * </p>
435      *
436      * @param object
437      *            the Object to create a {@code hashCode} for
438      * @param excludeFields
439      *            Collection of String field names to exclude from use in calculation of hash code
440      * @return int hash code
441      * @throws IllegalArgumentException
442      *             if the object is {@code null}
443      *
444      * @see HashCodeExclude
445      */
446     public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
447         return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
448     }
449 
450     // -------------------------------------------------------------------------
451 
452     /**
453      * <p>
454      * Uses reflection to build a valid hash code from the fields of {@code object}.
455      * </p>
456      *
457      * <p>
458      * This constructor uses two hard coded choices for the constants needed to build a hash code.
459      * </p>
460      *
461      * <p>
462      * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
463      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
464      * also not as efficient as testing explicitly.
465      * </p>
466      *
467      * <p>
468      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
469      * {@code Object}.
470      * </p>
471      *
472      * <p>
473      * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
474      * in the hash code, the result of this method will be constant.
475      * </p>
476      *
477      * @param object
478      *            the Object to create a {@code hashCode} for
479      * @param excludeFields
480      *            array of field names to exclude from use in calculation of hash code
481      * @return int hash code
482      * @throws IllegalArgumentException
483      *             if the object is {@code null}
484      *
485      * @see HashCodeExclude
486      */
487     public static int reflectionHashCode(final Object object, final String... excludeFields) {
488         return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
489                 null, excludeFields);
490     }
491 
492     /**
493      * <p>
494      * Registers the given object. Used by the reflection methods to avoid infinite loops.
495      * </p>
496      *
497      * @param value
498      *            The object to register.
499      */
500     private static void register(final Object value) {
501         Set<IDKey> registry = getRegistry();
502         if (registry == null) {
503             registry = new HashSet<>();
504             REGISTRY.set(registry);
505         }
506         registry.add(new IDKey(value));
507     }
508 
509     /**
510      * <p>
511      * Unregisters the given object.
512      * </p>
513      *
514      * <p>
515      * Used by the reflection methods to avoid infinite loops.
516      *
517      * @param value
518      *            The object to unregister.
519      * @since 2.3
520      */
521     private static void unregister(final Object value) {
522         final Set<IDKey> registry = getRegistry();
523         if (registry != null) {
524             registry.remove(new IDKey(value));
525             if (registry.isEmpty()) {
526                 REGISTRY.remove();
527             }
528         }
529     }
530 
531     /**
532      * Constant to use in building the hashCode.
533      */
534     private final int iConstant;
535 
536     /**
537      * Running total of the hashCode.
538      */
539     private int iTotal;
540 
541     /**
542      * <p>
543      * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
544      * </p>
545      */
546     public HashCodeBuilder() {
547         iConstant = 37;
548         iTotal = 17;
549     }
550 
551     /**
552      * <p>
553      * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
554      * however this is not vital.
555      * </p>
556      *
557      * <p>
558      * Prime numbers are preferred, especially for the multiplier.
559      * </p>
560      *
561      * @param initialOddNumber
562      *            an odd number used as the initial value
563      * @param multiplierOddNumber
564      *            an odd number used as the multiplier
565      * @throws IllegalArgumentException
566      *             if the number is even
567      */
568     public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
569         Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
570         Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
571         iConstant = multiplierOddNumber;
572         iTotal = initialOddNumber;
573     }
574 
575     /**
576      * <p>
577      * Append a {@code hashCode} for a {@code boolean}.
578      * </p>
579      * <p>
580      * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
581      * </p>
582      * <p>
583      * This is in contrast to the standard {@code java.lang.Boolean.hashCode} handling, which computes
584      * a {@code hashCode} value of {@code 1231} for {@code java.lang.Boolean} instances
585      * that represent {@code true} or {@code 1237} for {@code java.lang.Boolean} instances
586      * that represent {@code false}.
587      * </p>
588      * <p>
589      * This is in accordance with the <i>Effective Java</i> design.
590      * </p>
591      *
592      * @param value
593      *            the boolean to add to the {@code hashCode}
594      * @return this
595      */
596     public HashCodeBuilder append(final boolean value) {
597         iTotal = iTotal * iConstant + (value ? 0 : 1);
598         return this;
599     }
600 
601     /**
602      * <p>
603      * Append a {@code hashCode} for a {@code boolean} array.
604      * </p>
605      *
606      * @param array
607      *            the array to add to the {@code hashCode}
608      * @return this
609      */
610     public HashCodeBuilder append(final boolean[] array) {
611         if (array == null) {
612             iTotal = iTotal * iConstant;
613         } else {
614             for (final boolean element : array) {
615                 append(element);
616             }
617         }
618         return this;
619     }
620 
621     // -------------------------------------------------------------------------
622 
623     /**
624      * <p>
625      * Append a {@code hashCode} for a {@code byte}.
626      * </p>
627      *
628      * @param value
629      *            the byte to add to the {@code hashCode}
630      * @return this
631      */
632     public HashCodeBuilder append(final byte value) {
633         iTotal = iTotal * iConstant + value;
634         return this;
635     }
636 
637     // -------------------------------------------------------------------------
638 
639     /**
640      * <p>
641      * Append a {@code hashCode} for a {@code byte} array.
642      * </p>
643      *
644      * @param array
645      *            the array to add to the {@code hashCode}
646      * @return this
647      */
648     public HashCodeBuilder append(final byte[] array) {
649         if (array == null) {
650             iTotal = iTotal * iConstant;
651         } else {
652             for (final byte element : array) {
653                 append(element);
654             }
655         }
656         return this;
657     }
658 
659     /**
660      * <p>
661      * Append a {@code hashCode} for a {@code char}.
662      * </p>
663      *
664      * @param value
665      *            the char to add to the {@code hashCode}
666      * @return this
667      */
668     public HashCodeBuilder append(final char value) {
669         iTotal = iTotal * iConstant + value;
670         return this;
671     }
672 
673     /**
674      * <p>
675      * Append a {@code hashCode} for a {@code char} array.
676      * </p>
677      *
678      * @param array
679      *            the array to add to the {@code hashCode}
680      * @return this
681      */
682     public HashCodeBuilder append(final char[] array) {
683         if (array == null) {
684             iTotal = iTotal * iConstant;
685         } else {
686             for (final char element : array) {
687                 append(element);
688             }
689         }
690         return this;
691     }
692 
693     /**
694      * <p>
695      * Append a {@code hashCode} for a {@code double}.
696      * </p>
697      *
698      * @param value
699      *            the double to add to the {@code hashCode}
700      * @return this
701      */
702     public HashCodeBuilder append(final double value) {
703         return append(Double.doubleToLongBits(value));
704     }
705 
706     /**
707      * <p>
708      * Append a {@code hashCode} for a {@code double} array.
709      * </p>
710      *
711      * @param array
712      *            the array to add to the {@code hashCode}
713      * @return this
714      */
715     public HashCodeBuilder append(final double[] array) {
716         if (array == null) {
717             iTotal = iTotal * iConstant;
718         } else {
719             for (final double element : array) {
720                 append(element);
721             }
722         }
723         return this;
724     }
725 
726     /**
727      * <p>
728      * Append a {@code hashCode} for a {@code float}.
729      * </p>
730      *
731      * @param value
732      *            the float to add to the {@code hashCode}
733      * @return this
734      */
735     public HashCodeBuilder append(final float value) {
736         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
737         return this;
738     }
739 
740     /**
741      * <p>
742      * Append a {@code hashCode} for a {@code float} array.
743      * </p>
744      *
745      * @param array
746      *            the array to add to the {@code hashCode}
747      * @return this
748      */
749     public HashCodeBuilder append(final float[] array) {
750         if (array == null) {
751             iTotal = iTotal * iConstant;
752         } else {
753             for (final float element : array) {
754                 append(element);
755             }
756         }
757         return this;
758     }
759 
760     /**
761      * <p>
762      * Append a {@code hashCode} for an {@code int}.
763      * </p>
764      *
765      * @param value
766      *            the int to add to the {@code hashCode}
767      * @return this
768      */
769     public HashCodeBuilder append(final int value) {
770         iTotal = iTotal * iConstant + value;
771         return this;
772     }
773 
774     /**
775      * <p>
776      * Append a {@code hashCode} for an {@code int} array.
777      * </p>
778      *
779      * @param array
780      *            the array to add to the {@code hashCode}
781      * @return this
782      */
783     public HashCodeBuilder append(final int[] array) {
784         if (array == null) {
785             iTotal = iTotal * iConstant;
786         } else {
787             for (final int element : array) {
788                 append(element);
789             }
790         }
791         return this;
792     }
793 
794     /**
795      * <p>
796      * Append a {@code hashCode} for a {@code long}.
797      * </p>
798      *
799      * @param value
800      *            the long to add to the {@code hashCode}
801      * @return this
802      */
803     // NOTE: This method uses >> and not >>> as Effective Java and
804     //       Long.hashCode do. Ideally we should switch to >>> at
805     //       some stage. There are backwards compat issues, so
806     //       that will have to wait for the time being. cf LANG-342.
807     public HashCodeBuilder append(final long value) {
808         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
809         return this;
810     }
811 
812     /**
813      * <p>
814      * Append a {@code hashCode} for a {@code long} array.
815      * </p>
816      *
817      * @param array
818      *            the array to add to the {@code hashCode}
819      * @return this
820      */
821     public HashCodeBuilder append(final long[] array) {
822         if (array == null) {
823             iTotal = iTotal * iConstant;
824         } else {
825             for (final long element : array) {
826                 append(element);
827             }
828         }
829         return this;
830     }
831 
832     /**
833      * <p>
834      * Append a {@code hashCode} for an {@code Object}.
835      * </p>
836      *
837      * @param object
838      *            the Object to add to the {@code hashCode}
839      * @return this
840      */
841     public HashCodeBuilder append(final Object object) {
842         if (object == null) {
843             iTotal = iTotal * iConstant;
844 
845         } else if (object.getClass().isArray()) {
846             // factor out array case in order to keep method small enough
847             // to be inlined
848             appendArray(object);
849         } else {
850             iTotal = iTotal * iConstant + object.hashCode();
851         }
852         return this;
853     }
854 
855     /**
856      * <p>
857      * Append a {@code hashCode} for an array.
858      * </p>
859      *
860      * @param object
861      *            the array to add to the {@code hashCode}
862      */
863     private void appendArray(final Object object) {
864         // 'Switch' on type of array, to dispatch to the correct handler
865         // This handles multi dimensional arrays
866         if (object instanceof long[]) {
867             append((long[]) object);
868         } else if (object instanceof int[]) {
869             append((int[]) object);
870         } else if (object instanceof short[]) {
871             append((short[]) object);
872         } else if (object instanceof char[]) {
873             append((char[]) object);
874         } else if (object instanceof byte[]) {
875             append((byte[]) object);
876         } else if (object instanceof double[]) {
877             append((double[]) object);
878         } else if (object instanceof float[]) {
879             append((float[]) object);
880         } else if (object instanceof boolean[]) {
881             append((boolean[]) object);
882         } else {
883             // Not an array of primitives
884             append((Object[]) object);
885         }
886     }
887 
888     /**
889      * <p>
890      * Append a {@code hashCode} for an {@code Object} array.
891      * </p>
892      *
893      * @param array
894      *            the array to add to the {@code hashCode}
895      * @return this
896      */
897     public HashCodeBuilder append(final Object[] array) {
898         if (array == null) {
899             iTotal = iTotal * iConstant;
900         } else {
901             for (final Object element : array) {
902                 append(element);
903             }
904         }
905         return this;
906     }
907 
908     /**
909      * <p>
910      * Append a {@code hashCode} for a {@code short}.
911      * </p>
912      *
913      * @param value
914      *            the short to add to the {@code hashCode}
915      * @return this
916      */
917     public HashCodeBuilder append(final short value) {
918         iTotal = iTotal * iConstant + value;
919         return this;
920     }
921 
922     /**
923      * <p>
924      * Append a {@code hashCode} for a {@code short} array.
925      * </p>
926      *
927      * @param array
928      *            the array to add to the {@code hashCode}
929      * @return this
930      */
931     public HashCodeBuilder append(final short[] array) {
932         if (array == null) {
933             iTotal = iTotal * iConstant;
934         } else {
935             for (final short element : array) {
936                 append(element);
937             }
938         }
939         return this;
940     }
941 
942     /**
943      * <p>
944      * Adds the result of super.hashCode() to this builder.
945      * </p>
946      *
947      * @param superHashCode
948      *            the result of calling {@code super.hashCode()}
949      * @return this HashCodeBuilder, used to chain calls.
950      * @since 2.0
951      */
952     public HashCodeBuilder appendSuper(final int superHashCode) {
953         iTotal = iTotal * iConstant + superHashCode;
954         return this;
955     }
956 
957     /**
958      * <p>
959      * Returns the computed {@code hashCode}.
960      * </p>
961      *
962      * @return {@code hashCode} based on the fields appended
963      */
964     public int toHashCode() {
965         return iTotal;
966     }
967 
968     /**
969      * Returns the computed {@code hashCode}.
970      *
971      * @return {@code hashCode} based on the fields appended
972      *
973      * @since 3.0
974      */
975     @Override
976     public Integer build() {
977         return Integer.valueOf(toHashCode());
978     }
979 
980     /**
981      * <p>
982      * The computed {@code hashCode} from toHashCode() is returned due to the likelihood
983      * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
984      * HashCodeBuilder itself is.</p>
985      *
986      * @return {@code hashCode} based on the fields appended
987      * @since 2.5
988      */
989     @Override
990     public int hashCode() {
991         return toHashCode();
992     }
993 
994 }