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 }