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