Coverage Report - org.apache.commons.lang3.builder.HashCodeBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
HashCodeBuilder
95%
146/153
94%
93/98
2.6
 
 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  
 
 18  
 package org.apache.commons.lang3.builder;
 19  
 
 20  
 import java.lang.reflect.AccessibleObject;
 21  
 import java.lang.reflect.Field;
 22  
 import java.lang.reflect.Modifier;
 23  
 import java.util.Collection;
 24  
 import java.util.HashSet;
 25  
 import java.util.Set;
 26  
 
 27  
 import org.apache.commons.lang3.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  
  * @since 1.0
 98  
  * @version $Id: HashCodeBuilder.java 1436770 2013-01-22 07:09:45Z ggregory $
 99  
  */
 100  0
 public class HashCodeBuilder implements Builder<Integer> {
 101  
     /**
 102  
      * <p>
 103  
      * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
 104  
      * </p>
 105  
      *
 106  
      * @since 2.3
 107  
      */
 108  1
     private static final ThreadLocal<Set<IDKey>> REGISTRY = new ThreadLocal<Set<IDKey>>();
 109  
 
 110  
     /*
 111  
      * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
 112  
      * we are in the process of calculating.
 113  
      *
 114  
      * So we generate a one-to-one mapping from the original object to a new object.
 115  
      *
 116  
      * Now HashSet uses equals() to determine if two elements with the same hashcode really
 117  
      * are equal, so we also need to ensure that the replacement objects are only equal
 118  
      * if the original objects are identical.
 119  
      *
 120  
      * The original implementation (2.4 and before) used the System.indentityHashCode()
 121  
      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
 122  
      *
 123  
      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
 124  
      * to disambiguate the duplicate ids.
 125  
      */
 126  
 
 127  
     /**
 128  
      * <p>
 129  
      * Returns the registry of objects being traversed by the reflection methods in the current thread.
 130  
      * </p>
 131  
      *
 132  
      * @return Set the registry of objects being traversed
 133  
      * @since 2.3
 134  
      */
 135  
     static Set<IDKey> getRegistry() {
 136  996
         return REGISTRY.get();
 137  
     }
 138  
 
 139  
     /**
 140  
      * <p>
 141  
      * Returns <code>true</code> if the registry contains the given object. Used by the reflection methods to avoid
 142  
      * infinite loops.
 143  
      * </p>
 144  
      *
 145  
      * @param value
 146  
      *            The object to lookup in the registry.
 147  
      * @return boolean <code>true</code> if the registry contains the given object.
 148  
      * @since 2.3
 149  
      */
 150  
     static boolean isRegistered(final Object value) {
 151  202
         final Set<IDKey> registry = getRegistry();
 152  202
         return registry != null && registry.contains(new IDKey(value));
 153  
     }
 154  
 
 155  
     /**
 156  
      * <p>
 157  
      * Appends the fields and values defined by the given object of the given <code>Class</code>.
 158  
      * </p>
 159  
      *
 160  
      * @param object
 161  
      *            the object to append details of
 162  
      * @param clazz
 163  
      *            the class to append details of
 164  
      * @param builder
 165  
      *            the builder to append to
 166  
      * @param useTransients
 167  
      *            whether to use transient fields
 168  
      * @param excludeFields
 169  
      *            Collection of String field names to exclude from use in calculation of hash code
 170  
      */
 171  
     private static void reflectionAppend(final Object object, final Class<?> clazz, final HashCodeBuilder builder, final boolean useTransients,
 172  
             final String[] excludeFields) {
 173  202
         if (isRegistered(object)) {
 174  4
             return;
 175  
         }
 176  
         try {
 177  198
             register(object);
 178  198
             final Field[] fields = clazz.getDeclaredFields();
 179  198
             AccessibleObject.setAccessible(fields, true);
 180  603
             for (final Field field : fields) {
 181  405
                 if (!ArrayUtils.contains(excludeFields, field.getName())
 182  
                     && (field.getName().indexOf('$') == -1)
 183  
                     && (useTransients || !Modifier.isTransient(field.getModifiers()))
 184  
                     && (!Modifier.isStatic(field.getModifiers()))) {
 185  
                     try {
 186  201
                         final Object fieldValue = field.get(object);
 187  201
                         builder.append(fieldValue);
 188  0
                     } catch (final IllegalAccessException e) {
 189  
                         // this can't happen. Would get a Security exception instead
 190  
                         // throw a runtime exception in case the impossible happens.
 191  0
                         throw new InternalError("Unexpected IllegalAccessException");
 192  201
                     }
 193  
                 }
 194  
             }
 195  
         } finally {
 196  198
             unregister(object);
 197  198
         }
 198  198
     }
 199  
 
 200  
     /**
 201  
      * <p>
 202  
      * This method uses reflection to build a valid hash code.
 203  
      * </p>
 204  
      *
 205  
      * <p>
 206  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 207  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 208  
      * also not as efficient as testing explicitly.
 209  
      * </p>
 210  
      *
 211  
      * <p>
 212  
      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
 213  
      * <code>Object</code>.
 214  
      * </p>
 215  
      *
 216  
      * <p>
 217  
      * Static fields will not be tested. Superclass fields will be included.
 218  
      * </p>
 219  
      *
 220  
      * <p>
 221  
      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
 222  
      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
 223  
      * </p>
 224  
      *
 225  
      * @param initialNonZeroOddNumber
 226  
      *            a non-zero, odd number used as the initial value
 227  
      * @param multiplierNonZeroOddNumber
 228  
      *            a non-zero, odd number used as the multiplier
 229  
      * @param object
 230  
      *            the Object to create a <code>hashCode</code> for
 231  
      * @return int hash code
 232  
      * @throws IllegalArgumentException
 233  
      *             if the Object is <code>null</code>
 234  
      * @throws IllegalArgumentException
 235  
      *             if the number is zero or even
 236  
      */
 237  
     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object) {
 238  0
         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
 239  
     }
 240  
 
 241  
     /**
 242  
      * <p>
 243  
      * This method uses reflection to build a valid hash code.
 244  
      * </p>
 245  
      *
 246  
      * <p>
 247  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 248  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 249  
      * also not as efficient as testing explicitly.
 250  
      * </p>
 251  
      *
 252  
      * <p>
 253  
      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
 254  
      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
 255  
      * </p>
 256  
      *
 257  
      * <p>
 258  
      * Static fields will not be tested. Superclass fields will be included.
 259  
      * </p>
 260  
      *
 261  
      * <p>
 262  
      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
 263  
      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
 264  
      * </p>
 265  
      *
 266  
      * @param initialNonZeroOddNumber
 267  
      *            a non-zero, odd number used as the initial value
 268  
      * @param multiplierNonZeroOddNumber
 269  
      *            a non-zero, odd number used as the multiplier
 270  
      * @param object
 271  
      *            the Object to create a <code>hashCode</code> for
 272  
      * @param testTransients
 273  
      *            whether to include transient fields
 274  
      * @return int hash code
 275  
      * @throws IllegalArgumentException
 276  
      *             if the Object is <code>null</code>
 277  
      * @throws IllegalArgumentException
 278  
      *             if the number is zero or even
 279  
      */
 280  
     public static int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final Object object,
 281  
             final boolean testTransients) {
 282  5
         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
 283  
     }
 284  
 
 285  
     /**
 286  
      * <p>
 287  
      * This method uses reflection to build a valid hash code.
 288  
      * </p>
 289  
      *
 290  
      * <p>
 291  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 292  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 293  
      * also not as efficient as testing explicitly.
 294  
      * </p>
 295  
      *
 296  
      * <p>
 297  
      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
 298  
      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
 299  
      * </p>
 300  
      *
 301  
      * <p>
 302  
      * Static fields will not be included. Superclass fields will be included up to and including the specified
 303  
      * superclass. A null superclass is treated as java.lang.Object.
 304  
      * </p>
 305  
      *
 306  
      * <p>
 307  
      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
 308  
      * however this is not vital. Prime numbers are preferred, especially for the multiplier.
 309  
      * </p>
 310  
      *
 311  
      * @param <T>
 312  
      *            the type of the object involved
 313  
      * @param initialNonZeroOddNumber
 314  
      *            a non-zero, odd number used as the initial value
 315  
      * @param multiplierNonZeroOddNumber
 316  
      *            a non-zero, odd number used as the multiplier
 317  
      * @param object
 318  
      *            the Object to create a <code>hashCode</code> for
 319  
      * @param testTransients
 320  
      *            whether to include transient fields
 321  
      * @param reflectUpToClass
 322  
      *            the superclass to reflect up to (inclusive), may be <code>null</code>
 323  
      * @param excludeFields
 324  
      *            array of field names to exclude from use in calculation of hash code
 325  
      * @return int hash code
 326  
      * @throws IllegalArgumentException
 327  
      *             if the Object is <code>null</code>
 328  
      * @throws IllegalArgumentException
 329  
      *             if the number is zero or even
 330  
      * @since 2.0
 331  
      */
 332  
     public static <T> int reflectionHashCode(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber, final T object,
 333  
             final boolean testTransients, final Class<? super T> reflectUpToClass, final String... excludeFields) {
 334  
 
 335  86
         if (object == null) {
 336  1
             throw new IllegalArgumentException("The object to build a hash code for must not be null");
 337  
         }
 338  85
         final HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
 339  81
         Class<?> clazz = object.getClass();
 340  81
         reflectionAppend(object, clazz, builder, testTransients, excludeFields);
 341  202
         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
 342  121
             clazz = clazz.getSuperclass();
 343  121
             reflectionAppend(object, clazz, builder, testTransients, excludeFields);
 344  
         }
 345  81
         return builder.toHashCode();
 346  
     }
 347  
 
 348  
     /**
 349  
      * <p>
 350  
      * This method uses reflection to build a valid hash code.
 351  
      * </p>
 352  
      *
 353  
      * <p>
 354  
      * This constructor uses two hard coded choices for the constants needed to build a hash code.
 355  
      * </p>
 356  
      *
 357  
      * <p>
 358  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 359  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 360  
      * also not as efficient as testing explicitly.
 361  
      * </p>
 362  
      *
 363  
      * <P>
 364  
      * If the TestTransients parameter is set to <code>true</code>, transient members will be tested, otherwise they
 365  
      * are ignored, as they are likely derived fields, and not part of the value of the <code>Object</code>.
 366  
      * </p>
 367  
      *
 368  
      * <p>
 369  
      * Static fields will not be tested. Superclass fields will be included.
 370  
      * </p>
 371  
      *
 372  
      * @param object
 373  
      *            the Object to create a <code>hashCode</code> for
 374  
      * @param testTransients
 375  
      *            whether to include transient fields
 376  
      * @return int hash code
 377  
      * @throws IllegalArgumentException
 378  
      *             if the object is <code>null</code>
 379  
      */
 380  
     public static int reflectionHashCode(final Object object, final boolean testTransients) {
 381  62
         return reflectionHashCode(17, 37, object, testTransients, null);
 382  
     }
 383  
 
 384  
     /**
 385  
      * <p>
 386  
      * This method uses reflection to build a valid hash code.
 387  
      * </p>
 388  
      *
 389  
      * <p>
 390  
      * This constructor uses two hard coded choices for the constants needed to build a hash code.
 391  
      * </p>
 392  
      *
 393  
      * <p>
 394  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 395  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 396  
      * also not as efficient as testing explicitly.
 397  
      * </p>
 398  
      *
 399  
      * <p>
 400  
      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
 401  
      * <code>Object</code>.
 402  
      * </p>
 403  
      *
 404  
      * <p>
 405  
      * Static fields will not be tested. Superclass fields will be included.
 406  
      * </p>
 407  
      *
 408  
      * @param object
 409  
      *            the Object to create a <code>hashCode</code> for
 410  
      * @param excludeFields
 411  
      *            Collection of String field names to exclude from use in calculation of hash code
 412  
      * @return int hash code
 413  
      * @throws IllegalArgumentException
 414  
      *             if the object is <code>null</code>
 415  
      */
 416  
     public static int reflectionHashCode(final Object object, final Collection<String> excludeFields) {
 417  0
         return reflectionHashCode(object, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
 418  
     }
 419  
 
 420  
     // -------------------------------------------------------------------------
 421  
 
 422  
     /**
 423  
      * <p>
 424  
      * This method uses reflection to build a valid hash code.
 425  
      * </p>
 426  
      *
 427  
      * <p>
 428  
      * This constructor uses two hard coded choices for the constants needed to build a hash code.
 429  
      * </p>
 430  
      *
 431  
      * <p>
 432  
      * It uses <code>AccessibleObject.setAccessible</code> to gain access to private fields. This means that it will
 433  
      * throw a security exception if run under a security manager, if the permissions are not set up correctly. It is
 434  
      * also not as efficient as testing explicitly.
 435  
      * </p>
 436  
      *
 437  
      * <p>
 438  
      * Transient members will be not be used, as they are likely derived fields, and not part of the value of the
 439  
      * <code>Object</code>.
 440  
      * </p>
 441  
      *
 442  
      * <p>
 443  
      * Static fields will not be tested. Superclass fields will be included.
 444  
      * </p>
 445  
      *
 446  
      * @param object
 447  
      *            the Object to create a <code>hashCode</code> for
 448  
      * @param excludeFields
 449  
      *            array of field names to exclude from use in calculation of hash code
 450  
      * @return int hash code
 451  
      * @throws IllegalArgumentException
 452  
      *             if the object is <code>null</code>
 453  
      */
 454  
     public static int reflectionHashCode(final Object object, final String... excludeFields) {
 455  19
         return reflectionHashCode(17, 37, object, false, null, excludeFields);
 456  
     }
 457  
 
 458  
     /**
 459  
      * <p>
 460  
      * Registers the given object. Used by the reflection methods to avoid infinite loops.
 461  
      * </p>
 462  
      *
 463  
      * @param value
 464  
      *            The object to register.
 465  
      */
 466  
     static void register(final Object value) {
 467  198
         synchronized (HashCodeBuilder.class) {
 468  198
             if (getRegistry() == null) {
 469  194
                 REGISTRY.set(new HashSet<IDKey>());
 470  
             }
 471  198
         }
 472  198
         getRegistry().add(new IDKey(value));
 473  198
     }
 474  
 
 475  
     /**
 476  
      * <p>
 477  
      * Unregisters the given object.
 478  
      * </p>
 479  
      *
 480  
      * <p>
 481  
      * Used by the reflection methods to avoid infinite loops.
 482  
      *
 483  
      * @param value
 484  
      *            The object to unregister.
 485  
      * @since 2.3
 486  
      */
 487  
     static void unregister(final Object value) {
 488  198
         Set<IDKey> registry = getRegistry();
 489  198
         if (registry != null) {
 490  198
             registry.remove(new IDKey(value));
 491  198
             synchronized (HashCodeBuilder.class) {
 492  
                 //read again
 493  198
                 registry = getRegistry();
 494  198
                 if (registry != null && registry.isEmpty()) {
 495  194
                     REGISTRY.remove();
 496  
                 }
 497  198
             }
 498  
         }
 499  198
     }
 500  
 
 501  
     /**
 502  
      * Constant to use in building the hashCode.
 503  
      */
 504  
     private final int iConstant;
 505  
 
 506  
     /**
 507  
      * Running total of the hashCode.
 508  
      */
 509  189
     private int iTotal = 0;
 510  
 
 511  
     /**
 512  
      * <p>
 513  
      * Uses two hard coded choices for the constants needed to build a <code>hashCode</code>.
 514  
      * </p>
 515  
      */
 516  10
     public HashCodeBuilder() {
 517  10
         iConstant = 37;
 518  10
         iTotal = 17;
 519  10
     }
 520  
 
 521  
     /**
 522  
      * <p>
 523  
      * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally these should be different for each class,
 524  
      * however this is not vital.
 525  
      * </p>
 526  
      *
 527  
      * <p>
 528  
      * Prime numbers are preferred, especially for the multiplier.
 529  
      * </p>
 530  
      *
 531  
      * @param initialNonZeroOddNumber
 532  
      *            a non-zero, odd number used as the initial value
 533  
      * @param multiplierNonZeroOddNumber
 534  
      *            a non-zero, odd number used as the multiplier
 535  
      * @throws IllegalArgumentException
 536  
      *             if the number is zero or even
 537  
      */
 538  179
     public HashCodeBuilder(final int initialNonZeroOddNumber, final int multiplierNonZeroOddNumber) {
 539  179
         if (initialNonZeroOddNumber == 0) {
 540  3
             throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
 541  
         }
 542  176
         if (initialNonZeroOddNumber % 2 == 0) {
 543  3
             throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
 544  
         }
 545  173
         if (multiplierNonZeroOddNumber == 0) {
 546  0
             throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
 547  
         }
 548  173
         if (multiplierNonZeroOddNumber % 2 == 0) {
 549  0
             throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
 550  
         }
 551  173
         iConstant = multiplierNonZeroOddNumber;
 552  173
         iTotal = initialNonZeroOddNumber;
 553  173
     }
 554  
 
 555  
     /**
 556  
      * <p>
 557  
      * Append a <code>hashCode</code> for a <code>boolean</code>.
 558  
      * </p>
 559  
      * <p>
 560  
      * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
 561  
      * </p>
 562  
      * <p>
 563  
      * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
 564  
      * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
 565  
      * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
 566  
      * that represent <code>false</code>.
 567  
      * </p>
 568  
      * <p>
 569  
      * This is in accordance with the <quote>Effective Java</quote> design.
 570  
      * </p>
 571  
      *
 572  
      * @param value
 573  
      *            the boolean to add to the <code>hashCode</code>
 574  
      * @return this
 575  
      */
 576  
     public HashCodeBuilder append(final boolean value) {
 577  26
         iTotal = iTotal * iConstant + (value ? 0 : 1);
 578  26
         return this;
 579  
     }
 580  
 
 581  
     /**
 582  
      * <p>
 583  
      * Append a <code>hashCode</code> for a <code>boolean</code> array.
 584  
      * </p>
 585  
      *
 586  
      * @param array
 587  
      *            the array to add to the <code>hashCode</code>
 588  
      * @return this
 589  
      */
 590  
     public HashCodeBuilder append(final boolean[] array) {
 591  15
         if (array == null) {
 592  1
             iTotal = iTotal * iConstant;
 593  
         } else {
 594  38
             for (final boolean element : array) {
 595  24
                 append(element);
 596  
             }
 597  
         }
 598  15
         return this;
 599  
     }
 600  
 
 601  
     // -------------------------------------------------------------------------
 602  
 
 603  
     /**
 604  
      * <p>
 605  
      * Append a <code>hashCode</code> for a <code>byte</code>.
 606  
      * </p>
 607  
      *
 608  
      * @param value
 609  
      *            the byte to add to the <code>hashCode</code>
 610  
      * @return this
 611  
      */
 612  
     public HashCodeBuilder append(final byte value) {
 613  14
         iTotal = iTotal * iConstant + value;
 614  14
         return this;
 615  
     }
 616  
 
 617  
     // -------------------------------------------------------------------------
 618  
 
 619  
     /**
 620  
      * <p>
 621  
      * Append a <code>hashCode</code> for a <code>byte</code> array.
 622  
      * </p>
 623  
      *
 624  
      * @param array
 625  
      *            the array to add to the <code>hashCode</code>
 626  
      * @return this
 627  
      */
 628  
     public HashCodeBuilder append(final byte[] array) {
 629  7
         if (array == null) {
 630  1
             iTotal = iTotal * iConstant;
 631  
         } else {
 632  18
             for (final byte element : array) {
 633  12
                 append(element);
 634  
             }
 635  
         }
 636  7
         return this;
 637  
     }
 638  
 
 639  
     /**
 640  
      * <p>
 641  
      * Append a <code>hashCode</code> for a <code>char</code>.
 642  
      * </p>
 643  
      *
 644  
      * @param value
 645  
      *            the char to add to the <code>hashCode</code>
 646  
      * @return this
 647  
      */
 648  
     public HashCodeBuilder append(final char value) {
 649  15
         iTotal = iTotal * iConstant + value;
 650  15
         return this;
 651  
     }
 652  
 
 653  
     /**
 654  
      * <p>
 655  
      * Append a <code>hashCode</code> for a <code>char</code> array.
 656  
      * </p>
 657  
      *
 658  
      * @param array
 659  
      *            the array to add to the <code>hashCode</code>
 660  
      * @return this
 661  
      */
 662  
     public HashCodeBuilder append(final char[] array) {
 663  7
         if (array == null) {
 664  1
             iTotal = iTotal * iConstant;
 665  
         } else {
 666  18
             for (final char element : array) {
 667  12
                 append(element);
 668  
             }
 669  
         }
 670  7
         return this;
 671  
     }
 672  
 
 673  
     /**
 674  
      * <p>
 675  
      * Append a <code>hashCode</code> for a <code>double</code>.
 676  
      * </p>
 677  
      *
 678  
      * @param value
 679  
      *            the double to add to the <code>hashCode</code>
 680  
      * @return this
 681  
      */
 682  
     public HashCodeBuilder append(final double value) {
 683  14
         return append(Double.doubleToLongBits(value));
 684  
     }
 685  
 
 686  
     /**
 687  
      * <p>
 688  
      * Append a <code>hashCode</code> for a <code>double</code> array.
 689  
      * </p>
 690  
      *
 691  
      * @param array
 692  
      *            the array to add to the <code>hashCode</code>
 693  
      * @return this
 694  
      */
 695  
     public HashCodeBuilder append(final double[] array) {
 696  7
         if (array == null) {
 697  1
             iTotal = iTotal * iConstant;
 698  
         } else {
 699  18
             for (final double element : array) {
 700  12
                 append(element);
 701  
             }
 702  
         }
 703  7
         return this;
 704  
     }
 705  
 
 706  
     /**
 707  
      * <p>
 708  
      * Append a <code>hashCode</code> for a <code>float</code>.
 709  
      * </p>
 710  
      *
 711  
      * @param value
 712  
      *            the float to add to the <code>hashCode</code>
 713  
      * @return this
 714  
      */
 715  
     public HashCodeBuilder append(final float value) {
 716  14
         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
 717  14
         return this;
 718  
     }
 719  
 
 720  
     /**
 721  
      * <p>
 722  
      * Append a <code>hashCode</code> for a <code>float</code> array.
 723  
      * </p>
 724  
      *
 725  
      * @param array
 726  
      *            the array to add to the <code>hashCode</code>
 727  
      * @return this
 728  
      */
 729  
     public HashCodeBuilder append(final float[] array) {
 730  7
         if (array == null) {
 731  1
             iTotal = iTotal * iConstant;
 732  
         } else {
 733  18
             for (final float element : array) {
 734  12
                 append(element);
 735  
             }
 736  
         }
 737  7
         return this;
 738  
     }
 739  
 
 740  
     /**
 741  
      * <p>
 742  
      * Append a <code>hashCode</code> for an <code>int</code>.
 743  
      * </p>
 744  
      *
 745  
      * @param value
 746  
      *            the int to add to the <code>hashCode</code>
 747  
      * @return this
 748  
      */
 749  
     public HashCodeBuilder append(final int value) {
 750  18
         iTotal = iTotal * iConstant + value;
 751  18
         return this;
 752  
     }
 753  
 
 754  
     /**
 755  
      * <p>
 756  
      * Append a <code>hashCode</code> for an <code>int</code> array.
 757  
      * </p>
 758  
      *
 759  
      * @param array
 760  
      *            the array to add to the <code>hashCode</code>
 761  
      * @return this
 762  
      */
 763  
     public HashCodeBuilder append(final int[] array) {
 764  9
         if (array == null) {
 765  1
             iTotal = iTotal * iConstant;
 766  
         } else {
 767  24
             for (final int element : array) {
 768  16
                 append(element);
 769  
             }
 770  
         }
 771  9
         return this;
 772  
     }
 773  
 
 774  
     /**
 775  
      * <p>
 776  
      * Append a <code>hashCode</code> for a <code>long</code>.
 777  
      * </p>
 778  
      *
 779  
      * @param value
 780  
      *            the long to add to the <code>hashCode</code>
 781  
      * @return this
 782  
      */
 783  
     // NOTE: This method uses >> and not >>> as Effective Java and
 784  
     //       Long.hashCode do. Ideally we should switch to >>> at
 785  
     //       some stage. There are backwards compat issues, so
 786  
     //       that will have to wait for the time being. cf LANG-342.
 787  
     public HashCodeBuilder append(final long value) {
 788  44
         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
 789  44
         return this;
 790  
     }
 791  
 
 792  
     /**
 793  
      * <p>
 794  
      * Append a <code>hashCode</code> for a <code>long</code> array.
 795  
      * </p>
 796  
      *
 797  
      * @param array
 798  
      *            the array to add to the <code>hashCode</code>
 799  
      * @return this
 800  
      */
 801  
     public HashCodeBuilder append(final long[] array) {
 802  15
         if (array == null) {
 803  1
             iTotal = iTotal * iConstant;
 804  
         } else {
 805  42
             for (final long element : array) {
 806  28
                 append(element);
 807  
             }
 808  
         }
 809  15
         return this;
 810  
     }
 811  
 
 812  
     /**
 813  
      * <p>
 814  
      * Append a <code>hashCode</code> for an <code>Object</code>.
 815  
      * </p>
 816  
      *
 817  
      * @param object
 818  
      *            the Object to add to the <code>hashCode</code>
 819  
      * @return this
 820  
      */
 821  
     public HashCodeBuilder append(final Object object) {
 822  284
         if (object == null) {
 823  14
             iTotal = iTotal * iConstant;
 824  
 
 825  
         } else {
 826  270
             if(object.getClass().isArray()) {
 827  
                 // 'Switch' on type of array, to dispatch to the correct handler
 828  
                 // This handles multi dimensional arrays
 829  55
                 if (object instanceof long[]) {
 830  11
                     append((long[]) object);
 831  44
                 } else if (object instanceof int[]) {
 832  5
                     append((int[]) object);
 833  39
                 } else if (object instanceof short[]) {
 834  3
                     append((short[]) object);
 835  36
                 } else if (object instanceof char[]) {
 836  3
                     append((char[]) object);
 837  33
                 } else if (object instanceof byte[]) {
 838  3
                     append((byte[]) object);
 839  30
                 } else if (object instanceof double[]) {
 840  3
                     append((double[]) object);
 841  27
                 } else if (object instanceof float[]) {
 842  3
                     append((float[]) object);
 843  24
                 } else if (object instanceof boolean[]) {
 844  11
                     append((boolean[]) object);
 845  
                 } else {
 846  
                     // Not an array of primitives
 847  13
                     append((Object[]) object);
 848  
                 }
 849  
             } else {
 850  215
                 iTotal = iTotal * iConstant + object.hashCode();
 851  
             }
 852  
         }
 853  284
         return this;
 854  
     }
 855  
 
 856  
     /**
 857  
      * <p>
 858  
      * Append a <code>hashCode</code> for an <code>Object</code> array.
 859  
      * </p>
 860  
      *
 861  
      * @param array
 862  
      *            the array to add to the <code>hashCode</code>
 863  
      * @return this
 864  
      */
 865  
     public HashCodeBuilder append(final Object[] array) {
 866  23
         if (array == null) {
 867  1
             iTotal = iTotal * iConstant;
 868  
         } else {
 869  62
             for (final Object element : array) {
 870  40
                 append(element);
 871  
             }
 872  
         }
 873  23
         return this;
 874  
     }
 875  
 
 876  
     /**
 877  
      * <p>
 878  
      * Append a <code>hashCode</code> for a <code>short</code>.
 879  
      * </p>
 880  
      *
 881  
      * @param value
 882  
      *            the short to add to the <code>hashCode</code>
 883  
      * @return this
 884  
      */
 885  
     public HashCodeBuilder append(final short value) {
 886  14
         iTotal = iTotal * iConstant + value;
 887  14
         return this;
 888  
     }
 889  
 
 890  
     /**
 891  
      * <p>
 892  
      * Append a <code>hashCode</code> for a <code>short</code> array.
 893  
      * </p>
 894  
      *
 895  
      * @param array
 896  
      *            the array to add to the <code>hashCode</code>
 897  
      * @return this
 898  
      */
 899  
     public HashCodeBuilder append(final short[] array) {
 900  7
         if (array == null) {
 901  1
             iTotal = iTotal * iConstant;
 902  
         } else {
 903  18
             for (final short element : array) {
 904  12
                 append(element);
 905  
             }
 906  
         }
 907  7
         return this;
 908  
     }
 909  
 
 910  
     /**
 911  
      * <p>
 912  
      * Adds the result of super.hashCode() to this builder.
 913  
      * </p>
 914  
      *
 915  
      * @param superHashCode
 916  
      *            the result of calling <code>super.hashCode()</code>
 917  
      * @return this HashCodeBuilder, used to chain calls.
 918  
      * @since 2.0
 919  
      */
 920  
     public HashCodeBuilder appendSuper(final int superHashCode) {
 921  1
         iTotal = iTotal * iConstant + superHashCode;
 922  1
         return this;
 923  
     }
 924  
 
 925  
     /**
 926  
      * <p>
 927  
      * Return the computed <code>hashCode</code>.
 928  
      * </p>
 929  
      *
 930  
      * @return <code>hashCode</code> based on the fields appended
 931  
      */
 932  
     public int toHashCode() {
 933  184
         return iTotal;
 934  
     }
 935  
 
 936  
     /**
 937  
      * Returns the computed <code>hashCode</code>.
 938  
      *
 939  
      * @return <code>hashCode</code> based on the fields appended
 940  
      *
 941  
      * @since 3.0
 942  
      */
 943  
     @Override
 944  
     public Integer build() {
 945  2
         return Integer.valueOf(toHashCode());
 946  
     }
 947  
 
 948  
     /**
 949  
      * <p>
 950  
      * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
 951  
      * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
 952  
      * HashCodeBuilder itself is.</p>
 953  
      *
 954  
      * @return <code>hashCode</code> based on the fields appended
 955  
      * @since 2.5
 956  
      */
 957  
     @Override
 958  
     public int hashCode() {
 959  1
         return toHashCode();
 960  
     }
 961  
 
 962  
 }