Coverage report

  %line %branch
net.sf.classifier4J.util.HashCodeBuilder
0% 
0% 

 1  
 /* ====================================================================
 2  
  * The Apache Software License, Version 1.1
 3  
  *
 4  
  * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 5  
  * reserved.
 6  
  *
 7  
  * Redistribution and use in source and binary forms, with or without
 8  
  * modification, are permitted provided that the following conditions
 9  
  * are met:
 10  
  *
 11  
  * 1. Redistributions of source code must retain the above copyright
 12  
  *    notice, this list of conditions and the following disclaimer.
 13  
  *
 14  
  * 2. Redistributions in binary form must reproduce the above copyright
 15  
  *    notice, this list of conditions and the following disclaimer in
 16  
  *    the documentation and/or other materials provided with the
 17  
  *    distribution.
 18  
  *
 19  
  * 3. The end-user documentation included with the redistribution, if
 20  
  *    any, must include the following acknowledgement:
 21  
  *       "This product includes software developed by the
 22  
  *        Apache Software Foundation (http://www.apache.org/)."
 23  
  *    Alternately, this acknowledgement may appear in the software itself,
 24  
  *    if and wherever such third-party acknowledgements normally appear.
 25  
  *
 26  
  * 4. The names "The Jakarta Project", "Commons", and "Apache Software
 27  
  *    Foundation" must not be used to endorse or promote products derived
 28  
  *    from this software without prior written permission. For written
 29  
  *    permission, please contact apache@apache.org.
 30  
  *
 31  
  * 5. Products derived from this software may not be called "Apache"
 32  
  *    nor may "Apache" appear in their names without prior written
 33  
  *    permission of the Apache Software Foundation.
 34  
  *
 35  
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36  
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37  
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38  
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39  
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40  
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41  
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42  
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43  
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44  
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45  
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46  
  * SUCH DAMAGE.
 47  
  * ====================================================================
 48  
  *
 49  
  * This software consists of voluntary contributions made by many
 50  
  * individuals on behalf of the Apache Software Foundation.  For more
 51  
  * information on the Apache Software Foundation, please see
 52  
  * <http://www.apache.org/>.
 53  
  */
 54  
 package net.sf.classifier4J.util;
 55  
 
 56  
 import java.lang.reflect.AccessibleObject;
 57  
 import java.lang.reflect.Field;
 58  
 import java.lang.reflect.Modifier;
 59  
 
 60  
 /**
 61  
  * <p>Assists in implementing {@link Object#hashCode()} methods.</p>
 62  
  *
 63  
  * <p> This class enables a good <code>hashCode</code> method to be built for any class. It
 64  
  * follows the rules laid out in the book
 65  
  * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a>
 66  
  * by Joshua Bloch. Writing a good <code>hashCode</code> method is actually quite
 67  
  * difficult. This class aims to simplify the process.</p>
 68  
  *
 69  
  * <p>All relevant fields from the object should be included in the
 70  
  * <code>hashCode</code> method. Derived fields may be excluded. In general, any
 71  
  * field used in the <code>equals</code> method must be used in the <code>hashCode</code>
 72  
  * method.</p>
 73  
  *
 74  
  * <p>To use this class write code as follows:</p>
 75  
  * <pre>
 76  
  * public class Person {
 77  
  *   String name;
 78  
  *   int age;
 79  
  *   boolean isSmoker;
 80  
  *   ...
 81  
  *
 82  
  *   public int hashCode() {
 83  
  *     // you pick a hard-coded, randomly chosen, non-zero, odd number
 84  
  *     // ideally different for each class
 85  
  *     return new HashCodeBuilder(17, 37).
 86  
  *       append(name).
 87  
  *       append(age).
 88  
  *       append(smoker).
 89  
  *       toHashCode();
 90  
  *   }
 91  
  * }
 92  
  * </pre>
 93  
  *
 94  
  * <p>If required, the superclass <code>hashCode()</code> can be added
 95  
  * using {@link #appendSuper}.</p>
 96  
  *
 97  
  * <p>Alternatively, there is a method that uses reflection to determine
 98  
  * the fields to test. Because these fields are usually private, the method,
 99  
  * <code>reflectionHashCode</code>, uses <code>AccessibleObject.setAccessible</code> to
 100  
  * change the visibility of the fields. This will fail under a security manager,
 101  
  * unless the appropriate permissions are set up correctly. It is also slower
 102  
  * than testing explicitly.</p>
 103  
  *
 104  
  * <p>A typical invocation for this method would look like:</p>
 105  
  * <pre>
 106  
  * public int hashCode() {
 107  
  *   return HashCodeBuilder.reflectionHashCode(this);
 108  
  * }
 109  
  * </pre>
 110  
  *
 111  
  * @author Stephen Colebourne
 112  
  * @author Gary Gregory
 113  
  * @author Pete Gieser
 114  
  * @since 1.0
 115  
  * @version $Id: HashCodeBuilder.java,v 1.1 2005/02/04 05:30:28 nicklothian Exp $
 116  
  */
 117  
 public class HashCodeBuilder {
 118  
 
 119  
     /**
 120  
      * Constant to use in building the hashCode.
 121  
      */
 122  
     private final int iConstant;
 123  
     /**
 124  
      * Running total of the hashCode.
 125  
      */
 126  0
     private int iTotal = 0;
 127  
 
 128  
     /**
 129  
      * <p>Constructor.</p>
 130  
      *
 131  
      * <p>This constructor uses two hard coded choices for the constants
 132  
      * needed to build a <code>hashCode</code>.</p>
 133  
      */
 134  
     public HashCodeBuilder() {
 135  0
         super();
 136  0
         iConstant = 37;
 137  0
         iTotal = 17;
 138  0
     }
 139  
 
 140  
     /**
 141  
      * <p>Constructor.</p>
 142  
      *
 143  
      * <p>Two randomly chosen, non-zero, odd numbers must be passed in.
 144  
      * Ideally these should be different for each class, however this is
 145  
      * not vital.</p>
 146  
      *
 147  
      * <p>Prime numbers are preferred, especially for the multiplier.</p>
 148  
      *
 149  
      * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
 150  
      * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
 151  
      * @throws IllegalArgumentException if the number is zero or even
 152  
      */
 153  
     public HashCodeBuilder(int initialNonZeroOddNumber, class="keyword">int multiplierNonZeroOddNumber) {
 154  0
         super();
 155  0
         if (initialNonZeroOddNumber == 0) {
 156  0
             throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
 157  
         }
 158  0
         if (initialNonZeroOddNumber % 2 == 0) {
 159  0
             throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
 160  
         }
 161  0
         if (multiplierNonZeroOddNumber == 0) {
 162  0
             throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
 163  
         }
 164  0
         if (multiplierNonZeroOddNumber % 2 == 0) {
 165  0
             throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
 166  
         }
 167  0
         iConstant = multiplierNonZeroOddNumber;
 168  0
         iTotal = initialNonZeroOddNumber;
 169  0
     }
 170  
 
 171  
     //-------------------------------------------------------------------------
 172  
 
 173  
     /**
 174  
      * <p>This method uses reflection to build a valid hash code.</p>
 175  
      *
 176  
      * <p>This constructor uses two hard coded choices for the constants
 177  
      * needed to build a hash code.</p>
 178  
      *
 179  
      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
 180  
      * fields. This means that it will throw a security exception if run under
 181  
      * a security manager, if the permissions are not set up correctly. It is
 182  
      * also not as efficient as testing explicitly.</p>
 183  
      *
 184  
      * <p>Transient members will be not be used, as they are likely derived
 185  
      * fields, and not part of the value of the <code>Object</code>.</p>
 186  
      *
 187  
      * <p>Static fields will not be tested. Superclass fields will be included.</p>
 188  
      *
 189  
      * @param object  the Object to create a <code>hashCode</code> for
 190  
      * @return int hash code
 191  
      * @throws IllegalArgumentException if the object is <code>null</code>
 192  
      */
 193  
     public static int reflectionHashCode(Object object) {
 194  0
         return reflectionHashCode(17, 37, object, false, null);
 195  
     }
 196  
 
 197  
     /**
 198  
      * <p>This method uses reflection to build a valid hash code.</p>
 199  
      *
 200  
      * <p>This constructor uses two hard coded choices for the constants needed
 201  
      * to build a hash code.</p>
 202  
      *
 203  
      * <p> It uses <code>AccessibleObject.setAccessible</code> to gain access to private
 204  
      * fields. This means that it will throw a security exception if run under
 205  
      * a security manager, if the permissions are not set up correctly. It is
 206  
      * also not as efficient as testing explicitly.</p>
 207  
      *
 208  
      * <P>If the TestTransients parameter is set to <code>true</code>, transient
 209  
      * members will be tested, otherwise they are ignored, as they are likely
 210  
      * derived fields, and not part of the value of the <code>Object</code>.</p>
 211  
      *
 212  
      * <p>Static fields will not be tested. Superclass fields will be included.</p>
 213  
      *
 214  
      * @param object  the Object to create a <code>hashCode</code> for
 215  
      * @param testTransients  whether to include transient fields
 216  
      * @return int hash code
 217  
      * @throws IllegalArgumentException if the object is <code>null</code>
 218  
      */
 219  
     public static int reflectionHashCode(Object object, boolean testTransients) {
 220  0
         return reflectionHashCode(17, 37, object, testTransients, null);
 221  
     }
 222  
 
 223  
     /**
 224  
      * <p>This method uses reflection to build a valid hash code.</p>
 225  
      *
 226  
      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
 227  
      * fields. This means that it will throw a security exception if run under
 228  
      * a security manager, if the permissions are not set up correctly. It is
 229  
      * also not as efficient as testing explicitly.</p>
 230  
      *
 231  
      * <p>Transient members will be not be used, as they are likely derived
 232  
      * fields, and not part of the value of the <code>Object</code>.</p>
 233  
      *
 234  
      * <p>Static fields will not be tested. Superclass fields will be included.</p>
 235  
      *
 236  
      * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
 237  
      * these should be different for each class, however this is not vital.
 238  
      * Prime numbers are preferred, especially for the multiplier.</p>
 239  
      *
 240  
      * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
 241  
      * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
 242  
      * @param object  the Object to create a <code>hashCode</code> for
 243  
      * @return int hash code
 244  
      * @throws IllegalArgumentException if the Object is <code>null</code>
 245  
      * @throws IllegalArgumentException if the number is zero or even
 246  
      */
 247  
     public static int reflectionHashCode(
 248  
             int initialNonZeroOddNumber, class="keyword">int multiplierNonZeroOddNumber, Object object) {
 249  0
         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
 250  
     }
 251  
 
 252  
     /**
 253  
      * <p>This method uses reflection to build a valid hash code.</p>
 254  
      *
 255  
      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
 256  
      * fields. This means that it will throw a security exception if run under
 257  
      * a security manager, if the permissions are not set up correctly. It is also
 258  
      * not as efficient as testing explicitly.</p>
 259  
      *
 260  
      * <p>If the TestTransients parameter is set to <code>true</code>, transient
 261  
      * members will be tested, otherwise they are ignored, as they are likely
 262  
      * derived fields, and not part of the value of the <code>Object</code>.</p>
 263  
      *
 264  
      * <p>Static fields will not be tested. Superclass fields will be included.</p>
 265  
      *
 266  
      * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
 267  
      * these should be different for each class, however this is not vital.
 268  
      * Prime numbers are preferred, especially for the multiplier.</p>
 269  
      *
 270  
      * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
 271  
      * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
 272  
      * @param object  the Object to create a <code>hashCode</code> for
 273  
      * @param testTransients  whether to include transient fields
 274  
      * @return int hash code
 275  
      * @throws IllegalArgumentException if the Object is <code>null</code>
 276  
      * @throws IllegalArgumentException if the number is zero or even
 277  
      */
 278  
     public static int reflectionHashCode(
 279  
             int initialNonZeroOddNumber, class="keyword">int multiplierNonZeroOddNumber,
 280  
             Object object, boolean testTransients) {
 281  0
         return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
 282  
     }
 283  
             
 284  
     /**
 285  
      * <p>This method uses reflection to build a valid hash code.</p>
 286  
      *
 287  
      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
 288  
      * fields. This means that it will throw a security exception if run under
 289  
      * a security manager, if the permissions are not set up correctly. It is also
 290  
      * not as efficient as testing explicitly.</p>
 291  
      *
 292  
      * <p>If the TestTransients parameter is set to <code>true</code>, transient
 293  
      * members will be tested, otherwise they are ignored, as they are likely
 294  
      * derived fields, and not part of the value of the <code>Object</code>.</p>
 295  
      *
 296  
      * <p>Static fields will not be included. Superclass fields will be included
 297  
      * up to and including the specified superclass. A null superclass is treated
 298  
      * as java.lang.Object.</p>
 299  
      *
 300  
      * <p>Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
 301  
      * these should be different for each class, however this is not vital.
 302  
      * Prime numbers are preferred, especially for the multiplier.</p>
 303  
      *
 304  
      * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
 305  
      * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
 306  
      * @param object  the Object to create a <code>hashCode</code> for
 307  
      * @param testTransients  whether to include transient fields
 308  
      * @param reflectUpToClass  the superclass to reflect up to (inclusive),
 309  
      *  may be <code>null</code>
 310  
      * @return int hash code
 311  
      * @throws IllegalArgumentException if the Object is <code>null</code>
 312  
      * @throws IllegalArgumentException if the number is zero or even
 313  
      * @since 2.0
 314  
      */
 315  
     public static int reflectionHashCode(
 316  
         int initialNonZeroOddNumber,
 317  
         int multiplierNonZeroOddNumber,
 318  
         Object object,
 319  
         boolean testTransients,
 320  
         Class reflectUpToClass) {
 321  
 
 322  0
         if (object == null) {
 323  0
             throw new IllegalArgumentException("The object to build a hash code for must not be null");
 324  
         }
 325  0
         HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
 326  0
         Class clazz = object.getClass();
 327  0
         reflectionAppend(object, clazz, builder, testTransients);
 328  0
         while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
 329  0
             clazz = clazz.getSuperclass();
 330  0
             reflectionAppend(object, clazz, builder, testTransients);
 331  
         }
 332  0
         return builder.toHashCode();
 333  
     }
 334  
 
 335  
     /**
 336  
      * <p>Appends the fields and values defined by the given object of the
 337  
      * given <code>Class</code>.</p>
 338  
      * 
 339  
      * @param object  the object to append details of
 340  
      * @param clazz  the class to append details of
 341  
      * @param builder  the builder to append to
 342  
      * @param useTransients  whether to use transient fields
 343  
      */
 344  
     private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
 345  0
         Field[] fields = clazz.getDeclaredFields();
 346  0
         AccessibleObject.setAccessible(fields, true);
 347  0
         for (int i = 0; i < fields.length; i++) {
 348  0
             Field f = fields[i];
 349  0
             if ((f.getName().indexOf('$') == -1)
 350  
                 && (useTransients || !Modifier.isTransient(f.getModifiers()))
 351  
                 && (!Modifier.isStatic(f.getModifiers()))) {
 352  
                 try {
 353  0
                     builder.append(f.get(object));
 354  0
                 } catch (IllegalAccessException e) {
 355  
                     //this can't happen. Would get a Security exception instead
 356  
                     //throw a runtime exception in case the impossible happens.
 357  0
                     throw new InternalError("Unexpected IllegalAccessException");
 358  
                 }
 359  
             }
 360  
         }
 361  0
     }
 362  
 
 363  
     //-------------------------------------------------------------------------
 364  
 
 365  
     /**
 366  
      * <p>Adds the result of super.hashCode() to this builder.</p>
 367  
      *
 368  
      * @param superHashCode  the result of calling <code>super.hashCode()</code>
 369  
      * @return this HashCodeBuilder, used to chain calls.
 370  
      * @since 2.0
 371  
      */
 372  
     public HashCodeBuilder appendSuper(int superHashCode) {
 373  0
         iTotal = iTotal * iConstant + superHashCode;
 374  0
         return this;
 375  
     }
 376  
 
 377  
     //-------------------------------------------------------------------------
 378  
 
 379  
     /**
 380  
      * <p>Append a <code>hashCode</code> for an <code>Object</code>.</p>
 381  
      *
 382  
      * @param object  the Object to add to the <code>hashCode</code>
 383  
      * @return this
 384  
      */
 385  
     public HashCodeBuilder append(Object object) {
 386  0
         if (object == null) {
 387  0
             iTotal = iTotal * iConstant;
 388  
 
 389  
         } else {
 390  0
             if (object.getClass().isArray() == false) {
 391  
                 //the simple case, not an array, just the element
 392  0
                 iTotal = iTotal * iConstant + object.hashCode();
 393  
 
 394  
             } else {
 395  
                 //'Switch' on type of array, to dispatch to the correct handler
 396  
                 // This handles multi dimensional arrays
 397  0
                 if (object instanceof long[]) {
 398  0
                     append((long[]) object);
 399  0
                 } else if (object instanceof int[]) {
 400  0
                     append((int[]) object);
 401  0
                 } else if (object instanceof short[]) {
 402  0
                     append((short[]) object);
 403  0
                 } else if (object instanceof char[]) {
 404  0
                     append((char[]) object);
 405  0
                 } else if (object instanceof byte[]) {
 406  0
                     append((byte[]) object);
 407  0
                 } else if (object instanceof double[]) {
 408  0
                     append((double[]) object);
 409  0
                 } else if (object instanceof float[]) {
 410  0
                     append((float[]) object);
 411  0
                 } else if (object instanceof boolean[]) {
 412  0
                     append((boolean[]) object);
 413  
                 } else {
 414  
                     // Not an array of primitives
 415  0
                     append((Object[]) object);
 416  
                 }
 417  
             }
 418  
         }
 419  0
         return this;
 420  
     }
 421  
 
 422  
     /**
 423  
      * <p>Append a <code>hashCode</code> for a <code>long</code>.</p>
 424  
      *
 425  
      * @param value  the long to add to the <code>hashCode</code>
 426  
      * @return this
 427  
      */
 428  
     public HashCodeBuilder append(long value) {
 429  0
         iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
 430  0
         return this;
 431  
     }
 432  
 
 433  
     /**
 434  
      * <p>Append a <code>hashCode</code> for an <code>int</code>.</p>
 435  
      *
 436  
      * @param value  the int to add to the <code>hashCode</code>
 437  
      * @return this
 438  
      */
 439  
     public HashCodeBuilder append(int value) {
 440  0
         iTotal = iTotal * iConstant + value;
 441  0
         return this;
 442  
     }
 443  
 
 444  
     /**
 445  
      * <p>Append a <code>hashCode</code> for a <code>short</code>.</p>
 446  
      *
 447  
      * @param value  the short to add to the <code>hashCode</code>
 448  
      * @return this
 449  
      */
 450  
     public HashCodeBuilder append(short value) {
 451  0
         iTotal = iTotal * iConstant + value;
 452  0
         return this;
 453  
     }
 454  
 
 455  
     /**
 456  
      * <p>Append a <code>hashCode</code> for a <code>char</code>.</p>
 457  
      *
 458  
      * @param value  the char to add to the <code>hashCode</code>
 459  
      * @return this
 460  
      */
 461  
     public HashCodeBuilder append(char value) {
 462  0
         iTotal = iTotal * iConstant + value;
 463  0
         return this;
 464  
     }
 465  
 
 466  
     /**
 467  
      * <p>Append a <code>hashCode</code> for a <code>byte</code>.</p>
 468  
      *
 469  
      * @param value  the byte to add to the <code>hashCode</code>
 470  
      * @return this
 471  
      */
 472  
     public HashCodeBuilder append(byte value) {
 473  0
         iTotal = iTotal * iConstant + value;
 474  0
         return this;
 475  
     }
 476  
 
 477  
     /**
 478  
      * <p>Append a <code>hashCode</code> for a <code>double</code>.</p>
 479  
      *
 480  
      * @param value  the double to add to the <code>hashCode</code>
 481  
      * @return this
 482  
      */
 483  
     public HashCodeBuilder append(double value) {
 484  0
         return append(Double.doubleToLongBits(value));
 485  
     }
 486  
 
 487  
     /**
 488  
      * <p>Append a <code>hashCode</code> for a <code>float</code>.</p>
 489  
      *
 490  
      * @param value  the float to add to the <code>hashCode</code>
 491  
      * @return this
 492  
      */
 493  
     public HashCodeBuilder append(float value) {
 494  0
         iTotal = iTotal * iConstant + Float.floatToIntBits(value);
 495  0
         return this;
 496  
     }
 497  
 
 498  
     /**
 499  
      * <p>Append a <code>hashCode</code> for a <code>boolean</code>.</p>
 500  
      *
 501  
      * @param value  the boolean to add to the <code>hashCode</code>
 502  
      * @return this
 503  
      */
 504  
     public HashCodeBuilder append(boolean value) {
 505  0
         iTotal = iTotal * iConstant + (value ? 0 : 1);
 506  0
         return this;
 507  
     }
 508  
 
 509  
     /**
 510  
      * <p>Append a <code>hashCode</code> for an <code>Object</code> array.</p>
 511  
      *
 512  
      * @param array  the array to add to the <code>hashCode</code>
 513  
      * @return this
 514  
      */
 515  
     public HashCodeBuilder append(Object[] array) {
 516  0
         if (array == null) {
 517  0
             iTotal = iTotal * iConstant;
 518  
         } else {
 519  0
             for (int i = 0; i < array.length; i++) {
 520  0
                 append(array[i]);
 521  
             }
 522  
         }
 523  0
         return this;
 524  
     }
 525  
 
 526  
     /**
 527  
      * <p>Append a <code>hashCode</code> for a <code>long</code> array.</p>
 528  
      *
 529  
      * @param array  the array to add to the <code>hashCode</code>
 530  
      * @return this
 531  
      */
 532  
     public HashCodeBuilder append(long[] array) {
 533  0
         if (array == null) {
 534  0
             iTotal = iTotal * iConstant;
 535  
         } else {
 536  0
             for (int i = 0; i < array.length; i++) {
 537  0
                 append(array[i]);
 538  
             }
 539  
         }
 540  0
         return this;
 541  
     }
 542  
 
 543  
     /**
 544  
      * <p>Append a <code>hashCode</code> for an <code>int</code> array.</p>
 545  
      *
 546  
      * @param array  the array to add to the <code>hashCode</code>
 547  
      * @return this
 548  
      */
 549  
     public HashCodeBuilder append(int[] array) {
 550  0
         if (array == null) {
 551  0
             iTotal = iTotal * iConstant;
 552  
         } else {
 553  0
             for (int i = 0; i < array.length; i++) {
 554  0
                 append(array[i]);
 555  
             }
 556  
         }
 557  0
         return this;
 558  
     }
 559  
 
 560  
     /**
 561  
      * <p>Append a <code>hashCode</code> for a <code>short</code> array.</p>
 562  
      *
 563  
      * @param array  the array to add to the <code>hashCode</code>
 564  
      * @return this
 565  
      */
 566  
     public HashCodeBuilder append(short[] array) {
 567  0
         if (array == null) {
 568  0
             iTotal = iTotal * iConstant;
 569  
         } else {
 570  0
             for (int i = 0; i < array.length; i++) {
 571  0
                 append(array[i]);
 572  
             }
 573  
         }
 574  0
         return this;
 575  
     }
 576  
 
 577  
     /**
 578  
      * <p>Append a <code>hashCode</code> for a <code>char</code> array.</p>
 579  
      *
 580  
      * @param array  the array to add to the <code>hashCode</code>
 581  
      * @return this
 582  
      */
 583  
     public HashCodeBuilder append(char[] array) {
 584  0
         if (array == null) {
 585  0
             iTotal = iTotal * iConstant;
 586  
         } else {
 587  0
             for (int i = 0; i < array.length; i++) {
 588  0
                 append(array[i]);
 589  
             }
 590  
         }
 591  0
         return this;
 592  
     }
 593  
 
 594  
     /**
 595  
      * <p>Append a <code>hashCode</code> for a <code>byte</code> array.</p>
 596  
      *
 597  
      * @param array  the array to add to the <code>hashCode</code>
 598  
      * @return this
 599  
      */
 600  
     public HashCodeBuilder append(byte[] array) {
 601  0
         if (array == null) {
 602  0
             iTotal = iTotal * iConstant;
 603  
         } else {
 604  0
             for (int i = 0; i < array.length; i++) {
 605  0
                 append(array[i]);
 606  
             }
 607  
         }
 608  0
         return this;
 609  
     }
 610  
 
 611  
     /**
 612  
      * <p>Append a <code>hashCode</code> for a <code>double</code> array.</p>
 613  
      *
 614  
      * @param array  the array to add to the <code>hashCode</code>
 615  
      * @return this
 616  
      */
 617  
     public HashCodeBuilder append(double[] array) {
 618  0
         if (array == null) {
 619  0
             iTotal = iTotal * iConstant;
 620  
         } else {
 621  0
             for (int i = 0; i < array.length; i++) {
 622  0
                 append(array[i]);
 623  
             }
 624  
         }
 625  0
         return this;
 626  
     }
 627  
 
 628  
     /**
 629  
      * <p>Append a <code>hashCode</code> for a <code>float</code> array.</p>
 630  
      *
 631  
      * @param array  the array to add to the <code>hashCode</code>
 632  
      * @return this
 633  
      */
 634  
     public HashCodeBuilder append(float[] array) {
 635  0
         if (array == null) {
 636  0
             iTotal = iTotal * iConstant;
 637  
         } else {
 638  0
             for (int i = 0; i < array.length; i++) {
 639  0
                 append(array[i]);
 640  
             }
 641  
         }
 642  0
         return this;
 643  
     }
 644  
 
 645  
     /**
 646  
      * <p>Append a <code>hashCode</code> for a <code>boolean</code> array.</p>
 647  
      *
 648  
      * @param array  the array to add to the <code>hashCode</code>
 649  
      * @return this
 650  
      */
 651  
     public HashCodeBuilder append(boolean[] array) {
 652  0
         if (array == null) {
 653  0
             iTotal = iTotal * iConstant;
 654  
         } else {
 655  0
             for (int i = 0; i < array.length; i++) {
 656  0
                 append(array[i]);
 657  
             }
 658  
         }
 659  0
         return this;
 660  
     }
 661  
 
 662  
     /**
 663  
      * <p>Return the computed <code>hashCode</code>.</p>
 664  
      *
 665  
      * @return <code>hashCode</code> based on the fields appended
 666  
      */
 667  
     public int toHashCode() {
 668  0
         return iTotal;
 669  
     }
 670  
 
 671  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.