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