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