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