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