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