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