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