    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 *      https://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 = ThreadLocal.withInitial(HashSet::new);
    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     * Gets 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     * Tests whether 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        getRegistry().add(new IDKey(value));
    471    }
    472
    473    /**
    474     * Unregisters the given object.
    475     *
    476     * <p>
    477     * Used by the reflection methods to avoid infinite loops.
    478     * </p>
    479     *
    480     * @param value
    481     *            The object to unregister.
    482     * @since 2.3
    483     */
    484    private static void unregister(final Object value) {
    485        final Set<IDKey> registry = getRegistry();
    486        registry.remove(new IDKey(value));
    487        if (registry.isEmpty()) {
    488            REGISTRY.remove();
    489        }
    490    }
    491
    492    /**
    493     * Constant to use in building the hashCode.
    494     */
    495    private final int iConstant;
    496
    497    /**
    498     * Running total of the hashCode.
    499     */
    500    private int iTotal;
    501
    502    /**
    503     * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
    504     */
    505    public HashCodeBuilder() {
    506        iConstant = 37;
    507        iTotal = 17;
    508    }
    509
    510    /**
    511     * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
    512     * however this is not vital.
    513     *
    514     * <p>
    515     * Prime numbers are preferred, especially for the multiplier.
    516     * </p>
    517     *
    518     * @param initialOddNumber
    519     *            an odd number used as the initial value
    520     * @param multiplierOddNumber
    521     *            an odd number used as the multiplier
    522     * @throws IllegalArgumentException
    523     *             if the number is even
    524     */
    525    public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
    526        Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
    527        Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
    528        iConstant = multiplierOddNumber;
    529        iTotal = initialOddNumber;
    530    }
    531
    532    /**
    533     * Append a {@code hashCode} for a {@code boolean}.
    534     *
    535     * <p>
    536     * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
    537     * </p>
    538     * <p>
    539     * This is in contrast to the standard {@link Boolean#hashCode()} handling, which computes
    540     * a {@code hashCode} value of {@code 1231} for {@link Boolean} instances
    541     * that represent {@code true} or {@code 1237} for {@link Boolean} instances
    542     * that represent {@code false}.
    543     * </p>
    544     * <p>
    545     * This is in accordance with the <em>Effective Java</em> design.
    546     * </p>
    547     *
    548     * @param value
    549     *            the boolean to add to the {@code hashCode}
    550     * @return {@code this} instance.
    551     */
    552    public HashCodeBuilder append(final boolean value) {
    553        iTotal = iTotal * iConstant + (value ? 0 : 1);
    554        return this;
    555    }
    556
    557    /**
    558     * Append a {@code hashCode} for a {@code boolean} array.
    559     *
    560     * @param array
    561     *            the array to add to the {@code hashCode}
    562     * @return {@code this} instance.
    563     */
    564    public HashCodeBuilder append(final boolean[] array) {
    565        if (array == null) {
    566            iTotal = iTotal * iConstant;
    567        } else {
    568            for (final boolean element : array) {
    569                append(element);
    570            }
    571        }
    572        return this;
    573    }
    574
    575    /**
    576     * Append a {@code hashCode} for a {@code byte}.
    577     *
    578     * @param value
    579     *            the byte to add to the {@code hashCode}
    580     * @return {@code this} instance.
    581     */
    582    public HashCodeBuilder append(final byte value) {
    583        iTotal = iTotal * iConstant + value;
    584        return this;
    585    }
    586
    587    /**
    588     * Append a {@code hashCode} for a {@code byte} array.
    589     *
    590     * @param array
    591     *            the array to add to the {@code hashCode}
    592     * @return {@code this} instance.
    593     */
    594    public HashCodeBuilder append(final byte[] array) {
    595        if (array == null) {
    596            iTotal = iTotal * iConstant;
    597        } else {
    598            for (final byte element : array) {
    599                append(element);
    600            }
    601        }
    602        return this;
    603    }
    604
    605    /**
    606     * Append a {@code hashCode} for a {@code char}.
    607     *
    608     * @param value
    609     *            the char to add to the {@code hashCode}
    610     * @return {@code this} instance.
    611     */
    612    public HashCodeBuilder append(final char value) {
    613        iTotal = iTotal * iConstant + value;
    614        return this;
    615    }
    616
    617    /**
    618     * Append a {@code hashCode} for a {@code char} array.
    619     *
    620     * @param array
    621     *            the array to add to the {@code hashCode}
    622     * @return {@code this} instance.
    623     */
    624    public HashCodeBuilder append(final char[] array) {
    625        if (array == null) {
    626            iTotal = iTotal * iConstant;
    627        } else {
    628            for (final char element : array) {
    629                append(element);
    630            }
    631        }
    632        return this;
    633    }
    634
    635    /**
    636     * Append a {@code hashCode} for a {@code double}.
    637     *
    638     * @param value
    639     *            the double to add to the {@code hashCode}
    640     * @return {@code this} instance.
    641     */
    642    public HashCodeBuilder append(final double value) {
    643        return append(Double.doubleToLongBits(value));
    644    }
    645
    646    /**
    647     * Append a {@code hashCode} for a {@code double} array.
    648     *
    649     * @param array
    650     *            the array to add to the {@code hashCode}
    651     * @return {@code this} instance.
    652     */
    653    public HashCodeBuilder append(final double[] array) {
    654        if (array == null) {
    655            iTotal = iTotal * iConstant;
    656        } else {
    657            for (final double element : array) {
    658                append(element);
    659            }
    660        }
    661        return this;
    662    }
    663
    664    /**
    665     * Append a {@code hashCode} for a {@code float}.
    666     *
    667     * @param value
    668     *            the float to add to the {@code hashCode}
    669     * @return {@code this} instance.
    670     */
    671    public HashCodeBuilder append(final float value) {
    672        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
    673        return this;
    674    }
    675
    676    /**
    677     * Append a {@code hashCode} for a {@code float} array.
    678     *
    679     * @param array
    680     *            the array to add to the {@code hashCode}
    681     * @return {@code this} instance.
    682     */
    683    public HashCodeBuilder append(final float[] array) {
    684        if (array == null) {
    685            iTotal = iTotal * iConstant;
    686        } else {
    687            for (final float element : array) {
    688                append(element);
    689            }
    690        }
    691        return this;
    692    }
    693
    694    /**
    695     * Append a {@code hashCode} for an {@code int}.
    696     *
    697     * @param value
    698     *            the int to add to the {@code hashCode}
    699     * @return {@code this} instance.
    700     */
    701    public HashCodeBuilder append(final int value) {
    702        iTotal = iTotal * iConstant + value;
    703        return this;
    704    }
    705
    706    /**
    707     * Append a {@code hashCode} for an {@code int} array.
    708     *
    709     * @param array
    710     *            the array to add to the {@code hashCode}
    711     * @return {@code this} instance.
    712     */
    713    public HashCodeBuilder append(final int[] array) {
    714        if (array == null) {
    715            iTotal = iTotal * iConstant;
    716        } else {
    717            for (final int element : array) {
    718                append(element);
    719            }
    720        }
    721        return this;
    722    }
    723
    724    /**
    725     * Append a {@code hashCode} for a {@code long}.
    726     *
    727     * @param value
    728     *            the long to add to the {@code hashCode}
    729     * @return {@code this} instance.
    730     */
    731    // NOTE: This method uses >> and not >>> as Effective Java and
    732    //       Long.hashCode do. Ideally we should switch to >>> at
    733    //       some stage. There are backwards compat issues, so
    734    //       that will have to wait for the time being. cf LANG-342.
    735    public HashCodeBuilder append(final long value) {
    736        iTotal = iTotal * iConstant + (int) (value ^ value >> 32);
    737        return this;
    738    }
    739
    740    /**
    741     * Append a {@code hashCode} for a {@code long} array.
    742     *
    743     * @param array
    744     *            the array to add to the {@code hashCode}
    745     * @return {@code this} instance.
    746     */
    747    public HashCodeBuilder append(final long[] array) {
    748        if (array == null) {
    749            iTotal = iTotal * iConstant;
    750        } else {
    751            for (final long element : array) {
    752                append(element);
    753            }
    754        }
    755        return this;
    756    }
    757
    758    /**
    759     * Append a {@code hashCode} for an {@link Object}.
    760     *
    761     * @param object
    762     *            the Object to add to the {@code hashCode}
    763     * @return {@code this} instance.
    764     */
    765    public HashCodeBuilder append(final Object object) {
    766        if (object == null) {
    767            iTotal = iTotal * iConstant;
    768
    769        } else if (ObjectUtils.isArray(object)) {
    770            // factor out array case in order to keep method small enough
    771            // to be inlined
    772            appendArray(object);
    773        } else {
    774            iTotal = iTotal * iConstant + object.hashCode();
    775        }
    776        return this;
    777    }
    778
    779    /**
    780     * Append a {@code hashCode} for an {@link Object} array.
    781     *
    782     * @param array
    783     *            the array to add to the {@code hashCode}
    784     * @return {@code this} instance.
    785     */
    786    public HashCodeBuilder append(final Object[] array) {
    787        if (array == null) {
    788            iTotal = iTotal * iConstant;
    789        } else {
    790            for (final Object element : array) {
    791                append(element);
    792            }
    793        }
    794        return this;
    795    }
    796
    797    /**
    798     * Append a {@code hashCode} for a {@code short}.
    799     *
    800     * @param value
    801     *            the short to add to the {@code hashCode}
    802     * @return {@code this} instance.
    803     */
    804    public HashCodeBuilder append(final short value) {
    805        iTotal = iTotal * iConstant + value;
    806        return this;
    807    }
    808
    809    /**
    810     * Append a {@code hashCode} for a {@code short} array.
    811     *
    812     * @param array
    813     *            the array to add to the {@code hashCode}
    814     * @return {@code this} instance.
    815     */
    816    public HashCodeBuilder append(final short[] array) {
    817        if (array == null) {
    818            iTotal = iTotal * iConstant;
    819        } else {
    820            for (final short element : array) {
    821                append(element);
    822            }
    823        }
    824        return this;
    825    }
    826
    827    /**
    828     * Append a {@code hashCode} for an array.
    829     *
    830     * @param object
    831     *            the array to add to the {@code hashCode}
    832     */
    833    private void appendArray(final Object object) {
    834        // 'Switch' on type of array, to dispatch to the correct handler
    835        // This handles multidimensional arrays
    836        if (object instanceof long[]) {
    837            append((long[]) object);
    838        } else if (object instanceof int[]) {
    839            append((int[]) object);
    840        } else if (object instanceof short[]) {
    841            append((short[]) object);
    842        } else if (object instanceof char[]) {
    843            append((char[]) object);
    844        } else if (object instanceof byte[]) {
    845            append((byte[]) object);
    846        } else if (object instanceof double[]) {
    847            append((double[]) object);
    848        } else if (object instanceof float[]) {
    849            append((float[]) object);
    850        } else if (object instanceof boolean[]) {
    851            append((boolean[]) object);
    852        } else {
    853            // Not an array of primitives
    854            append((Object[]) object);
    855        }
    856    }
    857
    858    /**
    859     * Adds the result of super.hashCode() to this builder.
    860     *
    861     * @param superHashCode
    862     *            the result of calling {@code super.hashCode()}
    863     * @return {@code this} instance.
    864     * @since 2.0
    865     */
    866    public HashCodeBuilder appendSuper(final int superHashCode) {
    867        iTotal = iTotal * iConstant + superHashCode;
    868        return this;
    869    }
    870
    871    /**
    872     * Returns the computed {@code hashCode}.
    873     *
    874     * @return {@code hashCode} based on the fields appended
    875     * @since 3.0
    876     */
    877    @Override
    878    public Integer build() {
    879        return Integer.valueOf(toHashCode());
    880    }
    881
    882    /**
    883     * Implements equals using the hash code.
    884     *
    885     * @since 3.13.0
    886     */
    887    @Override
    888    public boolean equals(final Object obj) {
    889        if (this == obj) {
    890            return true;
    891        }
    892        if (!(obj instanceof HashCodeBuilder)) {
    893            return false;
    894        }
    895        final HashCodeBuilder other = (HashCodeBuilder) obj;
    896        return iTotal == other.iTotal;
    897    }
    898
    899    /**
    900     * The computed {@code hashCode} from toHashCode() is returned due to the likelihood
    901     * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
    902     * HashCodeBuilder itself is.
    903     *
    904     * @return {@code hashCode} based on the fields appended
    905     * @since 2.5
    906     */
    907    @Override
    908    public int hashCode() {
    909        return toHashCode();
    910    }
    911
    912    /**
    913     * Returns the computed {@code hashCode}.
    914     *
    915     * @return {@code hashCode} based on the fields appended
    916     */
    917    public int toHashCode() {
    918        return iTotal;
    919    }
    920
    921}