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