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