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