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