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 * <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<Set<IDKey>>();
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 hashcode 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
358        if (object == null) {
359            throw new IllegalArgumentException("The object to build a hash code for must not be null");
360        }
361        final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
362        Class<?> clazz = object.getClass();
363        reflectionAppend(object, clazz, builder, testTransients, excludeFields);
364        while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
365            clazz = clazz.getSuperclass();
366            reflectionAppend(object, clazz, builder, testTransients, excludeFields);
367        }
368        return builder.toHashCode();
369    }
370
371    /**
372     * <p>
373     * Uses reflection to build a valid hash code from the fields of {@code object}.
374     * </p>
375     *
376     * <p>
377     * This constructor uses two hard coded choices for the constants needed to build a hash code.
378     * </p>
379     *
380     * <p>
381     * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
382     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
383     * also not as efficient as testing explicitly.
384     * </p>
385     *
386     * <P>
387     * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
388     * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
389     * </p>
390     *
391     * <p>
392     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
393     * in the hash code, the result of this method will be constant.
394     * </p>
395     *
396     * @param object
397     *            the Object to create a <code>hashCode</code> for
398     * @param testTransients
399     *            whether to include transient fields
400     * @return int hash code
401     * @throws IllegalArgumentException
402     *             if the object is <code>null</code>
403     *
404     * @see HashCodeExclude
405     */
406    public static int reflectionHashCode(final Object object, final boolean testTransients) {
407        return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, 
408                testTransients, null);
409    }
410
411    /**
412     * <p>
413     * Uses reflection to build a valid hash code from the fields of {@code object}.
414     * </p>
415     *
416     * <p>
417     * This constructor uses two hard coded choices for the constants needed to build a hash code.
418     * </p>
419     *
420     * <p>
421     * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
422     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
423     * also not as efficient as testing explicitly.
424     * </p>
425     *
426     * <p>
427     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
428     * <code>Object</code>.
429     * </p>
430     *
431     * <p>
432     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
433     * in the hash code, the result of this method will be constant.
434     * </p>
435     *
436     * @param object
437     *            the Object to create a <code>hashCode</code> for
438     * @param excludeFields
439     *            Collection of String field names to exclude from use in calculation of hash code
440     * @return int hash code
441     * @throws IllegalArgumentException
442     *             if the object is <code>null</code>
443     *
444     * @see HashCodeExclude
445     */
446    public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
447        return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
448    }
449
450    // -------------------------------------------------------------------------
451
452    /**
453     * <p>
454     * Uses reflection to build a valid hash code from the fields of {@code object}.
455     * </p>
456     *
457     * <p>
458     * This constructor uses two hard coded choices for the constants needed to build a hash code.
459     * </p>
460     *
461     * <p>
462     * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
463     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
464     * also not as efficient as testing explicitly.
465     * </p>
466     *
467     * <p>
468     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
469     * <code>Object</code>.
470     * </p>
471     *
472     * <p>
473     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
474     * in the hash code, the result of this method will be constant.
475     * </p>
476     *
477     * @param object
478     *            the Object to create a <code>hashCode</code> for
479     * @param excludeFields
480     *            array of field names to exclude from use in calculation of hash code
481     * @return int hash code
482     * @throws IllegalArgumentException
483     *             if the object is <code>null</code>
484     *
485     * @see HashCodeExclude
486     */
487    public static int reflectionHashCode(final Object object, final String... excludeFields) {
488        return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false, 
489                null, excludeFields);
490    }
491
492    /**
493     * <p>
494     * Registers the given object. Used by the reflection methods to avoid infinite loops.
495     * </p>
496     *
497     * @param value
498     *            The object to register.
499     */
500    private static void register(final Object value) {
501        Set<IDKey> registry = getRegistry();
502        if (registry == null) {
503            registry = new HashSet<IDKey>();
504            REGISTRY.set(registry);
505        }
506        registry.add(new IDKey(value));
507    }
508
509    /**
510     * <p>
511     * Unregisters the given object.
512     * </p>
513     *
514     * <p>
515     * Used by the reflection methods to avoid infinite loops.
516     *
517     * @param value
518     *            The object to unregister.
519     * @since 2.3
520     */
521    private static void unregister(final Object value) {
522        Set<IDKey> registry = getRegistry();
523        if (registry != null) {
524            registry.remove(new IDKey(value));
525            if (registry.isEmpty()) {
526                REGISTRY.remove();
527            }
528        }
529    }
530
531    /**
532     * Constant to use in building the hashCode.
533     */
534    private final int iConstant;
535
536    /**
537     * Running total of the hashCode.
538     */
539    private int iTotal = 0;
540
541    /**
542     * <p>
543     * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>.
544     * </p>
545     */
546    public HashCodeBuilder() {
547        iConstant = 37;
548        iTotal = 17;
549    }
550
551    /**
552     * <p>
553     * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
554     * however this is not vital.
555     * </p>
556     *
557     * <p>
558     * Prime numbers are preferred, especially for the multiplier.
559     * </p>
560     *
561     * @param initialOddNumber
562     *            an odd number used as the initial value
563     * @param multiplierOddNumber
564     *            an odd number used as the multiplier
565     * @throws IllegalArgumentException
566     *             if the number is even
567     */
568    public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
569        Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
570        Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
571        iConstant = multiplierOddNumber;
572        iTotal = initialOddNumber;
573    }
574
575    /**
576     * <p>
577     * Append a <code>hashCode</code> for a <code>boolean</code>.
578     * </p>
579     * <p>
580     * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
581     * </p>
582     * <p>
583     * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
584     * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
585     * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
586     * that represent <code>false</code>.
587     * </p>
588     * <p>
589     * This is in accordance with the <i>Effective Java</i> design.
590     * </p>
591     *
592     * @param value
593     *            the boolean to add to the <code>hashCode</code>
594     * @return this
595     */
596    public HashCodeBuilder append(final boolean value) {
597        iTotal = iTotal * iConstant + (value ? 0 : 1);
598        return this;
599    }
600
601    /**
602     * <p>
603     * Append a <code>hashCode</code> for a <code>boolean</code> array.
604     * </p>
605     *
606     * @param array
607     *            the array to add to the <code>hashCode</code>
608     * @return this
609     */
610    public HashCodeBuilder append(final boolean[] array) {
611        if (array == null) {
612            iTotal = iTotal * iConstant;
613        } else {
614            for (final boolean element : array) {
615                append(element);
616            }
617        }
618        return this;
619    }
620
621    // -------------------------------------------------------------------------
622
623    /**
624     * <p>
625     * Append a <code>hashCode</code> for a <code>byte</code>.
626     * </p>
627     *
628     * @param value
629     *            the byte to add to the <code>hashCode</code>
630     * @return this
631     */
632    public HashCodeBuilder append(final byte value) {
633        iTotal = iTotal * iConstant + value;
634        return this;
635    }
636
637    // -------------------------------------------------------------------------
638
639    /**
640     * <p>
641     * Append a <code>hashCode</code> for a <code>byte</code> array.
642     * </p>
643     *
644     * @param array
645     *            the array to add to the <code>hashCode</code>
646     * @return this
647     */
648    public HashCodeBuilder append(final byte[] array) {
649        if (array == null) {
650            iTotal = iTotal * iConstant;
651        } else {
652            for (final byte element : array) {
653                append(element);
654            }
655        }
656        return this;
657    }
658
659    /**
660     * <p>
661     * Append a <code>hashCode</code> for a <code>char</code>.
662     * </p>
663     *
664     * @param value
665     *            the char to add to the <code>hashCode</code>
666     * @return this
667     */
668    public HashCodeBuilder append(final char value) {
669        iTotal = iTotal * iConstant + value;
670        return this;
671    }
672
673    /**
674     * <p>
675     * Append a <code>hashCode</code> for a <code>char</code> array.
676     * </p>
677     *
678     * @param array
679     *            the array to add to the <code>hashCode</code>
680     * @return this
681     */
682    public HashCodeBuilder append(final char[] array) {
683        if (array == null) {
684            iTotal = iTotal * iConstant;
685        } else {
686            for (final char element : array) {
687                append(element);
688            }
689        }
690        return this;
691    }
692
693    /**
694     * <p>
695     * Append a <code>hashCode</code> for a <code>double</code>.
696     * </p>
697     *
698     * @param value
699     *            the double to add to the <code>hashCode</code>
700     * @return this
701     */
702    public HashCodeBuilder append(final double value) {
703        return append(Double.doubleToLongBits(value));
704    }
705
706    /**
707     * <p>
708     * Append a <code>hashCode</code> for a <code>double</code> array.
709     * </p>
710     *
711     * @param array
712     *            the array to add to the <code>hashCode</code>
713     * @return this
714     */
715    public HashCodeBuilder append(final double[] array) {
716        if (array == null) {
717            iTotal = iTotal * iConstant;
718        } else {
719            for (final double element : array) {
720                append(element);
721            }
722        }
723        return this;
724    }
725
726    /**
727     * <p>
728     * Append a <code>hashCode</code> for a <code>float</code>.
729     * </p>
730     *
731     * @param value
732     *            the float to add to the <code>hashCode</code>
733     * @return this
734     */
735    public HashCodeBuilder append(final float value) {
736        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
737        return this;
738    }
739
740    /**
741     * <p>
742     * Append a <code>hashCode</code> for a <code>float</code> array.
743     * </p>
744     *
745     * @param array
746     *            the array to add to the <code>hashCode</code>
747     * @return this
748     */
749    public HashCodeBuilder append(final float[] array) {
750        if (array == null) {
751            iTotal = iTotal * iConstant;
752        } else {
753            for (final float element : array) {
754                append(element);
755            }
756        }
757        return this;
758    }
759
760    /**
761     * <p>
762     * Append a <code>hashCode</code> for an <code>int</code>.
763     * </p>
764     *
765     * @param value
766     *            the int to add to the <code>hashCode</code>
767     * @return this
768     */
769    public HashCodeBuilder append(final int value) {
770        iTotal = iTotal * iConstant + value;
771        return this;
772    }
773
774    /**
775     * <p>
776     * Append a <code>hashCode</code> for an <code>int</code> array.
777     * </p>
778     *
779     * @param array
780     *            the array to add to the <code>hashCode</code>
781     * @return this
782     */
783    public HashCodeBuilder append(final int[] array) {
784        if (array == null) {
785            iTotal = iTotal * iConstant;
786        } else {
787            for (final int element : array) {
788                append(element);
789            }
790        }
791        return this;
792    }
793
794    /**
795     * <p>
796     * Append a <code>hashCode</code> for a <code>long</code>.
797     * </p>
798     *
799     * @param value
800     *            the long to add to the <code>hashCode</code>
801     * @return this
802     */
803    // NOTE: This method uses >> and not >>> as Effective Java and
804    //       Long.hashCode do. Ideally we should switch to >>> at
805    //       some stage. There are backwards compat issues, so
806    //       that will have to wait for the time being. cf LANG-342.
807    public HashCodeBuilder append(final long value) {
808        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
809        return this;
810    }
811
812    /**
813     * <p>
814     * Append a <code>hashCode</code> for a <code>long</code> array.
815     * </p>
816     *
817     * @param array
818     *            the array to add to the <code>hashCode</code>
819     * @return this
820     */
821    public HashCodeBuilder append(final long[] array) {
822        if (array == null) {
823            iTotal = iTotal * iConstant;
824        } else {
825            for (final long element : array) {
826                append(element);
827            }
828        }
829        return this;
830    }
831
832    /**
833     * <p>
834     * Append a <code>hashCode</code> for an <code>Object</code>.
835     * </p>
836     *
837     * @param object
838     *            the Object to add to the <code>hashCode</code>
839     * @return this
840     */
841    public HashCodeBuilder append(final Object object) {
842        if (object == null) {
843            iTotal = iTotal * iConstant;
844
845        } else {
846            if (object.getClass().isArray()) {
847                // factor out array case in order to keep method small enough
848                // to be inlined
849                appendArray(object);
850            } else {
851                iTotal = iTotal * iConstant + object.hashCode();
852            }
853        }
854        return this;
855    }
856
857    /**
858     * <p>
859     * Append a <code>hashCode</code> for an array.
860     * </p>
861     *
862     * @param object
863     *            the array to add to the <code>hashCode</code>
864     */
865    private void appendArray(final Object object) {
866        // 'Switch' on type of array, to dispatch to the correct handler
867        // This handles multi dimensional arrays
868        if (object instanceof long[]) {
869            append((long[]) object);
870        } else if (object instanceof int[]) {
871            append((int[]) object);
872        } else if (object instanceof short[]) {
873            append((short[]) object);
874        } else if (object instanceof char[]) {
875            append((char[]) object);
876        } else if (object instanceof byte[]) {
877            append((byte[]) object);
878        } else if (object instanceof double[]) {
879            append((double[]) object);
880        } else if (object instanceof float[]) {
881            append((float[]) object);
882        } else if (object instanceof boolean[]) {
883            append((boolean[]) object);
884        } else {
885            // Not an array of primitives
886            append((Object[]) object);
887        }
888    }
889
890    /**
891     * <p>
892     * Append a <code>hashCode</code> for an <code>Object</code> array.
893     * </p>
894     *
895     * @param array
896     *            the array to add to the <code>hashCode</code>
897     * @return this
898     */
899    public HashCodeBuilder append(final Object[] array) {
900        if (array == null) {
901            iTotal = iTotal * iConstant;
902        } else {
903            for (final Object element : array) {
904                append(element);
905            }
906        }
907        return this;
908    }
909
910    /**
911     * <p>
912     * Append a <code>hashCode</code> for a <code>short</code>.
913     * </p>
914     *
915     * @param value
916     *            the short to add to the <code>hashCode</code>
917     * @return this
918     */
919    public HashCodeBuilder append(final short value) {
920        iTotal = iTotal * iConstant + value;
921        return this;
922    }
923
924    /**
925     * <p>
926     * Append a <code>hashCode</code> for a <code>short</code> array.
927     * </p>
928     *
929     * @param array
930     *            the array to add to the <code>hashCode</code>
931     * @return this
932     */
933    public HashCodeBuilder append(final short[] array) {
934        if (array == null) {
935            iTotal = iTotal * iConstant;
936        } else {
937            for (final short element : array) {
938                append(element);
939            }
940        }
941        return this;
942    }
943
944    /**
945     * <p>
946     * Adds the result of super.hashCode() to this builder.
947     * </p>
948     *
949     * @param superHashCode
950     *            the result of calling <code>super.hashCode()</code>
951     * @return this HashCodeBuilder, used to chain calls.
952     * @since 2.0
953     */
954    public HashCodeBuilder appendSuper(final int superHashCode) {
955        iTotal = iTotal * iConstant + superHashCode;
956        return this;
957    }
958
959    /**
960     * <p>
961     * Return the computed <code>hashCode</code>.
962     * </p>
963     *
964     * @return <code>hashCode</code> based on the fields appended
965     */
966    public int toHashCode() {
967        return iTotal;
968    }
969
970    /**
971     * Returns the computed <code>hashCode</code>.
972     *
973     * @return <code>hashCode</code> based on the fields appended
974     *
975     * @since 3.0
976     */
977    @Override
978    public Integer build() {
979        return Integer.valueOf(toHashCode());
980    }
981
982    /**
983     * <p>
984     * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
985     * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
986     * HashCodeBuilder itself is.</p>
987     *
988     * @return <code>hashCode</code> based on the fields appended
989     * @since 2.5
990     */
991    @Override
992    public int hashCode() {
993        return toHashCode();
994    }
995
996}