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