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