1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.lang.builder;
19 
20 import java.lang.reflect.AccessibleObject;
21 import java.lang.reflect.Field;
22 import java.lang.reflect.Modifier;
23 import java.util.Collection;
24 import java.util.HashSet;
25 import java.util.Set;
26 
27 import org.apache.commons.lang.ArrayUtils;
28 
29 /**
30  * <p>
31  * Assists in implementing {@link Object#hashCode()} methods.
32  * </p>
33  *
34  * <p>
35  * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in
36  * the book <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> by Joshua Bloch. Writing a
37  * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process.
38  * </p>
39  *
40  * <p>
41  * The following is the approach taken. When appending a data field, the current total is multiplied by the
42  * multiplier then a relevant value
43  * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
44  * appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.
45  * </p>
46  *
47  * <p>
48  * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be
49  * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code>
50  * method.
51  * </p>
52  *
53  * <p>
54  * To use this class write code as follows:
55  * </p>
56  *
57  * <pre>
58  * public class Person {
59  *   String name;
60  *   int age;
61  *   boolean smoker;
62  *   ...
63  *
64  *   public int hashCode() {
65  *     // you pick a hard-coded, randomly chosen, non-zero, odd number
66  *     // ideally different for each class
67  *     return new HashCodeBuilder(17, 37).
68  *       append(name).
69  *       append(age).
70  *       append(smoker).
71  *       toHashCode();
72  *   }
73  * }
74  * </pre>
75  *
76  * <p>
77  * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}.
78  * </p>
79  *
80  * <p>
81  * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
82  * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code>
83  * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
84  * are set up correctly. It is also slower than testing explicitly.
85  * </p>
86  *
87  * <p>
88  * A typical invocation for this method would look like:
89  * </p>
90  *
91  * <pre>
92  * public int hashCode() {
93  *   return HashCodeBuilder.reflectionHashCode(this);
94  * }
95  * </pre>
96  *
97  * @author Apache Software Foundation
98  * @author Gary Gregory
99  * @author Pete Gieser
100  * @since 1.0
101  * @version $Id: HashCodeBuilder.java 1057009 2011-01-09 19:48:06Z niallp $
102  */
103 public class HashCodeBuilder {
104     /**
105      * <p>
106      * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
107      * </p>
108      *
109      * @since 2.3
110      */
111     private static final ThreadLocal REGISTRY = new ThreadLocal();
112 
113     /*
114      * N.B. we cannot store the actual objects in a HashSet, as that would use the very hashCode()
115      * we are in the process of calculating.
116      *
117      * So we generate a one-to-one mapping from the original object to a new object.
118      *
119      * Now HashSet uses equals() to determine if two elements with the same hashcode really
120      * are equal, so we also need to ensure that the replacement objects are only equal
121      * if the original objects are identical.
122      *
123      * The original implementation (2.4 and before) used the System.indentityHashCode()
124      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
125      *
126      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
127      * to disambiguate the duplicate ids.
128      */
129 
130     /**
131      * <p>
132      * Returns the registry of objects being traversed by the reflection methods in the current thread.
133      * </p>
134      *
135      * @return Set the registry of objects being traversed
136      * @since 2.3
137      */
getRegistry()138     static Set getRegistry() {
139         return (Set) REGISTRY.get();
140     }
141 
142     /**
143      * <p>
144      * Returns <code>true</code> if the registry contains the given object. Used by the reflection methods to avoid
145      * infinite loops.
146      * </p>
147      *
148      * @param value
149      *            The object to lookup in the registry.
150      * @return boolean <code>true</code> if the registry contains the given object.
151      * @since 2.3
152      */
isRegistered(Object value)153     static boolean isRegistered(Object value) {
154         Set registry = getRegistry();
155         return registry != null && registry.contains(new IDKey(value));
156     }
157 
158     /**
159      * <p>
160      * Appends the fields and values defined by the given object of the given <code>Class</code>.
161      * </p>
162      *
163      * @param object
164      *            the object to append details of
165      * @param clazz
166      *            the class to append details of
167      * @param builder
168      *            the builder to append to
169      * @param useTransients
170      *            whether to use transient fields
171      * @param excludeFields
172      *            Collection of String field names to exclude from use in calculation of hash code
173      */
reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients, String[] excludeFields)174     private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients,
175             String[] excludeFields) {
176         if (isRegistered(object)) {
177             return;
178         }
179         try {
180             register(object);
181             Field[] fields = clazz.getDeclaredFields();
182             AccessibleObject.setAccessible(fields, true);
183             for (int i = 0; i < fields.length; i++) {
184                 Field field = fields[i];
185                 if (!ArrayUtils.contains(excludeFields, field.getName())
186                     && (field.getName().indexOf('$') == -1)
187                     && (useTransients || !Modifier.isTransient(field.getModifiers()))
188                     && (!Modifier.isStatic(field.getModifiers()))) {
189                     try {
190                         Object fieldValue = field.get(object);
191                         builder.append(fieldValue);
192                     } catch (IllegalAccessException e) {
193                         // this can't happen. Would get a Security exception instead
194                         // throw a runtime exception in case the impossible happens.
195                         throw new InternalError("Unexpected IllegalAccessException");
196                     }
197                 }
198             }
199         } finally {
200             unregister(object);
201         }
202     }
203 
204     /**
205      * <p>
206      * This method uses reflection to build a valid hash code.
207      * </p>
208      *
209      * <p>
210      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
211      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
212      * also not as efficient as testing explicitly.
213      * </p>
214      *
215      * <p>
216      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
217      * <code>Object</code>.
218      * </p>
219      *
220      * <p>
221      * Static fields will not be tested. Superclass fields will be included.
222      * </p>
223      *
224      * <p>
225      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
226      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
227      * </p>
228      *
229      * @param initialNonZeroOddNumber
230      *            a non-zero, odd number used as the initial value
231      * @param multiplierNonZeroOddNumber
232      *            a non-zero, odd number used as the multiplier
233      * @param object
234      *            the Object to create a <code>hashCode</code> for
235      * @return int hash code
236      * @throws IllegalArgumentException
237      *             if the Object is <code>null</code>
238      * @throws IllegalArgumentException
239      *             if the number is zero or even
240      */
reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object)241     public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
242         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null, null);
243     }
244 
245     /**
246      * <p>
247      * This method uses reflection to build a valid hash code.
248      * </p>
249      *
250      * <p>
251      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
252      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
253      * also not as efficient as testing explicitly.
254      * </p>
255      *
256      * <p>
257      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
258      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
259      * </p>
260      *
261      * <p>
262      * Static fields will not be tested. Superclass fields will be included.
263      * </p>
264      *
265      * <p>
266      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
267      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
268      * </p>
269      *
270      * @param initialNonZeroOddNumber
271      *            a non-zero, odd number used as the initial value
272      * @param multiplierNonZeroOddNumber
273      *            a non-zero, odd number used as the multiplier
274      * @param object
275      *            the Object to create a <code>hashCode</code> for
276      * @param testTransients
277      *            whether to include transient fields
278      * @return int hash code
279      * @throws IllegalArgumentException
280      *             if the Object is <code>null</code>
281      * @throws IllegalArgumentException
282      *             if the number is zero or even
283      */
reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object, boolean testTransients)284     public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
285             boolean testTransients) {
286         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null,
287                 null);
288     }
289 
290     /**
291      * Calls {@link #reflectionHashCode(int, int, Object, boolean, Class, String[])} with excludeFields set to
292      * <code>null</code>.
293      *
294      * @param initialNonZeroOddNumber
295      *            a non-zero, odd number used as the initial value
296      * @param multiplierNonZeroOddNumber
297      *            a non-zero, odd number used as the multiplier
298      * @param object
299      *            the Object to create a <code>hashCode</code> for
300      * @param testTransients
301      *            whether to include transient fields
302      * @param reflectUpToClass
303      *            the superclass to reflect up to (inclusive), may be <code>null</code>
304      * @return int hash code
305      */
reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object, boolean testTransients, Class reflectUpToClass)306     public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
307             boolean testTransients, Class reflectUpToClass) {
308         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients,
309                 reflectUpToClass, null);
310     }
311 
312     /**
313      * <p>
314      * This method uses reflection to build a valid hash code.
315      * </p>
316      *
317      * <p>
318      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
319      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
320      * also not as efficient as testing explicitly.
321      * </p>
322      *
323      * <p>
324      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
325      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
326      * </p>
327      *
328      * <p>
329      * Static fields will not be included. Superclass fields will be included up to and including the specified
330      * superclass. A null superclass is treated as java.lang.Object.
331      * </p>
332      *
333      * <p>
334      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
335      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
336      * </p>
337      *
338      * @param initialNonZeroOddNumber
339      *            a non-zero, odd number used as the initial value
340      * @param multiplierNonZeroOddNumber
341      *            a non-zero, odd number used as the multiplier
342      * @param object
343      *            the Object to create a <code>hashCode</code> for
344      * @param testTransients
345      *            whether to include transient fields
346      * @param reflectUpToClass
347      *            the superclass to reflect up to (inclusive), may be <code>null</code>
348      * @param excludeFields
349      *            array of field names to exclude from use in calculation of hash code
350      * @return int hash code
351      * @throws IllegalArgumentException
352      *             if the Object is <code>null</code>
353      * @throws IllegalArgumentException
354      *             if the number is zero or even
355      * @since 2.0
356      */
reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object, boolean testTransients, Class reflectUpToClass, String[] excludeFields)357     public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
358             boolean testTransients, Class reflectUpToClass, String[] excludeFields) {
359 
360         if (object == null) {
361             throw new IllegalArgumentException("The object to build a hash code for must not be null");
362         }
363         HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
364         Class clazz = object.getClass();
365         reflectionAppend(object, clazz, builder, testTransients, excludeFields);
366         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
367             clazz = clazz.getSuperclass();
368             reflectionAppend(object, clazz, builder, testTransients, excludeFields);
369         }
370         return builder.toHashCode();
371     }
372 
373     /**
374      * <p>
375      * This method uses reflection to build a valid hash code.
376      * </p>
377      *
378      * <p>
379      * This constructor uses two hard coded choices for the constants needed to build a hash code.
380      * </p>
381      *
382      * <p>
383      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
384      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
385      * also not as efficient as testing explicitly.
386      * </p>
387      *
388      * <p>
389      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
390      * <code>Object</code>.
391      * </p>
392      *
393      * <p>
394      * Static fields will not be tested. Superclass fields will be included.
395      * </p>
396      *
397      * @param object
398      *            the Object to create a <code>hashCode</code> for
399      * @return int hash code
400      * @throws IllegalArgumentException
401      *             if the object is <code>null</code>
402      */
reflectionHashCode(Object object)403     public static int reflectionHashCode(Object object) {
404         return reflectionHashCode(17, 37, object, false, null, null);
405     }
406 
407     /**
408      * <p>
409      * This method uses reflection to build a valid hash code.
410      * </p>
411      *
412      * <p>
413      * This constructor uses two hard coded choices for the constants needed to build a hash code.
414      * </p>
415      *
416      * <p>
417      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
418      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
419      * also not as efficient as testing explicitly.
420      * </p>
421      *
422      * <P>
423      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
424      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
425      * </p>
426      *
427      * <p>
428      * Static fields will not be tested. Superclass fields will be included.
429      * </p>
430      *
431      * @param object
432      *            the Object to create a <code>hashCode</code> for
433      * @param testTransients
434      *            whether to include transient fields
435      * @return int hash code
436      * @throws IllegalArgumentException
437      *             if the object is <code>null</code>
438      */
reflectionHashCode(Object object, boolean testTransients)439     public static int reflectionHashCode(Object object, boolean testTransients) {
440         return reflectionHashCode(17, 37, object, testTransients, null, null);
441     }
442 
443     /**
444      * <p>
445      * This method uses reflection to build a valid hash code.
446      * </p>
447      *
448      * <p>
449      * This constructor uses two hard coded choices for the constants needed to build a hash code.
450      * </p>
451      *
452      * <p>
453      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
454      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
455      * also not as efficient as testing explicitly.
456      * </p>
457      *
458      * <p>
459      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
460      * <code>Object</code>.
461      * </p>
462      *
463      * <p>
464      * Static fields will not be tested. Superclass fields will be included.
465      * </p>
466      *
467      * @param object
468      *            the Object to create a <code>hashCode</code> for
469      * @param excludeFields
470      *            Collection of String field names to exclude from use in calculation of hash code
471      * @return int hash code
472      * @throws IllegalArgumentException
473      *             if the object is <code>null</code>
474      */
reflectionHashCode(Object object, Collection excludeFields)475     public static int reflectionHashCode(Object object, Collection /* String */excludeFields) {
476         return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
477     }
478 
479     // -------------------------------------------------------------------------
480 
481     /**
482      * <p>
483      * This method uses reflection to build a valid hash code.
484      * </p>
485      *
486      * <p>
487      * This constructor uses two hard coded choices for the constants needed to build a hash code.
488      * </p>
489      *
490      * <p>
491      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
492      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
493      * also not as efficient as testing explicitly.
494      * </p>
495      *
496      * <p>
497      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
498      * <code>Object</code>.
499      * </p>
500      *
501      * <p>
502      * Static fields will not be tested. Superclass fields will be included.
503      * </p>
504      *
505      * @param object
506      *            the Object to create a <code>hashCode</code> for
507      * @param excludeFields
508      *            array of field names to exclude from use in calculation of hash code
509      * @return int hash code
510      * @throws IllegalArgumentException
511      *             if the object is <code>null</code>
512      */
reflectionHashCode(Object object, String[] excludeFields)513     public static int reflectionHashCode(Object object, String[] excludeFields) {
514         return reflectionHashCode(17, 37, object, false, null, excludeFields);
515     }
516 
517     /**
518      * <p>
519      * Registers the given object. Used by the reflection methods to avoid infinite loops.
520      * </p>
521      *
522      * @param value
523      *            The object to register.
524      */
register(Object value)525     static void register(Object value) {
526         synchronized (HashCodeBuilder.class) {
527             if (getRegistry() == null) {
528                 REGISTRY.set(new HashSet());
529             }
530         }
531         getRegistry().add(new IDKey(value));
532     }
533 
534     /**
535      * <p>
536      * Unregisters the given object.
537      * </p>
538      *
539      * <p>
540      * Used by the reflection methods to avoid infinite loops.
541      *
542      * @param value
543      *            The object to unregister.
544      * @since 2.3
545      */
unregister(Object value)546     static void unregister(Object value) {
547         Set registry = getRegistry();
548         if (registry != null) {
549             registry.remove(new IDKey(value));
550             synchronized (HashCodeBuilder.class) {
551                 //read again
552                 registry = getRegistry();
553                 if (registry != null && registry.isEmpty()) {
554                     REGISTRY.set(null);
555                 }
556             }
557         }
558     }
559 
560     /**
561      * Constant to use in building the hashCode.
562      */
563     private final int iConstant;
564 
565     /**
566      * Running total of the hashCode.
567      */
568     private int iTotal = 0;
569 
570     /**
571      * <p>
572      * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>.
573      * </p>
574      */
HashCodeBuilder()575     public HashCodeBuilder() {
576         iConstant = 37;
577         iTotal = 17;
578     }
579 
580     /**
581      * <p>
582      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
583      * however this is not vital.
584      * </p>
585      *
586      * <p>
587      * Prime numbers are preferred, especially for the multiplier.
588      * </p>
589      *
590      * @param initialNonZeroOddNumber
591      *            a non-zero, odd number used as the initial value
592      * @param multiplierNonZeroOddNumber
593      *            a non-zero, odd number used as the multiplier
594      * @throws IllegalArgumentException
595      *             if the number is zero or even
596      */
HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber)597     public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
598         if (initialNonZeroOddNumber == 0) {
599             throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
600         }
601         if (initialNonZeroOddNumber % 2 == 0) {
602             throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
603         }
604         if (multiplierNonZeroOddNumber == 0) {
605             throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
606         }
607         if (multiplierNonZeroOddNumber % 2 == 0) {
608             throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
609         }
610         iConstant = multiplierNonZeroOddNumber;
611         iTotal = initialNonZeroOddNumber;
612     }
613 
614     /**
615      * <p>
616      * Append a <code>hashCode</code> for a <code>boolean</code>.
617      * </p>
618      * <p>
619      * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
620      * </p>
621      * <p>
622      * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
623      * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
624      * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
625      * that represent <code>false</code>.
626      * </p>
627      * <p>
628      * This is in accordance with the <quote>Effective Java</quote> design.
629      * </p>
630      *
631      * @param value
632      *            the boolean to add to the <code>hashCode</code>
633      * @return this
634      */
append(boolean value)635     public HashCodeBuilder append(boolean value) {
636         iTotal = iTotal * iConstant + (value ? 0 : 1);
637         return this;
638     }
639 
640     /**
641      * <p>
642      * Append a <code>hashCode</code> for a <code>boolean</code> array.
643      * </p>
644      *
645      * @param array
646      *            the array to add to the <code>hashCode</code>
647      * @return this
648      */
append(boolean[] array)649     public HashCodeBuilder append(boolean[] array) {
650         if (array == null) {
651             iTotal = iTotal * iConstant;
652         } else {
653             for (int i = 0; i < array.length; i++) {
654                 append(array[i]);
655             }
656         }
657         return this;
658     }
659 
660     // -------------------------------------------------------------------------
661 
662     /**
663      * <p>
664      * Append a <code>hashCode</code> for a <code>byte</code>.
665      * </p>
666      *
667      * @param value
668      *            the byte to add to the <code>hashCode</code>
669      * @return this
670      */
append(byte value)671     public HashCodeBuilder append(byte value) {
672         iTotal = iTotal * iConstant + value;
673         return this;
674     }
675 
676     // -------------------------------------------------------------------------
677 
678     /**
679      * <p>
680      * Append a <code>hashCode</code> for a <code>byte</code> array.
681      * </p>
682      *
683      * @param array
684      *            the array to add to the <code>hashCode</code>
685      * @return this
686      */
append(byte[] array)687     public HashCodeBuilder append(byte[] array) {
688         if (array == null) {
689             iTotal = iTotal * iConstant;
690         } else {
691             for (int i = 0; i < array.length; i++) {
692                 append(array[i]);
693             }
694         }
695         return this;
696     }
697 
698     /**
699      * <p>
700      * Append a <code>hashCode</code> for a <code>char</code>.
701      * </p>
702      *
703      * @param value
704      *            the char to add to the <code>hashCode</code>
705      * @return this
706      */
append(char value)707     public HashCodeBuilder append(char value) {
708         iTotal = iTotal * iConstant + value;
709         return this;
710     }
711 
712     /**
713      * <p>
714      * Append a <code>hashCode</code> for a <code>char</code> array.
715      * </p>
716      *
717      * @param array
718      *            the array to add to the <code>hashCode</code>
719      * @return this
720      */
append(char[] array)721     public HashCodeBuilder append(char[] array) {
722         if (array == null) {
723             iTotal = iTotal * iConstant;
724         } else {
725             for (int i = 0; i < array.length; i++) {
726                 append(array[i]);
727             }
728         }
729         return this;
730     }
731 
732     /**
733      * <p>
734      * Append a <code>hashCode</code> for a <code>double</code>.
735      * </p>
736      *
737      * @param value
738      *            the double to add to the <code>hashCode</code>
739      * @return this
740      */
append(double value)741     public HashCodeBuilder append(double value) {
742         return append(Double.doubleToLongBits(value));
743     }
744 
745     /**
746      * <p>
747      * Append a <code>hashCode</code> for a <code>double</code> array.
748      * </p>
749      *
750      * @param array
751      *            the array to add to the <code>hashCode</code>
752      * @return this
753      */
append(double[] array)754     public HashCodeBuilder append(double[] array) {
755         if (array == null) {
756             iTotal = iTotal * iConstant;
757         } else {
758             for (int i = 0; i < array.length; i++) {
759                 append(array[i]);
760             }
761         }
762         return this;
763     }
764 
765     /**
766      * <p>
767      * Append a <code>hashCode</code> for a <code>float</code>.
768      * </p>
769      *
770      * @param value
771      *            the float to add to the <code>hashCode</code>
772      * @return this
773      */
append(float value)774     public HashCodeBuilder append(float value) {
775         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
776         return this;
777     }
778 
779     /**
780      * <p>
781      * Append a <code>hashCode</code> for a <code>float</code> array.
782      * </p>
783      *
784      * @param array
785      *            the array to add to the <code>hashCode</code>
786      * @return this
787      */
append(float[] array)788     public HashCodeBuilder append(float[] array) {
789         if (array == null) {
790             iTotal = iTotal * iConstant;
791         } else {
792             for (int i = 0; i < array.length; i++) {
793                 append(array[i]);
794             }
795         }
796         return this;
797     }
798 
799     /**
800      * <p>
801      * Append a <code>hashCode</code> for an <code>int</code>.
802      * </p>
803      *
804      * @param value
805      *            the int to add to the <code>hashCode</code>
806      * @return this
807      */
append(int value)808     public HashCodeBuilder append(int value) {
809         iTotal = iTotal * iConstant + value;
810         return this;
811     }
812 
813     /**
814      * <p>
815      * Append a <code>hashCode</code> for an <code>int</code> array.
816      * </p>
817      *
818      * @param array
819      *            the array to add to the <code>hashCode</code>
820      * @return this
821      */
append(int[] array)822     public HashCodeBuilder append(int[] array) {
823         if (array == null) {
824             iTotal = iTotal * iConstant;
825         } else {
826             for (int i = 0; i < array.length; i++) {
827                 append(array[i]);
828             }
829         }
830         return this;
831     }
832 
833     /**
834      * <p>
835      * Append a <code>hashCode</code> for a <code>long</code>.
836      * </p>
837      *
838      * @param value
839      *            the long to add to the <code>hashCode</code>
840      * @return this
841      */
842     // NOTE: This method uses >> and not >>> as Effective Java and
843     //       Long.hashCode do. Ideally we should switch to >>> at
844     //       some stage. There are backwards compat issues, so
845     //       that will have to wait for the time being. cf LANG-342.
append(long value)846     public HashCodeBuilder append(long value) {
847         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
848         return this;
849     }
850 
851     /**
852      * <p>
853      * Append a <code>hashCode</code> for a <code>long</code> array.
854      * </p>
855      *
856      * @param array
857      *            the array to add to the <code>hashCode</code>
858      * @return this
859      */
append(long[] array)860     public HashCodeBuilder append(long[] array) {
861         if (array == null) {
862             iTotal = iTotal * iConstant;
863         } else {
864             for (int i = 0; i < array.length; i++) {
865                 append(array[i]);
866             }
867         }
868         return this;
869     }
870 
871     /**
872      * <p>
873      * Append a <code>hashCode</code> for an <code>Object</code>.
874      * </p>
875      *
876      * @param object
877      *            the Object to add to the <code>hashCode</code>
878      * @return this
879      */
append(Object object)880     public HashCodeBuilder append(Object object) {
881         if (object == null) {
882             iTotal = iTotal * iConstant;
883 
884         } else {
885             if(object.getClass().isArray()) {
886                 // 'Switch' on type of array, to dispatch to the correct handler
887                 // This handles multi dimensional arrays
888                 if (object instanceof long[]) {
889                     append((long[]) object);
890                 } else if (object instanceof int[]) {
891                     append((int[]) object);
892                 } else if (object instanceof short[]) {
893                     append((short[]) object);
894                 } else if (object instanceof char[]) {
895                     append((char[]) object);
896                 } else if (object instanceof byte[]) {
897                     append((byte[]) object);
898                 } else if (object instanceof double[]) {
899                     append((double[]) object);
900                 } else if (object instanceof float[]) {
901                     append((float[]) object);
902                 } else if (object instanceof boolean[]) {
903                     append((boolean[]) object);
904                 } else {
905                     // Not an array of primitives
906                     append((Object[]) object);
907                 }
908             } else {
909                 iTotal = iTotal * iConstant + object.hashCode();
910             }
911         }
912         return this;
913     }
914 
915     /**
916      * <p>
917      * Append a <code>hashCode</code> for an <code>Object</code> array.
918      * </p>
919      *
920      * @param array
921      *            the array to add to the <code>hashCode</code>
922      * @return this
923      */
append(Object[] array)924     public HashCodeBuilder append(Object[] array) {
925         if (array == null) {
926             iTotal = iTotal * iConstant;
927         } else {
928             for (int i = 0; i < array.length; i++) {
929                 append(array[i]);
930             }
931         }
932         return this;
933     }
934 
935     /**
936      * <p>
937      * Append a <code>hashCode</code> for a <code>short</code>.
938      * </p>
939      *
940      * @param value
941      *            the short to add to the <code>hashCode</code>
942      * @return this
943      */
append(short value)944     public HashCodeBuilder append(short value) {
945         iTotal = iTotal * iConstant + value;
946         return this;
947     }
948 
949     /**
950      * <p>
951      * Append a <code>hashCode</code> for a <code>short</code> array.
952      * </p>
953      *
954      * @param array
955      *            the array to add to the <code>hashCode</code>
956      * @return this
957      */
append(short[] array)958     public HashCodeBuilder append(short[] array) {
959         if (array == null) {
960             iTotal = iTotal * iConstant;
961         } else {
962             for (int i = 0; i < array.length; i++) {
963                 append(array[i]);
964             }
965         }
966         return this;
967     }
968 
969     /**
970      * <p>
971      * Adds the result of super.hashCode() to this builder.
972      * </p>
973      *
974      * @param superHashCode
975      *            the result of calling <code>super.hashCode()</code>
976      * @return this HashCodeBuilder, used to chain calls.
977      * @since 2.0
978      */
appendSuper(int superHashCode)979     public HashCodeBuilder appendSuper(int superHashCode) {
980         iTotal = iTotal * iConstant + superHashCode;
981         return this;
982     }
983 
984     /**
985      * <p>
986      * Return the computed <code>hashCode</code>.
987      * </p>
988      *
989      * @return <code>hashCode</code> based on the fields appended
990      */
toHashCode()991     public int toHashCode() {
992         return iTotal;
993     }
994 
995     /**
996      * <p>
997      * The computed <code>hashCode</code> from toHashCode() is returned due to the likelyhood
998      * of bugs in mis-calling toHashCode() and the unlikelyness of it mattering what the hashCode for
999      * HashCodeBuilder itself is.
1000      *
1001      * @return <code>hashCode</code> based on the fields appended
1002      * @since 2.5
1003      */
hashCode()1004     public int hashCode() {
1005         return toHashCode();
1006     }
1007 
1008 }
1009