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