    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.Objects;
    027import java.util.Set;
    028
    029import org.apache.commons.lang3.ArraySorter;
    030import org.apache.commons.lang3.ArrayUtils;
    031import org.apache.commons.lang3.ObjectUtils;
    032import org.apache.commons.lang3.Validate;
    033
    034/**
    035 * Assists in implementing {@link Object#hashCode()} methods.
    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="https://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     * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
    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     * Returns the registry of objects being traversed by the reflection methods in the current thread.
    142     *
    143     * @return Set the registry of objects being traversed
    144     * @since 2.3
    145     */
    146    static Set<IDKey> getRegistry() {
    147        return REGISTRY.get();
    148    }
    149
    150    /**
    151     * Returns {@code true} if the registry contains the given object. Used by the reflection methods to avoid
    152     * infinite loops.
    153     *
    154     * @param value
    155     *            The object to lookup in the registry.
    156     * @return boolean {@code true} if the registry contains the given object.
    157     * @since 2.3
    158     */
    159    static boolean isRegistered(final Object value) {
    160        final Set<IDKey> registry = getRegistry();
    161        return registry != null && registry.contains(new IDKey(value));
    162    }
    163
    164    /**
    165     * Appends the fields and values defined by the given object of the given {@link Class}.
    166     *
    167     * @param object
    168     *            the object to append details of
    169     * @param clazz
    170     *            the class to append details of
    171     * @param builder
    172     *            the builder to append to
    173     * @param useTransients
    174     *            whether to use transient fields
    175     * @param excludeFields
    176     *            Collection of String field names to exclude from use in calculation of hash code
    177     */
    178    private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients,
    179            final String[] excludeFields) {
    180        if (isRegistered(object)) {
    181            return;
    182        }
    183        try {
    184            register(object);
    185            // The elements in the returned array are not sorted and are not in any particular order.
    186            final Field[] fields = ArraySorter.sort(clazz.getDeclaredFields(), Comparator.comparing(Field::getName));
    187            AccessibleObject.setAccessible(fields, true);
    188            for (final Field field : fields) {
    189                if (!ArrayUtils.contains(excludeFields, field.getName())
    190                    && !field.getName().contains("$")
    191                    && (useTransients || !Modifier.isTransient(field.getModifiers()))
    192                    && !Modifier.isStatic(field.getModifiers())
    193                    && !field.isAnnotationPresent(HashCodeExclude.class)) {
    194                    builder.append(Reflection.getUnchecked(field, object));
    195                }
    196            }
    197        } finally {
    198            unregister(object);
    199        }
    200    }
    201
    202    /**
    203     * Uses reflection to build a valid hash code from the fields of {@code object}.
    204     *
    205     * <p>
    206     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    207     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    208     * also not as efficient as testing explicitly.
    209     * </p>
    210     *
    211     * <p>
    212     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
    213     * {@link Object}.
    214     * </p>
    215     *
    216     * <p>
    217     * Static fields will not be tested. Superclass fields will be included.
    218     * </p>
    219     *
    220     * <p>
    221     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
    222     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
    223     * </p>
    224     *
    225     * @param initialNonZeroOddNumber
    226     *            a non-zero, odd number used as the initial value. This will be the returned
    227     *            value if no fields are found to include in the hash code
    228     * @param multiplierNonZeroOddNumber
    229     *            a non-zero, odd number used as the multiplier
    230     * @param object
    231     *            the Object to create a {@code hashCode} for
    232     * @return int hash code
    233     * @throws NullPointerException
    234     *             if the Object is {@code null}
    235     * @throws IllegalArgumentException
    236     *             if the number is zero or even
    237     *
    238     * @see HashCodeExclude
    239     */
    240    public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
    241        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
    242    }
    243
    244    /**
    245     * Uses reflection to build a valid hash code from the fields of {@code object}.
    246     *
    247     * <p>
    248     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    249     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    250     * also not as efficient as testing explicitly.
    251     * </p>
    252     *
    253     * <p>
    254     * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
    255     * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
    256     * </p>
    257     *
    258     * <p>
    259     * Static fields will not be tested. Superclass fields will be included.
    260     * </p>
    261     *
    262     * <p>
    263     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
    264     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
    265     * </p>
    266     *
    267     * @param initialNonZeroOddNumber
    268     *            a non-zero, odd number used as the initial value. This will be the returned
    269     *            value if no fields are found to include in the hash code
    270     * @param multiplierNonZeroOddNumber
    271     *            a non-zero, odd number used as the multiplier
    272     * @param object
    273     *            the Object to create a {@code hashCode} for
    274     * @param testTransients
    275     *            whether to include transient fields
    276     * @return int hash code
    277     * @throws NullPointerException
    278     *             if the Object is {@code null}
    279     * @throws IllegalArgumentException
    280     *             if the number is zero or even
    281     *
    282     * @see HashCodeExclude
    283     */
    284    public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
    285            final boolean testTransients) {
    286        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
    287    }
    288
    289    /**
    290     * Uses reflection to build a valid hash code from the fields of {@code object}.
    291     *
    292     * <p>
    293     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    294     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    295     * also not as efficient as testing explicitly.
    296     * </p>
    297     *
    298     * <p>
    299     * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
    300     * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
    301     * </p>
    302     *
    303     * <p>
    304     * Static fields will not be included. Superclass fields will be included up to and including the specified
    305     * superclass. A null superclass is treated as java.lang.Object.
    306     * </p>
    307     *
    308     * <p>
    309     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
    310     * however this is not vital. Prime numbers are preferred, especially for the multiplier.
    311     * </p>
    312     *
    313     * @param <T>
    314     *            the type of the object involved
    315     * @param initialNonZeroOddNumber
    316     *            a non-zero, odd number used as the initial value. This will be the returned
    317     *            value if no fields are found to include in the hash code
    318     * @param multiplierNonZeroOddNumber
    319     *            a non-zero, odd number used as the multiplier
    320     * @param object
    321     *            the Object to create a {@code hashCode} for
    322     * @param testTransients
    323     *            whether to include transient fields
    324     * @param reflectUpToClass
    325     *            the superclass to reflect up to (inclusive), may be {@code null}
    326     * @param excludeFields
    327     *            array of field names to exclude from use in calculation of hash code
    328     * @return int hash code
    329     * @throws NullPointerException
    330     *             if the Object is {@code null}
    331     * @throws IllegalArgumentException
    332     *             if the number is zero or even
    333     *
    334     * @see HashCodeExclude
    335     * @since 2.0
    336     */
    337    public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
    338            final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
    339        Objects.requireNonNull(object, "object");
    340        final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
    341        Class<?> clazz = object.getClass();
    342        reflectionAppend(object, clazz, builder, testTransients, excludeFields);
    343        while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
    344            clazz = clazz.getSuperclass();
    345            reflectionAppend(object, clazz, builder, testTransients, excludeFields);
    346        }
    347        return builder.toHashCode();
    348    }
    349
    350    /**
    351     * Uses reflection to build a valid hash code from the fields of {@code object}.
    352     *
    353     * <p>
    354     * This constructor uses two hard coded choices for the constants needed to build a hash code.
    355     * </p>
    356     *
    357     * <p>
    358     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    359     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    360     * also not as efficient as testing explicitly.
    361     * </p>
    362     *
    363     * <p>
    364     * If the TestTransients parameter is set to {@code true}, transient members will be tested, otherwise they
    365     * are ignored, as they are likely derived fields, and not part of the value of the {@link Object}.
    366     * </p>
    367     *
    368     * <p>
    369     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
    370     * in the hash code, the result of this method will be constant.
    371     * </p>
    372     *
    373     * @param object
    374     *            the Object to create a {@code hashCode} for
    375     * @param testTransients
    376     *            whether to include transient fields
    377     * @return int hash code
    378     * @throws NullPointerException
    379     *             if the object is {@code null}
    380     *
    381     * @see HashCodeExclude
    382     */
    383    public static int reflectionHashCode(final Object object, final boolean testTransients) {
    384        return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object,
    385                testTransients, null);
    386    }
    387
    388    /**
    389     * Uses reflection to build a valid hash code from the fields of {@code object}.
    390     *
    391     * <p>
    392     * This constructor uses two hard coded choices for the constants needed to build a hash code.
    393     * </p>
    394     *
    395     * <p>
    396     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    397     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    398     * also not as efficient as testing explicitly.
    399     * </p>
    400     *
    401     * <p>
    402     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
    403     * {@link Object}.
    404     * </p>
    405     *
    406     * <p>
    407     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
    408     * in the hash code, the result of this method will be constant.
    409     * </p>
    410     *
    411     * @param object
    412     *            the Object to create a {@code hashCode} for
    413     * @param excludeFields
    414     *            Collection of String field names to exclude from use in calculation of hash code
    415     * @return int hash code
    416     * @throws NullPointerException
    417     *             if the object is {@code null}
    418     *
    419     * @see HashCodeExclude
    420     */
    421    public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
    422        return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
    423    }
    424
    425    /**
    426     * Uses reflection to build a valid hash code from the fields of {@code object}.
    427     *
    428     * <p>
    429     * This constructor uses two hard coded choices for the constants needed to build a hash code.
    430     * </p>
    431     *
    432     * <p>
    433     * It uses {@code AccessibleObject.setAccessible} to gain access to private fields. This means that it will
    434     * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
    435     * also not as efficient as testing explicitly.
    436     * </p>
    437     *
    438     * <p>
    439     * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
    440     * {@link Object}.
    441     * </p>
    442     *
    443     * <p>
    444     * Static fields will not be tested. Superclass fields will be included. If no fields are found to include
    445     * in the hash code, the result of this method will be constant.
    446     * </p>
    447     *
    448     * @param object
    449     *            the Object to create a {@code hashCode} for
    450     * @param excludeFields
    451     *            array of field names to exclude from use in calculation of hash code
    452     * @return int hash code
    453     * @throws NullPointerException
    454     *             if the object is {@code null}
    455     *
    456     * @see HashCodeExclude
    457     */
    458    public static int reflectionHashCode(final Object object, final String... excludeFields) {
    459        return reflectionHashCode(DEFAULT_INITIAL_VALUE, DEFAULT_MULTIPLIER_VALUE, object, false,
    460                null, excludeFields);
    461    }
    462
    463    /**
    464     * Registers the given object. Used by the reflection methods to avoid infinite loops.
    465     *
    466     * @param value
    467     *            The object to register.
    468     */
    469    private static void register(final Object value) {
    470        Set<IDKey> registry = getRegistry();
    471        if (registry == null) {
    472            registry = new HashSet<>();
    473            REGISTRY.set(registry);
    474        }
    475        registry.add(new IDKey(value));
    476    }
    477
    478    /**
    479     * Unregisters the given object.
    480     *
    481     * <p>
    482     * Used by the reflection methods to avoid infinite loops.
    483     *
    484     * @param value
    485     *            The object to unregister.
    486     * @since 2.3
    487     */
    488    private static void unregister(final Object value) {
    489        final Set<IDKey> registry = getRegistry();
    490        if (registry != null) {
    491            registry.remove(new IDKey(value));
    492            if (registry.isEmpty()) {
    493                REGISTRY.remove();
    494            }
    495        }
    496    }
    497
    498    /**
    499     * Constant to use in building the hashCode.
    500     */
    501    private final int iConstant;
    502
    503    /**
    504     * Running total of the hashCode.
    505     */
    506    private int iTotal;
    507
    508    /**
    509     * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
    510     *
    511     */
    512    public HashCodeBuilder() {
    513        iConstant = 37;
    514        iTotal = 17;
    515    }
    516
    517    /**
    518     * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
    519     * however this is not vital.
    520     *
    521     * <p>
    522     * Prime numbers are preferred, especially for the multiplier.
    523     * </p>
    524     *
    525     * @param initialOddNumber
    526     *            an odd number used as the initial value
    527     * @param multiplierOddNumber
    528     *            an odd number used as the multiplier
    529     * @throws IllegalArgumentException
    530     *             if the number is even
    531     */
    532    public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
    533        Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
    534        Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
    535        iConstant = multiplierOddNumber;
    536        iTotal = initialOddNumber;
    537    }
    538
    539    /**
    540     * Append a {@code hashCode} for a {@code boolean}.
    541     *
    542     * <p>
    543     * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
    544     * </p>
    545     * <p>
    546     * This is in contrast to the standard {@code java.lang.Boolean.hashCode} handling, which computes
    547     * a {@code hashCode} value of {@code 1231} for {@code java.lang.Boolean} instances
    548     * that represent {@code true} or {@code 1237} for {@code java.lang.Boolean} instances
    549     * that represent {@code false}.
    550     * </p>
    551     * <p>
    552     * This is in accordance with the <i>Effective Java</i> design.
    553     * </p>
    554     *
    555     * @param value
    556     *            the boolean to add to the {@code hashCode}
    557     * @return this
    558     */
    559    public HashCodeBuilder append(final boolean value) {
    560        iTotal = iTotal * iConstant + (value ? 0 : 1);
    561        return this;
    562    }
    563
    564    /**
    565     * Append a {@code hashCode} for a {@code boolean} array.
    566     *
    567     * @param array
    568     *            the array to add to the {@code hashCode}
    569     * @return this
    570     */
    571    public HashCodeBuilder append(final boolean[] array) {
    572        if (array == null) {
    573            iTotal = iTotal * iConstant;
    574        } else {
    575            for (final boolean element : array) {
    576                append(element);
    577            }
    578        }
    579        return this;
    580    }
    581
    582    /**
    583     * Append a {@code hashCode} for a {@code byte}.
    584     *
    585     * @param value
    586     *            the byte to add to the {@code hashCode}
    587     * @return this
    588     */
    589    public HashCodeBuilder append(final byte value) {
    590        iTotal = iTotal * iConstant + value;
    591        return this;
    592    }
    593
    594    /**
    595     * Append a {@code hashCode} for a {@code byte} array.
    596     *
    597     * @param array
    598     *            the array to add to the {@code hashCode}
    599     * @return this
    600     */
    601    public HashCodeBuilder append(final byte[] array) {
    602        if (array == null) {
    603            iTotal = iTotal * iConstant;
    604        } else {
    605            for (final byte element : array) {
    606                append(element);
    607            }
    608        }
    609        return this;
    610    }
    611
    612    /**
    613     * Append a {@code hashCode} for a {@code char}.
    614     *
    615     * @param value
    616     *            the char to add to the {@code hashCode}
    617     * @return this
    618     */
    619    public HashCodeBuilder append(final char value) {
    620        iTotal = iTotal * iConstant + value;
    621        return this;
    622    }
    623
    624    /**
    625     * Append a {@code hashCode} for a {@code char} array.
    626     *
    627     * @param array
    628     *            the array to add to the {@code hashCode}
    629     * @return this
    630     */
    631    public HashCodeBuilder append(final char[] array) {
    632        if (array == null) {
    633            iTotal = iTotal * iConstant;
    634        } else {
    635            for (final char element : array) {
    636                append(element);
    637            }
    638        }
    639        return this;
    640    }
    641
    642    /**
    643     * Append a {@code hashCode} for a {@code double}.
    644     *
    645     * @param value
    646     *            the double to add to the {@code hashCode}
    647     * @return this
    648     */
    649    public HashCodeBuilder append(final double value) {
    650        return append(Double.doubleToLongBits(value));
    651    }
    652
    653    /**
    654     * Append a {@code hashCode} for a {@code double} array.
    655     *
    656     * @param array
    657     *            the array to add to the {@code hashCode}
    658     * @return this
    659     */
    660    public HashCodeBuilder append(final double[] array) {
    661        if (array == null) {
    662            iTotal = iTotal * iConstant;
    663        } else {
    664            for (final double element : array) {
    665                append(element);
    666            }
    667        }
    668        return this;
    669    }
    670
    671    /**
    672     * Append a {@code hashCode} for a {@code float}.
    673     *
    674     * @param value
    675     *            the float to add to the {@code hashCode}
    676     * @return this
    677     */
    678    public HashCodeBuilder append(final float value) {
    679        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
    680        return this;
    681    }
    682
    683    /**
    684     * Append a {@code hashCode} for a {@code float} array.
    685     *
    686     * @param array
    687     *            the array to add to the {@code hashCode}
    688     * @return this
    689     */
    690    public HashCodeBuilder append(final float[] array) {
    691        if (array == null) {
    692            iTotal = iTotal * iConstant;
    693        } else {
    694            for (final float element : array) {
    695                append(element);
    696            }
    697        }
    698        return this;
    699    }
    700
    701    /**
    702     * Append a {@code hashCode} for an {@code int}.
    703     *
    704     * @param value
    705     *            the int to add to the {@code hashCode}
    706     * @return this
    707     */
    708    public HashCodeBuilder append(final int value) {
    709        iTotal = iTotal * iConstant + value;
    710        return this;
    711    }
    712
    713    /**
    714     * Append a {@code hashCode} for an {@code int} array.
    715     *
    716     * @param array
    717     *            the array to add to the {@code hashCode}
    718     * @return this
    719     */
    720    public HashCodeBuilder append(final int[] array) {
    721        if (array == null) {
    722            iTotal = iTotal * iConstant;
    723        } else {
    724            for (final int element : array) {
    725                append(element);
    726            }
    727        }
    728        return this;
    729    }
    730
    731    /**
    732     * Append a {@code hashCode} for a {@code long}.
    733     *
    734     * @param value
    735     *            the long to add to the {@code hashCode}
    736     * @return this
    737     */
    738    // NOTE: This method uses >> and not >>> as Effective Java and
    739    //       Long.hashCode do. Ideally we should switch to >>> at
    740    //       some stage. There are backwards compat issues, so
    741    //       that will have to wait for the time being. cf LANG-342.
    742    public HashCodeBuilder append(final long value) {
    743        iTotal = iTotal * iConstant + (int) (value ^ value >> 32);
    744        return this;
    745    }
    746
    747    /**
    748     * Append a {@code hashCode} for a {@code long} array.
    749     *
    750     * @param array
    751     *            the array to add to the {@code hashCode}
    752     * @return this
    753     */
    754    public HashCodeBuilder append(final long[] array) {
    755        if (array == null) {
    756            iTotal = iTotal * iConstant;
    757        } else {
    758            for (final long element : array) {
    759                append(element);
    760            }
    761        }
    762        return this;
    763    }
    764
    765    /**
    766     * Append a {@code hashCode} for an {@link Object}.
    767     *
    768     * @param object
    769     *            the Object to add to the {@code hashCode}
    770     * @return this
    771     */
    772    public HashCodeBuilder append(final Object object) {
    773        if (object == null) {
    774            iTotal = iTotal * iConstant;
    775
    776        } else if (ObjectUtils.isArray(object)) {
    777            // factor out array case in order to keep method small enough
    778            // to be inlined
    779            appendArray(object);
    780        } else {
    781            iTotal = iTotal * iConstant + object.hashCode();
    782        }
    783        return this;
    784    }
    785
    786    /**
    787     * Append a {@code hashCode} for an {@link Object} array.
    788     *
    789     * @param array
    790     *            the array to add to the {@code hashCode}
    791     * @return this
    792     */
    793    public HashCodeBuilder append(final Object[] array) {
    794        if (array == null) {
    795            iTotal = iTotal * iConstant;
    796        } else {
    797            for (final Object element : array) {
    798                append(element);
    799            }
    800        }
    801        return this;
    802    }
    803
    804    /**
    805     * Append a {@code hashCode} for a {@code short}.
    806     *
    807     * @param value
    808     *            the short to add to the {@code hashCode}
    809     * @return this
    810     */
    811    public HashCodeBuilder append(final short value) {
    812        iTotal = iTotal * iConstant + value;
    813        return this;
    814    }
    815
    816    /**
    817     * Append a {@code hashCode} for a {@code short} array.
    818     *
    819     * @param array
    820     *            the array to add to the {@code hashCode}
    821     * @return this
    822     */
    823    public HashCodeBuilder append(final short[] array) {
    824        if (array == null) {
    825            iTotal = iTotal * iConstant;
    826        } else {
    827            for (final short element : array) {
    828                append(element);
    829            }
    830        }
    831        return this;
    832    }
    833
    834    /**
    835     * Append a {@code hashCode} for an array.
    836     *
    837     * @param object
    838     *            the array to add to the {@code hashCode}
    839     */
    840    private void appendArray(final Object object) {
    841        // 'Switch' on type of array, to dispatch to the correct handler
    842        // This handles multidimensional arrays
    843        if (object instanceof long[]) {
    844            append((long[]) object);
    845        } else if (object instanceof int[]) {
    846            append((int[]) object);
    847        } else if (object instanceof short[]) {
    848            append((short[]) object);
    849        } else if (object instanceof char[]) {
    850            append((char[]) object);
    851        } else if (object instanceof byte[]) {
    852            append((byte[]) object);
    853        } else if (object instanceof double[]) {
    854            append((double[]) object);
    855        } else if (object instanceof float[]) {
    856            append((float[]) object);
    857        } else if (object instanceof boolean[]) {
    858            append((boolean[]) object);
    859        } else {
    860            // Not an array of primitives
    861            append((Object[]) object);
    862        }
    863    }
    864
    865    /**
    866     * Adds the result of super.hashCode() to this builder.
    867     *
    868     * @param superHashCode
    869     *            the result of calling {@code super.hashCode()}
    870     * @return this
    871     * @since 2.0
    872     */
    873    public HashCodeBuilder appendSuper(final int superHashCode) {
    874        iTotal = iTotal * iConstant + superHashCode;
    875        return this;
    876    }
    877
    878    /**
    879     * Returns the computed {@code hashCode}.
    880     *
    881     * @return {@code hashCode} based on the fields appended
    882     * @since 3.0
    883     */
    884    @Override
    885    public Integer build() {
    886        return Integer.valueOf(toHashCode());
    887    }
    888
    889    /**
    890     * Implements equals using the hash code.
    891     *
    892     * @since 3.13.0
    893     */
    894    @Override
    895    public boolean equals(final Object obj) {
    896        if (this == obj) {
    897            return true;
    898        }
    899        if (!(obj instanceof HashCodeBuilder)) {
    900            return false;
    901        }
    902        final HashCodeBuilder other = (HashCodeBuilder) obj;
    903        return iTotal == other.iTotal;
    904    }
    905
    906    /**
    907     * The computed {@code hashCode} from toHashCode() is returned due to the likelihood
    908     * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
    909     * HashCodeBuilder itself is.
    910     *
    911     * @return {@code hashCode} based on the fields appended
    912     * @since 2.5
    913     */
    914    @Override
    915    public int hashCode() {
    916        return toHashCode();
    917    }
    918
    919    /**
    920     * Returns the computed {@code hashCode}.
    921     *
    922     * @return {@code hashCode} based on the fields appended
    923     */
    924    public int toHashCode() {
    925        return iTotal;
    926    }
    927
    928}