View Javadoc

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