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