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