source: src/main/java/agents/org/apache/commons/lang/builder/HashCodeBuilder.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 34.3 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package agents.org.apache.commons.lang.builder;
19
20import java.lang.reflect.AccessibleObject;
21import java.lang.reflect.Field;
22import java.lang.reflect.Modifier;
23import java.util.Collection;
24import java.util.HashSet;
25import java.util.Set;
26
27import agents.org.apache.commons.lang.ArrayUtils;
28
29/**
30 * <p>
31 * Assists in implementing {@link Object#hashCode()} methods.
32 * </p>
33 *
34 * <p>
35 * This class enables a good <code>hashCode</code> method to be built for any class. It follows the rules laid out in
36 * the book <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> by Joshua Bloch. Writing a
37 * good <code>hashCode</code> method is actually quite difficult. This class aims to simplify the process.
38 * </p>
39 *
40 * <p>
41 * The following is the approach taken. When appending a data field, the current total is multiplied by the
42 * multiplier then a relevant value
43 * for that data type is added. For example, if the current hashCode is 17, and the multiplier is 37, then
44 * appending the integer 45 will create a hashcode of 674, namely 17 * 37 + 45.
45 * </p>
46 *
47 * <p>
48 * All relevant fields from the object should be included in the <code>hashCode</code> method. Derived fields may be
49 * excluded. In general, any field used in the <code>equals</code> method must be used in the <code>hashCode</code>
50 * method.
51 * </p>
52 *
53 * <p>
54 * To use this class write code as follows:
55 * </p>
56 *
57 * <pre>
58 * public class Person {
59 * String name;
60 * int age;
61 * boolean smoker;
62 * ...
63 *
64 * public int hashCode() {
65 * // you pick a hard-coded, randomly chosen, non-zero, odd number
66 * // ideally different for each class
67 * return new HashCodeBuilder(17, 37).
68 * append(name).
69 * append(age).
70 * append(smoker).
71 * toHashCode();
72 * }
73 * }
74 * </pre>
75 *
76 * <p>
77 * If required, the superclass <code>hashCode()</code> can be added using {@link #appendSuper}.
78 * </p>
79 *
80 * <p>
81 * Alternatively, there is a method that uses reflection to determine the fields to test. Because these fields are
82 * usually private, the method, <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code>
83 * to change the visibility of the fields. This will fail under a security manager, unless the appropriate permissions
84 * are set up correctly. It is also slower than testing explicitly.
85 * </p>
86 *
87 * <p>
88 * A typical invocation for this method would look like:
89 * </p>
90 *
91 * <pre>
92 * public int hashCode() {
93 * return HashCodeBuilder.reflectionHashCode(this);
94 * }
95 * </pre>
96 *
97 * @author Apache Software Foundation
98 * @author Gary Gregory
99 * @author Pete Gieser
100 * @since 1.0
101 * @version $Id: HashCodeBuilder.java 1057009 2011-01-09 19:48:06Z niallp $
102 */
103public class HashCodeBuilder {
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 REGISTRY = new ThreadLocal();
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 getRegistry() {
139 return (Set) 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 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 (int i = 0; i < fields.length; i++) {
184 Field field = fields[i];
185 if (!ArrayUtils.contains(excludeFields, field.getName())
186 && (field.getName().indexOf('$') == -1)
187 && (useTransients || !Modifier.isTransient(field.getModifiers()))
188 && (!Modifier.isStatic(field.getModifiers()))) {
189 try {
190 Object fieldValue = field.get(object);
191 builder.append(fieldValue);
192 } catch (IllegalAccessException e) {
193 // this can't happen. Would get a Security exception instead
194 // throw a runtime exception in case the impossible happens.
195 throw new InternalError("Unexpected IllegalAccessException");
196 }
197 }
198 }
199 } finally {
200 unregister(object);
201 }
202 }
203
204 /**
205 * <p>
206 * This method uses reflection to build a valid hash code.
207 * </p>
208 *
209 * <p>
210 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
211 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
212 * also not as efficient as testing explicitly.
213 * </p>
214 *
215 * <p>
216 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
217 * <code>Object</code>.
218 * </p>
219 *
220 * <p>
221 * Static fields will not be tested. Superclass fields will be included.
222 * </p>
223 *
224 * <p>
225 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
226 * however this is not vital. Prime numbers are preferred, especially for the multiplier.
227 * </p>
228 *
229 * @param initialNonZeroOddNumber
230 * a non-zero, odd number used as the initial value
231 * @param multiplierNonZeroOddNumber
232 * a non-zero, odd number used as the multiplier
233 * @param object
234 * the Object to create a <code>hashCode</code> for
235 * @return int hash code
236 * @throws IllegalArgumentException
237 * if the Object is <code>null</code>
238 * @throws IllegalArgumentException
239 * if the number is zero or even
240 */
241 public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
242 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null, null);
243 }
244
245 /**
246 * <p>
247 * This method uses reflection to build a valid hash code.
248 * </p>
249 *
250 * <p>
251 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
252 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
253 * also not as efficient as testing explicitly.
254 * </p>
255 *
256 * <p>
257 * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
258 * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
259 * </p>
260 *
261 * <p>
262 * Static fields will not be tested. Superclass fields will be included.
263 * </p>
264 *
265 * <p>
266 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
267 * however this is not vital. Prime numbers are preferred, especially for the multiplier.
268 * </p>
269 *
270 * @param initialNonZeroOddNumber
271 * a non-zero, odd number used as the initial value
272 * @param multiplierNonZeroOddNumber
273 * a non-zero, odd number used as the multiplier
274 * @param object
275 * the Object to create a <code>hashCode</code> for
276 * @param testTransients
277 * whether to include transient fields
278 * @return int hash code
279 * @throws IllegalArgumentException
280 * if the Object is <code>null</code>
281 * @throws IllegalArgumentException
282 * if the number is zero or even
283 */
284 public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
285 boolean testTransients) {
286 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null,
287 null);
288 }
289
290 /**
291 * Calls {@link #reflectionHashCode(int, int, Object, boolean, Class, String[])} with excludeFields set to
292 * <code>null</code>.
293 *
294 * @param initialNonZeroOddNumber
295 * a non-zero, odd number used as the initial value
296 * @param multiplierNonZeroOddNumber
297 * a non-zero, odd number used as the multiplier
298 * @param object
299 * the Object to create a <code>hashCode</code> for
300 * @param testTransients
301 * whether to include transient fields
302 * @param reflectUpToClass
303 * the superclass to reflect up to (inclusive), may be <code>null</code>
304 * @return int hash code
305 */
306 public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
307 boolean testTransients, Class reflectUpToClass) {
308 return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients,
309 reflectUpToClass, null);
310 }
311
312 /**
313 * <p>
314 * This method uses reflection to build a valid hash code.
315 * </p>
316 *
317 * <p>
318 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
319 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
320 * also not as efficient as testing explicitly.
321 * </p>
322 *
323 * <p>
324 * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
325 * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
326 * </p>
327 *
328 * <p>
329 * Static fields will not be included. Superclass fields will be included up to and including the specified
330 * superclass. A null superclass is treated as java.lang.Object.
331 * </p>
332 *
333 * <p>
334 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
335 * however this is not vital. Prime numbers are preferred, especially for the multiplier.
336 * </p>
337 *
338 * @param initialNonZeroOddNumber
339 * a non-zero, odd number used as the initial value
340 * @param multiplierNonZeroOddNumber
341 * a non-zero, odd number used as the multiplier
342 * @param object
343 * the Object to create a <code>hashCode</code> for
344 * @param testTransients
345 * whether to include transient fields
346 * @param reflectUpToClass
347 * the superclass to reflect up to (inclusive), may be <code>null</code>
348 * @param excludeFields
349 * array of field names to exclude from use in calculation of hash code
350 * @return int hash code
351 * @throws IllegalArgumentException
352 * if the Object is <code>null</code>
353 * @throws IllegalArgumentException
354 * if the number is zero or even
355 * @since 2.0
356 */
357 public static int reflectionHashCode(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object,
358 boolean testTransients, Class reflectUpToClass, String[] excludeFields) {
359
360 if (object == null) {
361 throw new IllegalArgumentException("The object to build a hash code for must not be null");
362 }
363 HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
364 Class clazz = object.getClass();
365 reflectionAppend(object, clazz, builder, testTransients, excludeFields);
366 while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
367 clazz = clazz.getSuperclass();
368 reflectionAppend(object, clazz, builder, testTransients, excludeFields);
369 }
370 return builder.toHashCode();
371 }
372
373 /**
374 * <p>
375 * This method uses reflection to build a valid hash code.
376 * </p>
377 *
378 * <p>
379 * This constructor uses two hard coded choices for the constants needed to build a hash code.
380 * </p>
381 *
382 * <p>
383 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
384 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
385 * also not as efficient as testing explicitly.
386 * </p>
387 *
388 * <p>
389 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
390 * <code>Object</code>.
391 * </p>
392 *
393 * <p>
394 * Static fields will not be tested. Superclass fields will be included.
395 * </p>
396 *
397 * @param object
398 * the Object to create a <code>hashCode</code> for
399 * @return int hash code
400 * @throws IllegalArgumentException
401 * if the object is <code>null</code>
402 */
403 public static int reflectionHashCode(Object object) {
404 return reflectionHashCode(17, 37, object, false, null, null);
405 }
406
407 /**
408 * <p>
409 * This method uses reflection to build a valid hash code.
410 * </p>
411 *
412 * <p>
413 * This constructor uses two hard coded choices for the constants needed to build a hash code.
414 * </p>
415 *
416 * <p>
417 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
418 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
419 * also not as efficient as testing explicitly.
420 * </p>
421 *
422 * <P>
423 * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
424 * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
425 * </p>
426 *
427 * <p>
428 * Static fields will not be tested. Superclass fields will be included.
429 * </p>
430 *
431 * @param object
432 * the Object to create a <code>hashCode</code> for
433 * @param testTransients
434 * whether to include transient fields
435 * @return int hash code
436 * @throws IllegalArgumentException
437 * if the object is <code>null</code>
438 */
439 public static int reflectionHashCode(Object object, boolean testTransients) {
440 return reflectionHashCode(17, 37, object, testTransients, null, null);
441 }
442
443 /**
444 * <p>
445 * This method uses reflection to build a valid hash code.
446 * </p>
447 *
448 * <p>
449 * This constructor uses two hard coded choices for the constants needed to build a hash code.
450 * </p>
451 *
452 * <p>
453 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
454 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
455 * also not as efficient as testing explicitly.
456 * </p>
457 *
458 * <p>
459 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
460 * <code>Object</code>.
461 * </p>
462 *
463 * <p>
464 * Static fields will not be tested. Superclass fields will be included.
465 * </p>
466 *
467 * @param object
468 * the Object to create a <code>hashCode</code> for
469 * @param excludeFields
470 * Collection of String field names to exclude from use in calculation of hash code
471 * @return int hash code
472 * @throws IllegalArgumentException
473 * if the object is <code>null</code>
474 */
475 public static int reflectionHashCode(Object object, Collection /* String */excludeFields) {
476 return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
477 }
478
479 // -------------------------------------------------------------------------
480
481 /**
482 * <p>
483 * This method uses reflection to build a valid hash code.
484 * </p>
485 *
486 * <p>
487 * This constructor uses two hard coded choices for the constants needed to build a hash code.
488 * </p>
489 *
490 * <p>
491 * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
492 * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
493 * also not as efficient as testing explicitly.
494 * </p>
495 *
496 * <p>
497 * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
498 * <code>Object</code>.
499 * </p>
500 *
501 * <p>
502 * Static fields will not be tested. Superclass fields will be included.
503 * </p>
504 *
505 * @param object
506 * the Object to create a <code>hashCode</code> for
507 * @param excludeFields
508 * array of field names to exclude from use in calculation of hash code
509 * @return int hash code
510 * @throws IllegalArgumentException
511 * if the object is <code>null</code>
512 */
513 public static int reflectionHashCode(Object object, String[] excludeFields) {
514 return reflectionHashCode(17, 37, object, false, null, excludeFields);
515 }
516
517 /**
518 * <p>
519 * Registers the given object. Used by the reflection methods to avoid infinite loops.
520 * </p>
521 *
522 * @param value
523 * The object to register.
524 */
525 static void register(Object value) {
526 synchronized (HashCodeBuilder.class) {
527 if (getRegistry() == null) {
528 REGISTRY.set(new HashSet());
529 }
530 }
531 getRegistry().add(new IDKey(value));
532 }
533
534 /**
535 * <p>
536 * Unregisters the given object.
537 * </p>
538 *
539 * <p>
540 * Used by the reflection methods to avoid infinite loops.
541 *
542 * @param value
543 * The object to unregister.
544 * @since 2.3
545 */
546 static void unregister(Object value) {
547 Set registry = getRegistry();
548 if (registry != null) {
549 registry.remove(new IDKey(value));
550 synchronized (HashCodeBuilder.class) {
551 //read again
552 registry = getRegistry();
553 if (registry != null && registry.isEmpty()) {
554 REGISTRY.set(null);
555 }
556 }
557 }
558 }
559
560 /**
561 * Constant to use in building the hashCode.
562 */
563 private final int iConstant;
564
565 /**
566 * Running total of the hashCode.
567 */
568 private int iTotal = 0;
569
570 /**
571 * <p>
572 * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>.
573 * </p>
574 */
575 public HashCodeBuilder() {
576 iConstant = 37;
577 iTotal = 17;
578 }
579
580 /**
581 * <p>
582 * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
583 * however this is not vital.
584 * </p>
585 *
586 * <p>
587 * Prime numbers are preferred, especially for the multiplier.
588 * </p>
589 *
590 * @param initialNonZeroOddNumber
591 * a non-zero, odd number used as the initial value
592 * @param multiplierNonZeroOddNumber
593 * a non-zero, odd number used as the multiplier
594 * @throws IllegalArgumentException
595 * if the number is zero or even
596 */
597 public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
598 if (initialNonZeroOddNumber == 0) {
599 throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
600 }
601 if (initialNonZeroOddNumber % 2 == 0) {
602 throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
603 }
604 if (multiplierNonZeroOddNumber == 0) {
605 throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
606 }
607 if (multiplierNonZeroOddNumber % 2 == 0) {
608 throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
609 }
610 iConstant = multiplierNonZeroOddNumber;
611 iTotal = initialNonZeroOddNumber;
612 }
613
614 /**
615 * <p>
616 * Append a <code>hashCode</code> for a <code>boolean</code>.
617 * </p>
618 * <p>
619 * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
620 * </p>
621 * <p>
622 * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
623 * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
624 * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
625 * that represent <code>false</code>.
626 * </p>
627 * <p>
628 * This is in accordance with the <quote>Effective Java</quote> design.
629 * </p>
630 *
631 * @param value
632 * the boolean to add to the <code>hashCode</code>
633 * @return this
634 */
635 public HashCodeBuilder append(boolean value) {
636 iTotal = iTotal * iConstant + (value ? 0 : 1);
637 return this;
638 }
639
640 /**
641 * <p>
642 * Append a <code>hashCode</code> for a <code>boolean</code> array.
643 * </p>
644 *
645 * @param array
646 * the array to add to the <code>hashCode</code>
647 * @return this
648 */
649 public HashCodeBuilder append(boolean[] array) {
650 if (array == null) {
651 iTotal = iTotal * iConstant;
652 } else {
653 for (int i = 0; i < array.length; i++) {
654 append(array[i]);
655 }
656 }
657 return this;
658 }
659
660 // -------------------------------------------------------------------------
661
662 /**
663 * <p>
664 * Append a <code>hashCode</code> for a <code>byte</code>.
665 * </p>
666 *
667 * @param value
668 * the byte to add to the <code>hashCode</code>
669 * @return this
670 */
671 public HashCodeBuilder append(byte value) {
672 iTotal = iTotal * iConstant + value;
673 return this;
674 }
675
676 // -------------------------------------------------------------------------
677
678 /**
679 * <p>
680 * Append a <code>hashCode</code> for a <code>byte</code> array.
681 * </p>
682 *
683 * @param array
684 * the array to add to the <code>hashCode</code>
685 * @return this
686 */
687 public HashCodeBuilder append(byte[] array) {
688 if (array == null) {
689 iTotal = iTotal * iConstant;
690 } else {
691 for (int i = 0; i < array.length; i++) {
692 append(array[i]);
693 }
694 }
695 return this;
696 }
697
698 /**
699 * <p>
700 * Append a <code>hashCode</code> for a <code>char</code>.
701 * </p>
702 *
703 * @param value
704 * the char to add to the <code>hashCode</code>
705 * @return this
706 */
707 public HashCodeBuilder append(char value) {
708 iTotal = iTotal * iConstant + value;
709 return this;
710 }
711
712 /**
713 * <p>
714 * Append a <code>hashCode</code> for a <code>char</code> array.
715 * </p>
716 *
717 * @param array
718 * the array to add to the <code>hashCode</code>
719 * @return this
720 */
721 public HashCodeBuilder append(char[] array) {
722 if (array == null) {
723 iTotal = iTotal * iConstant;
724 } else {
725 for (int i = 0; i < array.length; i++) {
726 append(array[i]);
727 }
728 }
729 return this;
730 }
731
732 /**
733 * <p>
734 * Append a <code>hashCode</code> for a <code>double</code>.
735 * </p>
736 *
737 * @param value
738 * the double to add to the <code>hashCode</code>
739 * @return this
740 */
741 public HashCodeBuilder append(double value) {
742 return append(Double.doubleToLongBits(value));
743 }
744
745 /**
746 * <p>
747 * Append a <code>hashCode</code> for a <code>double</code> array.
748 * </p>
749 *
750 * @param array
751 * the array to add to the <code>hashCode</code>
752 * @return this
753 */
754 public HashCodeBuilder append(double[] array) {
755 if (array == null) {
756 iTotal = iTotal * iConstant;
757 } else {
758 for (int i = 0; i < array.length; i++) {
759 append(array[i]);
760 }
761 }
762 return this;
763 }
764
765 /**
766 * <p>
767 * Append a <code>hashCode</code> for a <code>float</code>.
768 * </p>
769 *
770 * @param value
771 * the float to add to the <code>hashCode</code>
772 * @return this
773 */
774 public HashCodeBuilder append(float value) {
775 iTotal = iTotal * iConstant + Float.floatToIntBits(value);
776 return this;
777 }
778
779 /**
780 * <p>
781 * Append a <code>hashCode</code> for a <code>float</code> array.
782 * </p>
783 *
784 * @param array
785 * the array to add to the <code>hashCode</code>
786 * @return this
787 */
788 public HashCodeBuilder append(float[] array) {
789 if (array == null) {
790 iTotal = iTotal * iConstant;
791 } else {
792 for (int i = 0; i < array.length; i++) {
793 append(array[i]);
794 }
795 }
796 return this;
797 }
798
799 /**
800 * <p>
801 * Append a <code>hashCode</code> for an <code>int</code>.
802 * </p>
803 *
804 * @param value
805 * the int to add to the <code>hashCode</code>
806 * @return this
807 */
808 public HashCodeBuilder append(int value) {
809 iTotal = iTotal * iConstant + value;
810 return this;
811 }
812
813 /**
814 * <p>
815 * Append a <code>hashCode</code> for an <code>int</code> array.
816 * </p>
817 *
818 * @param array
819 * the array to add to the <code>hashCode</code>
820 * @return this
821 */
822 public HashCodeBuilder append(int[] array) {
823 if (array == null) {
824 iTotal = iTotal * iConstant;
825 } else {
826 for (int i = 0; i < array.length; i++) {
827 append(array[i]);
828 }
829 }
830 return this;
831 }
832
833 /**
834 * <p>
835 * Append a <code>hashCode</code> for a <code>long</code>.
836 * </p>
837 *
838 * @param value
839 * the long to add to the <code>hashCode</code>
840 * @return this
841 */
842 // NOTE: This method uses >> and not >>> as Effective Java and
843 // Long.hashCode do. Ideally we should switch to >>> at
844 // some stage. There are backwards compat issues, so
845 // that will have to wait for the time being. cf LANG-342.
846 public HashCodeBuilder append(long value) {
847 iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
848 return this;
849 }
850
851 /**
852 * <p>
853 * Append a <code>hashCode</code> for a <code>long</code> array.
854 * </p>
855 *
856 * @param array
857 * the array to add to the <code>hashCode</code>
858 * @return this
859 */
860 public HashCodeBuilder append(long[] array) {
861 if (array == null) {
862 iTotal = iTotal * iConstant;
863 } else {
864 for (int i = 0; i < array.length; i++) {
865 append(array[i]);
866 }
867 }
868 return this;
869 }
870
871 /**
872 * <p>
873 * Append a <code>hashCode</code> for an <code>Object</code>.
874 * </p>
875 *
876 * @param object
877 * the Object to add to the <code>hashCode</code>
878 * @return this
879 */
880 public HashCodeBuilder append(Object object) {
881 if (object == null) {
882 iTotal = iTotal * iConstant;
883
884 } else {
885 if(object.getClass().isArray()) {
886 // 'Switch' on type of array, to dispatch to the correct handler
887 // This handles multi dimensional arrays
888 if (object instanceof long[]) {
889 append((long[]) object);
890 } else if (object instanceof int[]) {
891 append((int[]) object);
892 } else if (object instanceof short[]) {
893 append((short[]) object);
894 } else if (object instanceof char[]) {
895 append((char[]) object);
896 } else if (object instanceof byte[]) {
897 append((byte[]) object);
898 } else if (object instanceof double[]) {
899 append((double[]) object);
900 } else if (object instanceof float[]) {
901 append((float[]) object);
902 } else if (object instanceof boolean[]) {
903 append((boolean[]) object);
904 } else {
905 // Not an array of primitives
906 append((Object[]) object);
907 }
908 } else {
909 iTotal = iTotal * iConstant + object.hashCode();
910 }
911 }
912 return this;
913 }
914
915 /**
916 * <p>
917 * Append a <code>hashCode</code> for an <code>Object</code> array.
918 * </p>
919 *
920 * @param array
921 * the array to add to the <code>hashCode</code>
922 * @return this
923 */
924 public HashCodeBuilder append(Object[] array) {
925 if (array == null) {
926 iTotal = iTotal * iConstant;
927 } else {
928 for (int i = 0; i < array.length; i++) {
929 append(array[i]);
930 }
931 }
932 return this;
933 }
934
935 /**
936 * <p>
937 * Append a <code>hashCode</code> for a <code>short</code>.
938 * </p>
939 *
940 * @param value
941 * the short to add to the <code>hashCode</code>
942 * @return this
943 */
944 public HashCodeBuilder append(short value) {
945 iTotal = iTotal * iConstant + value;
946 return this;
947 }
948
949 /**
950 * <p>
951 * Append a <code>hashCode</code> for a <code>short</code> array.
952 * </p>
953 *
954 * @param array
955 * the array to add to the <code>hashCode</code>
956 * @return this
957 */
958 public HashCodeBuilder append(short[] array) {
959 if (array == null) {
960 iTotal = iTotal * iConstant;
961 } else {
962 for (int i = 0; i < array.length; i++) {
963 append(array[i]);
964 }
965 }
966 return this;
967 }
968
969 /**
970 * <p>
971 * Adds the result of super.hashCode() to this builder.
972 * </p>
973 *
974 * @param superHashCode
975 * the result of calling <code>super.hashCode()</code>
976 * @return this HashCodeBuilder, used to chain calls.
977 * @since 2.0
978 */
979 public HashCodeBuilder appendSuper(int superHashCode) {
980 iTotal = iTotal * iConstant + superHashCode;
981 return this;
982 }
983
984 /**
985 * <p>
986 * Return the computed <code>hashCode</code>.
987 * </p>
988 *
989 * @return <code>hashCode</code> based on the fields appended
990 */
991 public int toHashCode() {
992 return iTotal;
993 }
994
995 /**
996 * <p>
997 * The computed <code>hashCode</code> from toHashCode() is returned due to the likelyhood
998 * of bugs in mis-calling toHashCode() and the unlikelyness of it mattering what the hashCode for
999 * HashCodeBuilder itself is.
1000 *
1001 * @return <code>hashCode</code> based on the fields appended
1002 * @since 2.5
1003 */
1004 public int hashCode() {
1005 return toHashCode();
1006 }
1007
1008}
Note: See TracBrowser for help on using the repository browser.