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