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