Coverage Report - org.apache.commons.lang3.builder.HashCodeBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
HashCodeBuilder
95%
143/149
95%
90/94
2,486
 
 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://www.oracle.com/technetwork/java/effectivejava-136174.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 1583482 2014-03-31 22:54:57Z niallp $
 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  190
     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, 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 initialOddNumber
 532  
      *            an odd number used as the initial value
 533  
      * @param multiplierOddNumber
 534  
      *            an odd number used as the multiplier
 535  
      * @throws IllegalArgumentException
 536  
      *             if the number is even
 537  
      */
 538  180
     public HashCodeBuilder(final int initialOddNumber, final int multiplierOddNumber) {
 539  180
         if (initialOddNumber % 2 == 0) {
 540  7
             throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
 541  
         }
 542  173
         if (multiplierOddNumber % 2 == 0) {
 543  0
             throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
 544  
         }
 545  173
         iConstant = multiplierOddNumber;
 546  173
         iTotal = initialOddNumber;
 547  173
     }
 548  
 
 549  
     /**
 550  
      * <p>
 551  
      * Append a <code>hashCode</code> for a <code>boolean</code>.
 552  
      * </p>
 553  
      * <p>
 554  
      * This adds <code>1</code> when true, and <code>0</code> when false to the <code>hashCode</code>.
 555  
      * </p>
 556  
      * <p>
 557  
      * This is in contrast to the standard <code>java.lang.Boolean.hashCode</code> handling, which computes
 558  
      * a <code>hashCode</code> value of <code>1231</code> for <code>java.lang.Boolean</code> instances
 559  
      * that represent <code>true</code> or <code>1237</code> for <code>java.lang.Boolean</code> instances
 560  
      * that represent <code>false</code>.
 561  
      * </p>
 562  
      * <p>
 563  
      * This is in accordance with the <i>Effective Java</i> design.
 564  
      * </p>
 565  
      *
 566  
      * @param value
 567  
      *            the boolean to add to the <code>hashCode</code>
 568  
      * @return this
 569  
      */
 570  
     public HashCodeBuilder append(final boolean value) {
 571  26
         iTotal = iTotal * iConstant + (value ? 0 : 1);
 572  26
         return this;
 573  
     }
 574  
 
 575  
     /**
 576  
      * <p>
 577  
      * Append a <code>hashCode</code> for a <code>boolean</code> array.
 578  
      * </p>
 579  
      *
 580  
      * @param array
 581  
      *            the array to add to the <code>hashCode</code>
 582  
      * @return this
 583  
      */
 584  
     public HashCodeBuilder append(final boolean[] array) {
 585  15
         if (array == null) {
 586  1
             iTotal = iTotal * iConstant;
 587  
         } else {
 588  38
             for (final boolean element : array) {
 589  24
                 append(element);
 590  
             }
 591  
         }
 592  15
         return this;
 593  
     }
 594  
 
 595  
     // -------------------------------------------------------------------------
 596  
 
 597  
     /**
 598  
      * <p>
 599  
      * Append a <code>hashCode</code> for a <code>byte</code>.
 600  
      * </p>
 601  
      *
 602  
      * @param value
 603  
      *            the byte to add to the <code>hashCode</code>
 604  
      * @return this
 605  
      */
 606  
     public HashCodeBuilder append(final byte value) {
 607  14
         iTotal = iTotal * iConstant + value;
 608  14
         return this;
 609  
     }
 610  
 
 611  
     // -------------------------------------------------------------------------
 612  
 
 613  
     /**
 614  
      * <p>
 615  
      * Append a <code>hashCode</code> for a <code>byte</code> array.
 616  
      * </p>
 617  
      *
 618  
      * @param array
 619  
      *            the array to add to the <code>hashCode</code>
 620  
      * @return this
 621  
      */
 622  
     public HashCodeBuilder append(final byte[] array) {
 623  7
         if (array == null) {
 624  1
             iTotal = iTotal * iConstant;
 625  
         } else {
 626  18
             for (final byte element : array) {
 627  12
                 append(element);
 628  
             }
 629  
         }
 630  7
         return this;
 631  
     }
 632  
 
 633  
     /**
 634  
      * <p>
 635  
      * Append a <code>hashCode</code> for a <code>char</code>.
 636  
      * </p>
 637  
      *
 638  
      * @param value
 639  
      *            the char to add to the <code>hashCode</code>
 640  
      * @return this
 641  
      */
 642  
     public HashCodeBuilder append(final char value) {
 643  15
         iTotal = iTotal * iConstant + value;
 644  15
         return this;
 645  
     }
 646  
 
 647  
     /**
 648  
      * <p>
 649  
      * Append a <code>hashCode</code> for a <code>char</code> array.
 650  
      * </p>
 651  
      *
 652  
      * @param array
 653  
      *            the array to add to the <code>hashCode</code>
 654  
      * @return this
 655  
      */
 656  
     public HashCodeBuilder append(final char[] array) {
 657  7
         if (array == null) {
 658  1
             iTotal = iTotal * iConstant;
 659  
         } else {
 660  18
             for (final char element : array) {
 661  12
                 append(element);
 662  
             }
 663  
         }
 664  7
         return this;
 665  
     }
 666  
 
 667  
     /**
 668  
      * <p>
 669  
      * Append a <code>hashCode</code> for a <code>double</code>.
 670  
      * </p>
 671  
      *
 672  
      * @param value
 673  
      *            the double to add to the <code>hashCode</code>
 674  
      * @return this
 675  
      */
 676  
     public HashCodeBuilder append(final double value) {
 677  14
         return append(Double.doubleToLongBits(value));
 678  
     }
 679  
 
 680  
     /**
 681  
      * <p>
 682  
      * Append a <code>hashCode</code> for a <code>double</code> array.
 683  
      * </p>
 684  
      *
 685  
      * @param array
 686  
      *            the array to add to the <code>hashCode</code>
 687  
      * @return this
 688  
      */
 689  
     public HashCodeBuilder append(final double[] array) {
 690  7
         if (array == null) {
 691  1
             iTotal = iTotal * iConstant;
 692  
         } else {
 693  18
             for (final double element : array) {
 694  12
                 append(element);
 695  
             }
 696  
         }
 697  7
         return this;
 698  
     }
 699  
 
 700  
     /**
 701  
      * <p>
 702  
      * Append a <code>hashCode</code> for a <code>float</code>.
 703  
      * </p>
 704  
      *
 705  
      * @param value
 706  
      *            the float to add to the <code>hashCode</code>
 707  
      * @return this
 708  
      */
 709  
     public HashCodeBuilder append(final float value) {
 710  14
         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
 711  14
         return this;
 712  
     }
 713  
 
 714  
     /**
 715  
      * <p>
 716  
      * Append a <code>hashCode</code> for a <code>float</code> array.
 717  
      * </p>
 718  
      *
 719  
      * @param array
 720  
      *            the array to add to the <code>hashCode</code>
 721  
      * @return this
 722  
      */
 723  
     public HashCodeBuilder append(final float[] array) {
 724  7
         if (array == null) {
 725  1
             iTotal = iTotal * iConstant;
 726  
         } else {
 727  18
             for (final float element : array) {
 728  12
                 append(element);
 729  
             }
 730  
         }
 731  7
         return this;
 732  
     }
 733  
 
 734  
     /**
 735  
      * <p>
 736  
      * Append a <code>hashCode</code> for an <code>int</code>.
 737  
      * </p>
 738  
      *
 739  
      * @param value
 740  
      *            the int to add to the <code>hashCode</code>
 741  
      * @return this
 742  
      */
 743  
     public HashCodeBuilder append(final int value) {
 744  18
         iTotal = iTotal * iConstant + value;
 745  18
         return this;
 746  
     }
 747  
 
 748  
     /**
 749  
      * <p>
 750  
      * Append a <code>hashCode</code> for an <code>int</code> array.
 751  
      * </p>
 752  
      *
 753  
      * @param array
 754  
      *            the array to add to the <code>hashCode</code>
 755  
      * @return this
 756  
      */
 757  
     public HashCodeBuilder append(final int[] array) {
 758  9
         if (array == null) {
 759  1
             iTotal = iTotal * iConstant;
 760  
         } else {
 761  24
             for (final int element : array) {
 762  16
                 append(element);
 763  
             }
 764  
         }
 765  9
         return this;
 766  
     }
 767  
 
 768  
     /**
 769  
      * <p>
 770  
      * Append a <code>hashCode</code> for a <code>long</code>.
 771  
      * </p>
 772  
      *
 773  
      * @param value
 774  
      *            the long to add to the <code>hashCode</code>
 775  
      * @return this
 776  
      */
 777  
     // NOTE: This method uses >> and not >>> as Effective Java and
 778  
     //       Long.hashCode do. Ideally we should switch to >>> at
 779  
     //       some stage. There are backwards compat issues, so
 780  
     //       that will have to wait for the time being. cf LANG-342.
 781  
     public HashCodeBuilder append(final long value) {
 782  44
         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
 783  44
         return this;
 784  
     }
 785  
 
 786  
     /**
 787  
      * <p>
 788  
      * Append a <code>hashCode</code> for a <code>long</code> array.
 789  
      * </p>
 790  
      *
 791  
      * @param array
 792  
      *            the array to add to the <code>hashCode</code>
 793  
      * @return this
 794  
      */
 795  
     public HashCodeBuilder append(final long[] array) {
 796  15
         if (array == null) {
 797  1
             iTotal = iTotal * iConstant;
 798  
         } else {
 799  42
             for (final long element : array) {
 800  28
                 append(element);
 801  
             }
 802  
         }
 803  15
         return this;
 804  
     }
 805  
 
 806  
     /**
 807  
      * <p>
 808  
      * Append a <code>hashCode</code> for an <code>Object</code>.
 809  
      * </p>
 810  
      *
 811  
      * @param object
 812  
      *            the Object to add to the <code>hashCode</code>
 813  
      * @return this
 814  
      */
 815  
     public HashCodeBuilder append(final Object object) {
 816  284
         if (object == null) {
 817  14
             iTotal = iTotal * iConstant;
 818  
 
 819  
         } else {
 820  270
             if(object.getClass().isArray()) {
 821  
                 // 'Switch' on type of array, to dispatch to the correct handler
 822  
                 // This handles multi dimensional arrays
 823  55
                 if (object instanceof long[]) {
 824  11
                     append((long[]) object);
 825  44
                 } else if (object instanceof int[]) {
 826  5
                     append((int[]) object);
 827  39
                 } else if (object instanceof short[]) {
 828  3
                     append((short[]) object);
 829  36
                 } else if (object instanceof char[]) {
 830  3
                     append((char[]) object);
 831  33
                 } else if (object instanceof byte[]) {
 832  3
                     append((byte[]) object);
 833  30
                 } else if (object instanceof double[]) {
 834  3
                     append((double[]) object);
 835  27
                 } else if (object instanceof float[]) {
 836  3
                     append((float[]) object);
 837  24
                 } else if (object instanceof boolean[]) {
 838  11
                     append((boolean[]) object);
 839  
                 } else {
 840  
                     // Not an array of primitives
 841  13
                     append((Object[]) object);
 842  
                 }
 843  
             } else {
 844  215
                 iTotal = iTotal * iConstant + object.hashCode();
 845  
             }
 846  
         }
 847  284
         return this;
 848  
     }
 849  
 
 850  
     /**
 851  
      * <p>
 852  
      * Append a <code>hashCode</code> for an <code>Object</code> array.
 853  
      * </p>
 854  
      *
 855  
      * @param array
 856  
      *            the array to add to the <code>hashCode</code>
 857  
      * @return this
 858  
      */
 859  
     public HashCodeBuilder append(final Object[] array) {
 860  23
         if (array == null) {
 861  1
             iTotal = iTotal * iConstant;
 862  
         } else {
 863  62
             for (final Object element : array) {
 864  40
                 append(element);
 865  
             }
 866  
         }
 867  23
         return this;
 868  
     }
 869  
 
 870  
     /**
 871  
      * <p>
 872  
      * Append a <code>hashCode</code> for a <code>short</code>.
 873  
      * </p>
 874  
      *
 875  
      * @param value
 876  
      *            the short to add to the <code>hashCode</code>
 877  
      * @return this
 878  
      */
 879  
     public HashCodeBuilder append(final short value) {
 880  14
         iTotal = iTotal * iConstant + value;
 881  14
         return this;
 882  
     }
 883  
 
 884  
     /**
 885  
      * <p>
 886  
      * Append a <code>hashCode</code> for a <code>short</code> array.
 887  
      * </p>
 888  
      *
 889  
      * @param array
 890  
      *            the array to add to the <code>hashCode</code>
 891  
      * @return this
 892  
      */
 893  
     public HashCodeBuilder append(final short[] array) {
 894  7
         if (array == null) {
 895  1
             iTotal = iTotal * iConstant;
 896  
         } else {
 897  18
             for (final short element : array) {
 898  12
                 append(element);
 899  
             }
 900  
         }
 901  7
         return this;
 902  
     }
 903  
 
 904  
     /**
 905  
      * <p>
 906  
      * Adds the result of super.hashCode() to this builder.
 907  
      * </p>
 908  
      *
 909  
      * @param superHashCode
 910  
      *            the result of calling <code>super.hashCode()</code>
 911  
      * @return this HashCodeBuilder, used to chain calls.
 912  
      * @since 2.0
 913  
      */
 914  
     public HashCodeBuilder appendSuper(final int superHashCode) {
 915  1
         iTotal = iTotal * iConstant + superHashCode;
 916  1
         return this;
 917  
     }
 918  
 
 919  
     /**
 920  
      * <p>
 921  
      * Return the computed <code>hashCode</code>.
 922  
      * </p>
 923  
      *
 924  
      * @return <code>hashCode</code> based on the fields appended
 925  
      */
 926  
     public int toHashCode() {
 927  184
         return iTotal;
 928  
     }
 929  
 
 930  
     /**
 931  
      * Returns the computed <code>hashCode</code>.
 932  
      *
 933  
      * @return <code>hashCode</code> based on the fields appended
 934  
      *
 935  
      * @since 3.0
 936  
      */
 937  
     @Override
 938  
     public Integer build() {
 939  2
         return Integer.valueOf(toHashCode());
 940  
     }
 941  
 
 942  
     /**
 943  
      * <p>
 944  
      * The computed <code>hashCode</code> from toHashCode() is returned due to the likelihood
 945  
      * of bugs in mis-calling toHashCode() and the unlikeliness of it mattering what the hashCode for
 946  
      * HashCodeBuilder itself is.</p>
 947  
      *
 948  
      * @return <code>hashCode</code> based on the fields appended
 949  
      * @since 2.5
 950  
      */
 951  
     @Override
 952  
     public int hashCode() {
 953  1
         return toHashCode();
 954  
     }
 955  
 
 956  
 }