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