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