001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.lang.builder;
019    
020    import java.lang.reflect.AccessibleObject;
021    import java.lang.reflect.Field;
022    import java.lang.reflect.Modifier;
023    import java.util.Arrays;
024    import java.util.Collection;
025    import java.util.Collections;
026    import java.util.HashSet;
027    import java.util.List;
028    import java.util.Set;
029    
030    /**
031     * <p>
032     * Assists in implementing {@link Object#hashCode()} methods.
033     * </p>
034     * 
035     * <p>
036     * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in
037     * the book <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> by Joshua Bloch. Writing a
038     * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process.
039     * </p>
040     * 
041     * <p>
042     * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be
043     * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code>
044     * method.
045     * </p>
046     * 
047     * <p>
048     * To use this class write code as follows:
049     * </p>
050     * 
051     * <pre>
052     * public class Person {
053     *   String name;
054     *   int age;
055     *   boolean smoker;
056     *   ...
057     *
058     *   public int hashCode() {
059     *     // you pick a hard-coded, randomly chosen, non-zero, odd number
060     *     // ideally different for each class
061     *     return new HashCodeBuilder(17, 37).
062     *       append(name).
063     *       append(age).
064     *       append(smoker).
065     *       toHashCode();
066     *   }
067     * }
068     * </pre>
069     * 
070     * <p>
071     * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}.
072     * </p>
073     * 
074     * <p>
075     * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
076     * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code>
077     * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
078     * are set up correctly. It is also slower than testing explicitly.
079     * </p>
080     * 
081     * <p>
082     * A typical invocation for this method would look like:
083     * </p>
084     * 
085     * <pre>
086     * public int hashCode() {
087     *   return HashCodeBuilder.reflectionHashCode(this);
088     * }
089     * </pre>
090     * 
091     * @author Stephen Colebourne
092     * @author Gary Gregory
093     * @author Pete Gieser
094     * @since 1.0
095     * @version $Id: HashCodeBuilder.java 564070 2007-08-09 01:58:11Z bayard $
096     */
097    public class HashCodeBuilder {
098        /**
099         * <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    }