    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}