001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.lang3.builder;
019
020import java.lang.reflect.AccessibleObject;
021import java.lang.reflect.Field;
022import java.lang.reflect.Modifier;
023import java.util.Collection;
024import java.util.HashSet;
025import java.util.Set;
026
027import org.apache.commons.lang3.ArrayUtils;
028
029/**
030 * <p>
031 * Assists in implementing {@link Object#hashCode()} methods.
032 * </p>
033 *
034 * <p>
035 * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in
036 * the book <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> by Joshua Bloch. Writing a
037 * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process.
038 * </p>
039 *
040 * <p>
041 * The following is the approach taken. When appending a data field, the current total is multiplied by the
042 * multiplier then a relevant value
043 * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
044 * appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.
045 * </p>
046 *
047 * <p>
048 * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be
049 * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code>
050 * method.
051 * </p>
052 *
053 * <p>
054 * To use this class write code as follows:
055 * </p>
056 *
057 * <pre>
058 * public class Person {
059 *   String name;
060 *   int age;
061 *   boolean smoker;
062 *   ...
063 *
064 *   public int hashCode() {
065 *     // you pick a hard-coded, randomly chosen, non-zero, odd number
066 *     // ideally different for each class
067 *     return new HashCodeBuilder(17, 37).
068 *       append(name).
069 *       append(age).
070 *       append(smoker).
071 *       toHashCode();
072 *   }
073 * }
074 * </pre>
075 *
076 * <p>
077 * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}.
078 * </p>
079 *
080 * <p>
081 * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
082 * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code>
083 * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
084 * are set up correctly. It is also slower than testing explicitly.
085 * </p>
086 *
087 * <p>
088 * A typical invocation for this method would look like:
089 * </p>
090 *
091 * <pre>
092 * public int hashCode() {
093 *   return HashCodeBuilder.reflectionHashCode(this);
094 * }
095 * </pre>
096 *
097 * @since 1.0
098 * @version $Id: HashCodeBuilder.java 1583482 2014-03-31 22:54:57Z niallp $
099 */
100public 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, 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 initialOddNumber
532     *            an odd number used as the initial value
533     * @param multiplierOddNumber
534     *            an odd number used as the multiplier
535     * @throws IllegalArgumentException
536     *             if the number is even
537     */
538    public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
539        if (initialOddNumber % 2 == 0) {
540            throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
541        }
542        if (multiplierOddNumber % 2 == 0) {
543            throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
544        }
545        iConstant = multiplierOddNumber;
546        iTotal = initialOddNumber;
547    }
548
549    /**
550     * <p>
551     * Append a <code>hashCode</code> for a <code>boolean</code>.
552     * </p>
553     * <p>
554     * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
555     * </p>
556     * <p>
557     * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
558     * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
559     * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
560     * that represent <code>false</code>.
561     * </p>
562     * <p>
563     * This is in accordance with the <i>Effective Java</i> design.
564     * </p>
565     *
566     * @param value
567     *            the boolean to add to the <code>hashCode</code>
568     * @return this
569     */
570    public HashCodeBuilder append(final boolean value) {
571        iTotal = iTotal * iConstant + (value ? 0 : 1);
572        return this;
573    }
574
575    /**
576     * <p>
577     * Append a <code>hashCode</code> for a <code>boolean</code> array.
578     * </p>
579     *
580     * @param array
581     *            the array to add to the <code>hashCode</code>
582     * @return this
583     */
584    public HashCodeBuilder append(final boolean[] array) {
585        if (array == null) {
586            iTotal = iTotal * iConstant;
587        } else {
588            for (final boolean element : array) {
589                append(element);
590            }
591        }
592        return this;
593    }
594
595    // -------------------------------------------------------------------------
596
597    /**
598     * <p>
599     * Append a <code>hashCode</code> for a <code>byte</code>.
600     * </p>
601     *
602     * @param value
603     *            the byte to add to the <code>hashCode</code>
604     * @return this
605     */
606    public HashCodeBuilder append(final byte value) {
607        iTotal = iTotal * iConstant + value;
608        return this;
609    }
610
611    // -------------------------------------------------------------------------
612
613    /**
614     * <p>
615     * Append a <code>hashCode</code> for a <code>byte</code> array.
616     * </p>
617     *
618     * @param array
619     *            the array to add to the <code>hashCode</code>
620     * @return this
621     */
622    public HashCodeBuilder append(final byte[] array) {
623        if (array == null) {
624            iTotal = iTotal * iConstant;
625        } else {
626            for (final byte element : array) {
627                append(element);
628            }
629        }
630        return this;
631    }
632
633    /**
634     * <p>
635     * Append a <code>hashCode</code> for a <code>char</code>.
636     * </p>
637     *
638     * @param value
639     *            the char to add to the <code>hashCode</code>
640     * @return this
641     */
642    public HashCodeBuilder append(final char value) {
643        iTotal = iTotal * iConstant + value;
644        return this;
645    }
646
647    /**
648     * <p>
649     * Append a <code>hashCode</code> for a <code>char</code> array.
650     * </p>
651     *
652     * @param array
653     *            the array to add to the <code>hashCode</code>
654     * @return this
655     */
656    public HashCodeBuilder append(final char[] array) {
657        if (array == null) {
658            iTotal = iTotal * iConstant;
659        } else {
660            for (final char element : array) {
661                append(element);
662            }
663        }
664        return this;
665    }
666
667    /**
668     * <p>
669     * Append a <code>hashCode</code> for a <code>double</code>.
670     * </p>
671     *
672     * @param value
673     *            the double to add to the <code>hashCode</code>
674     * @return this
675     */
676    public HashCodeBuilder append(final double value) {
677        return append(Double.doubleToLongBits(value));
678    }
679
680    /**
681     * <p>
682     * Append a <code>hashCode</code> for a <code>double</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(final double[] array) {
690        if (array == null) {
691            iTotal = iTotal * iConstant;
692        } else {
693            for (final double element : array) {
694                append(element);
695            }
696        }
697        return this;
698    }
699
700    /**
701     * <p>
702     * Append a <code>hashCode</code> for a <code>float</code>.
703     * </p>
704     *
705     * @param value
706     *            the float to add to the <code>hashCode</code>
707     * @return this
708     */
709    public HashCodeBuilder append(final float value) {
710        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
711        return this;
712    }
713
714    /**
715     * <p>
716     * Append a <code>hashCode</code> for a <code>float</code> array.
717     * </p>
718     *
719     * @param array
720     *            the array to add to the <code>hashCode</code>
721     * @return this
722     */
723    public HashCodeBuilder append(final float[] array) {
724        if (array == null) {
725            iTotal = iTotal * iConstant;
726        } else {
727            for (final float element : array) {
728                append(element);
729            }
730        }
731        return this;
732    }
733
734    /**
735     * <p>
736     * Append a <code>hashCode</code> for an <code>int</code>.
737     * </p>
738     *
739     * @param value
740     *            the int to add to the <code>hashCode</code>
741     * @return this
742     */
743    public HashCodeBuilder append(final int value) {
744        iTotal = iTotal * iConstant + value;
745        return this;
746    }
747
748    /**
749     * <p>
750     * Append a <code>hashCode</code> for an <code>int</code> array.
751     * </p>
752     *
753     * @param array
754     *            the array to add to the <code>hashCode</code>
755     * @return this
756     */
757    public HashCodeBuilder append(final int[] array) {
758        if (array == null) {
759            iTotal = iTotal * iConstant;
760        } else {
761            for (final int element : array) {
762                append(element);
763            }
764        }
765        return this;
766    }
767
768    /**
769     * <p>
770     * Append a <code>hashCode</code> for a <code>long</code>.
771     * </p>
772     *
773     * @param value
774     *            the long to add to the <code>hashCode</code>
775     * @return this
776     */
777    // NOTE: This method uses >> and not >>> as Effective Java and
778    //       Long.hashCode do. Ideally we should switch to >>> at
779    //       some stage. There are backwards compat issues, so
780    //       that will have to wait for the time being. cf LANG-342.
781    public HashCodeBuilder append(final long value) {
782        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
783        return this;
784    }
785
786    /**
787     * <p>
788     * Append a <code>hashCode</code> for a <code>long</code> array.
789     * </p>
790     *
791     * @param array
792     *            the array to add to the <code>hashCode</code>
793     * @return this
794     */
795    public HashCodeBuilder append(final long[] array) {
796        if (array == null) {
797            iTotal = iTotal * iConstant;
798        } else {
799            for (final long element : array) {
800                append(element);
801            }
802        }
803        return this;
804    }
805
806    /**
807     * <p>
808     * Append a <code>hashCode</code> for an <code>Object</code>.
809     * </p>
810     *
811     * @param object
812     *            the Object to add to the <code>hashCode</code>
813     * @return this
814     */
815    public HashCodeBuilder append(final Object object) {
816        if (object == null) {
817            iTotal = iTotal * iConstant;
818
819        } else {
820            if(object.getClass().isArray()) {
821                // 'Switch' on type of array, to dispatch to the correct handler
822                // This handles multi dimensional arrays
823                if (object instanceof long[]) {
824                    append((long[]) object);
825                } else if (object instanceof int[]) {
826                    append((int[]) object);
827                } else if (object instanceof short[]) {
828                    append((short[]) object);
829                } else if (object instanceof char[]) {
830                    append((char[]) object);
831                } else if (object instanceof byte[]) {
832                    append((byte[]) object);
833                } else if (object instanceof double[]) {
834                    append((double[]) object);
835                } else if (object instanceof float[]) {
836                    append((float[]) object);
837                } else if (object instanceof boolean[]) {
838                    append((boolean[]) object);
839                } else {
840                    // Not an array of primitives
841                    append((Object[]) object);
842                }
843            } else {
844                iTotal = iTotal * iConstant + object.hashCode();
845            }
846        }
847        return this;
848    }
849
850    /**
851     * <p>
852     * Append a <code>hashCode</code> for an <code>Object</code> array.
853     * </p>
854     *
855     * @param array
856     *            the array to add to the <code>hashCode</code>
857     * @return this
858     */
859    public HashCodeBuilder append(final Object[] array) {
860        if (array == null) {
861            iTotal = iTotal * iConstant;
862        } else {
863            for (final Object element : array) {
864                append(element);
865            }
866        }
867        return this;
868    }
869
870    /**
871     * <p>
872     * Append a <code>hashCode</code> for a <code>short</code>.
873     * </p>
874     *
875     * @param value
876     *            the short to add to the <code>hashCode</code>
877     * @return this
878     */
879    public HashCodeBuilder append(final short value) {
880        iTotal = iTotal * iConstant + value;
881        return this;
882    }
883
884    /**
885     * <p>
886     * Append a <code>hashCode</code> for a <code>short</code> array.
887     * </p>
888     *
889     * @param array
890     *            the array to add to the <code>hashCode</code>
891     * @return this
892     */
893    public HashCodeBuilder append(final short[] array) {
894        if (array == null) {
895            iTotal = iTotal * iConstant;
896        } else {
897            for (final short element : array) {
898                append(element);
899            }
900        }
901        return this;
902    }
903
904    /**
905     * <p>
906     * Adds the result of super.hashCode() to this builder.
907     * </p>
908     *
909     * @param superHashCode
910     *            the result of calling <code>super.hashCode()</code>
911     * @return this HashCodeBuilder, used to chain calls.
912     * @since 2.0
913     */
914    public HashCodeBuilder appendSuper(final int superHashCode) {
915        iTotal = iTotal * iConstant + superHashCode;
916        return this;
917    }
918
919    /**
920     * <p>
921     * Return the computed <code>hashCode</code>.
922     * </p>
923     *
924     * @return <code>hashCode</code> based on the fields appended
925     */
926    public int toHashCode() {
927        return iTotal;
928    }
929
930    /**
931     * Returns the computed <code>hashCode</code>.
932     *
933     * @return <code>hashCode</code> based on the fields appended
934     *
935     * @since 3.0
936     */
937    @Override
938    public Integer build() {
939        return Integer.valueOf(toHashCode());
940    }
941
942    /**
943     * <p>
944     * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
945     * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
946     * HashCodeBuilder itself is.</p>
947     *
948     * @return <code>hashCode</code> based on the fields appended
949     * @since 2.5
950     */
951    @Override
952    public int hashCode() {
953        return toHashCode();
954    }
955
956}