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.Comparator;
025import java.util.HashSet;
026import java.util.Set;
027
028import org.apache.commons.lang3.ArraySorter;
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 = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
195            AccessibleObject.setAccessible(fields, true);
196            for (final Field field : fields) {
197                if (!ArrayUtils.contains(excludeFields, field.getName())
198                    && !field.getName().contains("$")
199                    && (useTransients || !Modifier.isTransient(field.getModifiers()))
200                    && !Modifier.isStatic(field.getModifiers())
201                    && !field.isAnnotationPresent(HashCodeExclude.class)) {
202                    try {
203                        final Object fieldValue = field.get(object);
204                        builder.append(fieldValue);
205                    } catch (final IllegalAccessException e) {
206                        // this can't happen. Would get a Security exception instead
207                        // throw a runtime exception in case the impossible happens.
208                        throw new InternalError("Unexpected IllegalAccessException");
209                    }
210                }
211            }
212        } finally {
213            unregister(object);
214        }
215    }
216
217    /**
218     * <p>
219     * Uses reflection to build a valid hash code from the fields of {@code object}.
220     * </p>
221     *
222     * <p>
223     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
224     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
225     * also not as efficient as testing explicitly.
226     * </p>
227     *
228     * <p>
229     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
230     * {@code Object}.
231     * </p>
232     *
233     * <p>
234     * Static fields will not be tested. Superclass fields will be included.
235     * </p>
236     *
237     * <p>
238     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
239     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
240     * </p>
241     *
242     * @param initialNonZeroOddNumber
243     *            a non-zero, odd number used as the initial value. This will be the returned
244     *            value if no fields are found to include in the hash code
245     * @param multiplierNonZeroOddNumber
246     *            a non-zero, odd number used as the multiplier
247     * @param object
248     *            the Object to create a {@code hashCode} for
249     * @return int hash code
250     * @throws IllegalArgumentException
251     *             if the Object is {@code null}
252     * @throws IllegalArgumentException
253     *             if the number is zero or even
254     *
255     * @see HashCodeExclude
256     */
257    public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
258        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
259    }
260
261    /**
262     * <p>
263     * Uses reflection to build a valid hash code from the fields of {@code object}.
264     * </p>
265     *
266     * <p>
267     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
268     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
269     * also not as efficient as testing explicitly.
270     * </p>
271     *
272     * <p>
273     * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
274     * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}.
275     * </p>
276     *
277     * <p>
278     * Static fields will not be tested. Superclass fields will be included.
279     * </p>
280     *
281     * <p>
282     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
283     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
284     * </p>
285     *
286     * @param initialNonZeroOddNumber
287     *            a non-zero, odd number used as the initial value. This will be the returned
288     *            value if no fields are found to include in the hash code
289     * @param multiplierNonZeroOddNumber
290     *            a non-zero, odd number used as the multiplier
291     * @param object
292     *            the Object to create a {@code hashCode} for
293     * @param testTransients
294     *            whether to include transient fields
295     * @return int hash code
296     * @throws IllegalArgumentException
297     *             if the Object is {@code null}
298     * @throws IllegalArgumentException
299     *             if the number is zero or even
300     *
301     * @see HashCodeExclude
302     */
303    public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
304            final boolean testTransients) {
305        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
306    }
307
308    /**
309     * <p>
310     * Uses reflection to build a valid hash code from the fields of {@code object}.
311     * </p>
312     *
313     * <p>
314     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
315     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
316     * also not as efficient as testing explicitly.
317     * </p>
318     *
319     * <p>
320     * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
321     * are ignored, as they are likely derived fields, and not part of the value of the {@code Object}.
322     * </p>
323     *
324     * <p>
325     * Static fields will not be included. Superclass fields will be included up to and including the specified
326     * superclass. A null superclass is treated as java.lang.Object.
327     * </p>
328     *
329     * <p>
330     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
331     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
332     * </p>
333     *
334     * @param <T>
335     *            the type of the object involved
336     * @param initialNonZeroOddNumber
337     *            a non-zero, odd number used as the initial value. This will be the returned
338     *            value if no fields are found to include in the hash code
339     * @param multiplierNonZeroOddNumber
340     *            a non-zero, odd number used as the multiplier
341     * @param object
342     *            the Object to create a {@code hashCode} for
343     * @param testTransients
344     *            whether to include transient fields
345     * @param reflectUpToClass
346     *            the superclass to reflect up to (inclusive), may be {@code null}
347     * @param excludeFields
348     *            array of field names to exclude from use in calculation of hash code
349     * @return int hash code
350     * @throws IllegalArgumentException
351     *             if the Object is {@code null}
352     * @throws IllegalArgumentException
353     *             if the number is zero or even
354     *
355     * @see HashCodeExclude
356     * @since 2.0
357     */
358    public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
359            final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
360        Validate.notNull(object, "object");
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} 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}, 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}.
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} 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}
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} 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}.
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} 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}
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} 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}.
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} 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}
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<>();
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        final 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;
540
541    /**
542     * <p>
543     * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
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} for a {@code boolean}.
578     * </p>
579     * <p>
580     * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
581     * </p>
582     * <p>
583     * This is in contrast to the standard {@code java.lang.Boolean.hashCode} handling, which computes
584     * a {@code hashCode} value of {@code 1231} for {@code java.lang.Boolean} instances
585     * that represent {@code true} or {@code 1237} for {@code java.lang.Boolean} instances
586     * that represent {@code false}.
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}
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} for a {@code boolean} array.
604     * </p>
605     *
606     * @param array
607     *            the array to add to the {@code hashCode}
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} for a {@code byte}.
626     * </p>
627     *
628     * @param value
629     *            the byte to add to the {@code hashCode}
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} for a {@code byte} array.
642     * </p>
643     *
644     * @param array
645     *            the array to add to the {@code hashCode}
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} for a {@code char}.
662     * </p>
663     *
664     * @param value
665     *            the char to add to the {@code hashCode}
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} for a {@code char} array.
676     * </p>
677     *
678     * @param array
679     *            the array to add to the {@code hashCode}
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} for a {@code double}.
696     * </p>
697     *
698     * @param value
699     *            the double to add to the {@code hashCode}
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} for a {@code double} array.
709     * </p>
710     *
711     * @param array
712     *            the array to add to the {@code hashCode}
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} for a {@code float}.
729     * </p>
730     *
731     * @param value
732     *            the float to add to the {@code hashCode}
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} for a {@code float} array.
743     * </p>
744     *
745     * @param array
746     *            the array to add to the {@code hashCode}
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} for an {@code int}.
763     * </p>
764     *
765     * @param value
766     *            the int to add to the {@code hashCode}
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} for an {@code int} array.
777     * </p>
778     *
779     * @param array
780     *            the array to add to the {@code hashCode}
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} for a {@code long}.
797     * </p>
798     *
799     * @param value
800     *            the long to add to the {@code hashCode}
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} for a {@code long} array.
815     * </p>
816     *
817     * @param array
818     *            the array to add to the {@code hashCode}
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} for an {@code Object}.
835     * </p>
836     *
837     * @param object
838     *            the Object to add to the {@code hashCode}
839     * @return this
840     */
841    public HashCodeBuilder append(final Object object) {
842        if (object == null) {
843            iTotal = iTotal * iConstant;
844
845        } else if (object.getClass().isArray()) {
846            // factor out array case in order to keep method small enough
847            // to be inlined
848            appendArray(object);
849        } else {
850            iTotal = iTotal * iConstant + object.hashCode();
851        }
852        return this;
853    }
854
855    /**
856     * <p>
857     * Append a {@code hashCode} for an array.
858     * </p>
859     *
860     * @param object
861     *            the array to add to the {@code hashCode}
862     */
863    private void appendArray(final Object object) {
864        // 'Switch' on type of array, to dispatch to the correct handler
865        // This handles multi dimensional arrays
866        if (object instanceof long[]) {
867            append((long[]) object);
868        } else if (object instanceof int[]) {
869            append((int[]) object);
870        } else if (object instanceof short[]) {
871            append((short[]) object);
872        } else if (object instanceof char[]) {
873            append((char[]) object);
874        } else if (object instanceof byte[]) {
875            append((byte[]) object);
876        } else if (object instanceof double[]) {
877            append((double[]) object);
878        } else if (object instanceof float[]) {
879            append((float[]) object);
880        } else if (object instanceof boolean[]) {
881            append((boolean[]) object);
882        } else {
883            // Not an array of primitives
884            append((Object[]) object);
885        }
886    }
887
888    /**
889     * <p>
890     * Append a {@code hashCode} for an {@code Object} array.
891     * </p>
892     *
893     * @param array
894     *            the array to add to the {@code hashCode}
895     * @return this
896     */
897    public HashCodeBuilder append(final Object[] array) {
898        if (array == null) {
899            iTotal = iTotal * iConstant;
900        } else {
901            for (final Object element : array) {
902                append(element);
903            }
904        }
905        return this;
906    }
907
908    /**
909     * <p>
910     * Append a {@code hashCode} for a {@code short}.
911     * </p>
912     *
913     * @param value
914     *            the short to add to the {@code hashCode}
915     * @return this
916     */
917    public HashCodeBuilder append(final short value) {
918        iTotal = iTotal * iConstant + value;
919        return this;
920    }
921
922    /**
923     * <p>
924     * Append a {@code hashCode} for a {@code short} array.
925     * </p>
926     *
927     * @param array
928     *            the array to add to the {@code hashCode}
929     * @return this
930     */
931    public HashCodeBuilder append(final short[] array) {
932        if (array == null) {
933            iTotal = iTotal * iConstant;
934        } else {
935            for (final short element : array) {
936                append(element);
937            }
938        }
939        return this;
940    }
941
942    /**
943     * <p>
944     * Adds the result of super.hashCode() to this builder.
945     * </p>
946     *
947     * @param superHashCode
948     *            the result of calling {@code super.hashCode()}
949     * @return this HashCodeBuilder, used to chain calls.
950     * @since 2.0
951     */
952    public HashCodeBuilder appendSuper(final int superHashCode) {
953        iTotal = iTotal * iConstant + superHashCode;
954        return this;
955    }
956
957    /**
958     * <p>
959     * Returns the computed {@code hashCode}.
960     * </p>
961     *
962     * @return {@code hashCode} based on the fields appended
963     */
964    public int toHashCode() {
965        return iTotal;
966    }
967
968    /**
969     * Returns the computed {@code hashCode}.
970     *
971     * @return {@code hashCode} based on the fields appended
972     *
973     * @since 3.0
974     */
975    @Override
976    public Integer build() {
977        return Integer.valueOf(toHashCode());
978    }
979
980    /**
981     * <p>
982     * The computed {@code hashCode} from toHashCode() is returned due to the likelihood
983     * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
984     * HashCodeBuilder itself is.</p>
985     *
986     * @return {@code hashCode} based on the fields appended
987     * @since 2.5
988     */
989    @Override
990    public int hashCode() {
991        return toHashCode();
992    }
993
994}