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 = ThreadLocal.withInitial(HashSet::new);
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        getRegistry().add(new IDKey(value));
471    }
472
473    /**
474     * Unregisters the given object.
475     *
476     * <p>
477     * Used by the reflection methods to avoid infinite loops.
478     * </p>
479     *
480     * @param value
481     *            The object to unregister.
482     * @since 2.3
483     */
484    private static void unregister(final Object value) {
485        final Set<IDKey> registry = getRegistry();
486        registry.remove(new IDKey(value));
487        if (registry.isEmpty()) {
488            REGISTRY.remove();
489        }
490    }
491
492    /**
493     * Constant to use in building the hashCode.
494     */
495    private final int iConstant;
496
497    /**
498     * Running total of the hashCode.
499     */
500    private int iTotal;
501
502    /**
503     * Uses two hard coded choices for the constants needed to build a {@code hashCode}.
504     */
505    public HashCodeBuilder() {
506        iConstant = 37;
507        iTotal = 17;
508    }
509
510    /**
511     * Two randomly chosen, odd numbers must be passed in. Ideally these should be different for each class,
512     * however this is not vital.
513     *
514     * <p>
515     * Prime numbers are preferred, especially for the multiplier.
516     * </p>
517     *
518     * @param initialOddNumber
519     *            an odd number used as the initial value
520     * @param multiplierOddNumber
521     *            an odd number used as the multiplier
522     * @throws IllegalArgumentException
523     *             if the number is even
524     */
525    public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
526        Validate.isTrue(initialOddNumber % 2 != 0, "HashCodeBuilder requires an odd initial value");
527        Validate.isTrue(multiplierOddNumber % 2 != 0, "HashCodeBuilder requires an odd multiplier");
528        iConstant = multiplierOddNumber;
529        iTotal = initialOddNumber;
530    }
531
532    /**
533     * Append a {@code hashCode} for a {@code boolean}.
534     *
535     * <p>
536     * This adds {@code 1} when true, and {@code 0} when false to the {@code hashCode}.
537     * </p>
538     * <p>
539     * This is in contrast to the standard {@link Boolean#hashCode()} handling, which computes
540     * a {@code hashCode} value of {@code 1231} for {@link Boolean} instances
541     * that represent {@code true} or {@code 1237} for {@link Boolean} instances
542     * that represent {@code false}.
543     * </p>
544     * <p>
545     * This is in accordance with the <em>Effective Java</em> design.
546     * </p>
547     *
548     * @param value
549     *            the boolean to add to the {@code hashCode}
550     * @return {@code this} instance.
551     */
552    public HashCodeBuilder append(final boolean value) {
553        iTotal = iTotal * iConstant + (value ? 0 : 1);
554        return this;
555    }
556
557    /**
558     * Append a {@code hashCode} for a {@code boolean} array.
559     *
560     * @param array
561     *            the array to add to the {@code hashCode}
562     * @return {@code this} instance.
563     */
564    public HashCodeBuilder append(final boolean[] array) {
565        if (array == null) {
566            iTotal = iTotal * iConstant;
567        } else {
568            for (final boolean element : array) {
569                append(element);
570            }
571        }
572        return this;
573    }
574
575    /**
576     * Append a {@code hashCode} for a {@code byte}.
577     *
578     * @param value
579     *            the byte to add to the {@code hashCode}
580     * @return {@code this} instance.
581     */
582    public HashCodeBuilder append(final byte value) {
583        iTotal = iTotal * iConstant + value;
584        return this;
585    }
586
587    /**
588     * Append a {@code hashCode} for a {@code byte} array.
589     *
590     * @param array
591     *            the array to add to the {@code hashCode}
592     * @return {@code this} instance.
593     */
594    public HashCodeBuilder append(final byte[] array) {
595        if (array == null) {
596            iTotal = iTotal * iConstant;
597        } else {
598            for (final byte element : array) {
599                append(element);
600            }
601        }
602        return this;
603    }
604
605    /**
606     * Append a {@code hashCode} for a {@code char}.
607     *
608     * @param value
609     *            the char to add to the {@code hashCode}
610     * @return {@code this} instance.
611     */
612    public HashCodeBuilder append(final char value) {
613        iTotal = iTotal * iConstant + value;
614        return this;
615    }
616
617    /**
618     * Append a {@code hashCode} for a {@code char} array.
619     *
620     * @param array
621     *            the array to add to the {@code hashCode}
622     * @return {@code this} instance.
623     */
624    public HashCodeBuilder append(final char[] array) {
625        if (array == null) {
626            iTotal = iTotal * iConstant;
627        } else {
628            for (final char element : array) {
629                append(element);
630            }
631        }
632        return this;
633    }
634
635    /**
636     * Append a {@code hashCode} for a {@code double}.
637     *
638     * @param value
639     *            the double to add to the {@code hashCode}
640     * @return {@code this} instance.
641     */
642    public HashCodeBuilder append(final double value) {
643        return append(Double.doubleToLongBits(value));
644    }
645
646    /**
647     * Append a {@code hashCode} for a {@code double} array.
648     *
649     * @param array
650     *            the array to add to the {@code hashCode}
651     * @return {@code this} instance.
652     */
653    public HashCodeBuilder append(final double[] array) {
654        if (array == null) {
655            iTotal = iTotal * iConstant;
656        } else {
657            for (final double element : array) {
658                append(element);
659            }
660        }
661        return this;
662    }
663
664    /**
665     * Append a {@code hashCode} for a {@code float}.
666     *
667     * @param value
668     *            the float to add to the {@code hashCode}
669     * @return {@code this} instance.
670     */
671    public HashCodeBuilder append(final float value) {
672        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
673        return this;
674    }
675
676    /**
677     * Append a {@code hashCode} for a {@code float} array.
678     *
679     * @param array
680     *            the array to add to the {@code hashCode}
681     * @return {@code this} instance.
682     */
683    public HashCodeBuilder append(final float[] array) {
684        if (array == null) {
685            iTotal = iTotal * iConstant;
686        } else {
687            for (final float element : array) {
688                append(element);
689            }
690        }
691        return this;
692    }
693
694    /**
695     * Append a {@code hashCode} for an {@code int}.
696     *
697     * @param value
698     *            the int to add to the {@code hashCode}
699     * @return {@code this} instance.
700     */
701    public HashCodeBuilder append(final int value) {
702        iTotal = iTotal * iConstant + value;
703        return this;
704    }
705
706    /**
707     * Append a {@code hashCode} for an {@code int} array.
708     *
709     * @param array
710     *            the array to add to the {@code hashCode}
711     * @return {@code this} instance.
712     */
713    public HashCodeBuilder append(final int[] array) {
714        if (array == null) {
715            iTotal = iTotal * iConstant;
716        } else {
717            for (final int element : array) {
718                append(element);
719            }
720        }
721        return this;
722    }
723
724    /**
725     * Append a {@code hashCode} for a {@code long}.
726     *
727     * @param value
728     *            the long to add to the {@code hashCode}
729     * @return {@code this} instance.
730     */
731    // NOTE: This method uses >> and not >>> as Effective Java and
732    //       Long.hashCode do. Ideally we should switch to >>> at
733    //       some stage. There are backwards compat issues, so
734    //       that will have to wait for the time being. cf LANG-342.
735    public HashCodeBuilder append(final long value) {
736        iTotal = iTotal * iConstant + (int) (value ^ value >> 32);
737        return this;
738    }
739
740    /**
741     * Append a {@code hashCode} for a {@code long} array.
742     *
743     * @param array
744     *            the array to add to the {@code hashCode}
745     * @return {@code this} instance.
746     */
747    public HashCodeBuilder append(final long[] array) {
748        if (array == null) {
749            iTotal = iTotal * iConstant;
750        } else {
751            for (final long element : array) {
752                append(element);
753            }
754        }
755        return this;
756    }
757
758    /**
759     * Append a {@code hashCode} for an {@link Object}.
760     *
761     * @param object
762     *            the Object to add to the {@code hashCode}
763     * @return {@code this} instance.
764     */
765    public HashCodeBuilder append(final Object object) {
766        if (object == null) {
767            iTotal = iTotal * iConstant;
768
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            iTotal = iTotal * iConstant + 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            iTotal = iTotal * iConstant;
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        iTotal = iTotal * iConstant + 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            iTotal = iTotal * iConstant;
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        iTotal = iTotal * iConstant + 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 iTotal == other.iTotal;
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 iTotal;
919    }
920
921}