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