Coverage report

  %line %branch
net.sf.classifier4J.util.CompareToBuilder
5% 
23% 

 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  
 import java.util.Comparator;
 60  
 
 61  
 /** 
 62  
  * Assists in implementing {@link java.lang.Comparable#compareTo(Object)} methods.
 63  
  *
 64  
  * It is consistent with <code>equals(Object)</code> and
 65  
  * <code>hashcode()</code> built with {@link EqualsBuilder} and
 66  
  * {@link HashCodeBuilder}.</p>
 67  
  *
 68  
  * <p>Two Objects that compare equal using <code>equals(Object)</code> should normally
 69  
  * also compare equal using <code>compareTo(Object)</code>.</p>
 70  
  *
 71  
  * <p>All relevant fields should be included in the calculation of the
 72  
  * comparison. Derived fields may be ignored. The same fields, in the same
 73  
  * order, should be used in both <code>compareTo(Object)</code> and
 74  
  * <code>equals(Object)</code>.</p>
 75  
  *
 76  
  * <p>To use this class write code as follows:</p>
 77  
  *
 78  
  * <pre>
 79  
  * public class MyClass {
 80  
  *   String field1;
 81  
  *   int field2;
 82  
  *   boolean field3;
 83  
  *
 84  
  *   ...
 85  
  *
 86  
  *   public int compareTo(Object o) {
 87  
  *     MyClass myClass = (MyClass) o;
 88  
  *     return new CompareToBuilder()
 89  
  *       .appendSuper(super.compareTo(o)
 90  
  *       .append(this.field1, myClass.field1)
 91  
  *       .append(this.field2, myClass.field2)
 92  
  *       .append(this.field3, myClass.field3)
 93  
  *       .toComparison();
 94  
  *   }
 95  
  * }
 96  
  * </pre>
 97  
  *
 98  
  * <p>Alternatively, there is a method {@link #reflectionCompare reflectionCompare} that uses
 99  
  * reflection to determine the fields to append. Because fields can be private,
 100  
  * <code>reflectionCompare</code> uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to
 101  
  * bypass normal access control checks. This will fail under a security manager,
 102  
  * unless the appropriate permissions are set up correctly. It is also
 103  
  * slower than appending explicitly.</p>
 104  
  *
 105  
  * <p>A typical implementation of <code>compareTo(Object)</code> using
 106  
  * <code>reflectionCompare</code> looks like:</p>
 107  
 
 108  
  * <pre>
 109  
  * public int compareTo(Object o) {
 110  
  *   return CompareToBuilder.reflectionCompare(this, o);
 111  
  * }
 112  
  * </pre>
 113  
  *
 114  
  * @see java.lang.Comparable
 115  
  * @see java.lang.Object#equals(Object)
 116  
  * @see java.lang.Object#hashCode()
 117  
  * @see EqualsBuilder
 118  
  * @see HashCodeBuilder
 119  
  * @author <a href="mailto:steve.downey@netfolio.com">Steve Downey</a>
 120  
  * @author Stephen Colebourne
 121  
  * @author Gary Gregory
 122  
  * @author Pete Gieser
 123  
  * @since 1.0
 124  
  * @version $Id: CompareToBuilder.java,v 1.1 2005/02/04 05:30:28 nicklothian Exp $
 125  
  */
 126  
 public class CompareToBuilder {
 127  
     
 128  
     /**
 129  
      * Current state of the comparison as appended fields are checked.
 130  
      */
 131  
     private int comparison;
 132  
 
 133  
     /**
 134  
      * <p>Constructor for CompareToBuilder.</p>
 135  
      *
 136  
      * <p>Starts off assuming that the objects are equal. Multiple calls are 
 137  
      * then made to the various append methods, followed by a call to 
 138  
      * {@link #toComparison} to get the result.</p>
 139  
      */
 140  
     public CompareToBuilder() {
 141  4
         super();
 142  4
         comparison = 0;
 143  4
     }
 144  
 
 145  
     //-----------------------------------------------------------------------
 146  
     /** 
 147  
      * <p>Compares two <code>Object</code>s via reflection.</p>
 148  
      *
 149  
      * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
 150  
      * is used to bypass normal access control checks. This will fail under a 
 151  
      * security manager unless the appropriate permissions are set.</p>
 152  
      *
 153  
      * <ul>
 154  
      * <li>Static fields will not be compared</li>
 155  
      * <li>Transient members will be not be compared, as they are likely derived
 156  
      *     fields</li>
 157  
      * <li>Superclass fields will be compared</li>
 158  
      * </ul>
 159  
      *
 160  
      * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
 161  
      * they are considered equal.</p>
 162  
      *
 163  
      * @param lhs  left-hand object
 164  
      * @param rhs  right-hand object
 165  
      * @return a negative integer, zero, or a positive integer as <code>lhs</code>
 166  
      *  is less than, equal to, or greater than <code>rhs</code>
 167  
      * @throws NullPointerException  if either (but not both) parameters are
 168  
      *  <code>null</code>
 169  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 170  
      *  with <code>lhs</code>
 171  
      */
 172  
     public static int reflectionCompare(Object lhs, Object rhs) {
 173  0
         return reflectionCompare(lhs, rhs, false, null);
 174  
     }
 175  
 
 176  
     /**
 177  
      * <p>Compares two <code>Object</code>s via reflection.</p>
 178  
      *
 179  
      * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
 180  
      * is used to bypass normal access control checks. This will fail under a 
 181  
      * security manager unless the appropriate permissions are set.</p>
 182  
      *
 183  
      * <ul>
 184  
      * <li>Static fields will not be compared</li>
 185  
      * <li>If <code>compareTransients</code> is <code>true</code>,
 186  
      *     compares transient members.  Otherwise ignores them, as they
 187  
      *     are likely derived fields.</li>
 188  
      * <li>Superclass fields will be compared</li>
 189  
      * </ul>
 190  
      *
 191  
      * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
 192  
      * they are considered equal.</p>
 193  
      *
 194  
      * @param lhs  left-hand object
 195  
      * @param rhs  right-hand object
 196  
      * @param compareTransients  whether to compare transient fields
 197  
      * @return a negative integer, zero, or a positive integer as <code>lhs</code>
 198  
      *  is less than, equal to, or greater than <code>rhs</code>
 199  
      * @throws NullPointerException  if either <code>lhs</code> or <code>rhs</code>
 200  
      *  (but not both) is <code>null</code>
 201  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 202  
      *  with <code>lhs</code>
 203  
      */
 204  
     public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients) {
 205  0
         return reflectionCompare(lhs, rhs, compareTransients, null);
 206  
     }
 207  
 
 208  
     /**
 209  
      * <p>Compares two <code>Object</code>s via reflection.</p>
 210  
      *
 211  
      * <p>Fields can be private, thus <code>AccessibleObject.setAccessible</code>
 212  
      * is used to bypass normal access control checks. This will fail under a 
 213  
      * security manager unless the appropriate permissions are set.</p>
 214  
      *
 215  
      * <ul>
 216  
      * <li>Static fields will not be compared</li>
 217  
      * <li>If the <code>compareTransients</code> is <code>true</code>,
 218  
      *     compares transient members.  Otherwise ignores them, as they
 219  
      *     are likely derived fields.</li>
 220  
      * <li>Compares superclass fields up to and including <code>reflectUpToClass</code>.
 221  
      *     If <code>reflectUpToClass</code> is <code>null</code>, compares all superclass fields.</li>
 222  
      * </ul>
 223  
      *
 224  
      * <p>If both <code>lhs</code> and <code>rhs</code> are <code>null</code>,
 225  
      * they are considered equal.</p>
 226  
      *
 227  
      * @param lhs  left-hand object
 228  
      * @param rhs  right-hand object
 229  
      * @param compareTransients  whether to compare transient fields
 230  
      * @param reflectUpToClass  last superclass for which fields are compared
 231  
      * @return a negative integer, zero, or a positive integer as <code>lhs</code>
 232  
      *  is less than, equal to, or greater than <code>rhs</code>
 233  
      * @throws NullPointerException  if either <code>lhs</code> or <code>rhs</code>
 234  
      *  (but not both) is <code>null</code>
 235  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 236  
      *  with <code>lhs</code>
 237  
      * @since 2.0
 238  
      */
 239  
     public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients, Class reflectUpToClass) {
 240  0
         if (lhs == rhs) {
 241  0
             return 0;
 242  
         }
 243  0
         if (lhs == null || rhs == class="keyword">null) {
 244  0
             throw new NullPointerException();
 245  
         }
 246  0
         Class lhsClazz = lhs.getClass();
 247  0
         if (!lhsClazz.isInstance(rhs)) {
 248  0
             throw new ClassCastException();
 249  
         }
 250  0
         CompareToBuilder compareToBuilder = new CompareToBuilder();
 251  0
         reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
 252  0
         while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
 253  0
             lhsClazz = lhsClazz.getSuperclass();
 254  0
             reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
 255  
         }
 256  0
         return compareToBuilder.toComparison();
 257  
     }
 258  
 
 259  
     /**
 260  
      * <p>Appends to <code>builder</code> the comparison of <code>lhs</code>
 261  
      * to <code>rhs</code> using the fields defined in <code>clazz</code>.</p>
 262  
      * 
 263  
      * @param lhs  left-hand object
 264  
      * @param rhs  right-hand object
 265  
      * @param clazz  <code>Class</code> that defines fields to be compared
 266  
      * @param builder  <code>CompareToBuilder</code> to append to
 267  
      * @param useTransients  whether to compare transient fields
 268  
      */
 269  
     private static void reflectionAppend(
 270  
         Object lhs,
 271  
         Object rhs,
 272  
         Class clazz,
 273  
         CompareToBuilder builder,
 274  
         boolean useTransients) {
 275  
         
 276  0
         Field[] fields = clazz.getDeclaredFields();
 277  0
         AccessibleObject.setAccessible(fields, true);
 278  0
         for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
 279  0
             Field f = fields[i];
 280  0
             if ((f.getName().indexOf('$') == -1)
 281  
                 && (useTransients || !Modifier.isTransient(f.getModifiers()))
 282  
                 && (!Modifier.isStatic(f.getModifiers()))) {
 283  
                 try {
 284  0
                     builder.append(f.get(lhs), f.get(rhs));
 285  0
                 } catch (IllegalAccessException e) {
 286  
                     // This can't happen. Would get a Security exception instead.
 287  
                     // Throw a runtime exception in case the impossible happens.
 288  0
                     throw new InternalError("Unexpected IllegalAccessException");
 289  
                 }
 290  
             }
 291  
         }
 292  0
     }
 293  
 
 294  
     //-----------------------------------------------------------------------
 295  
     /**
 296  
      * <p>Appends to the <code>builder</code> the <code>compareTo(Object)</code>
 297  
      * result of the superclass.</p>
 298  
      *
 299  
      * @param superCompareTo  result of calling <code>super.compareTo(Object)</code>
 300  
      * @return this - used to chain append calls
 301  
      * @since 2.0
 302  
      */
 303  
     public CompareToBuilder appendSuper(int superCompareTo) {
 304  0
         if (comparison != 0) {
 305  0
             return this;
 306  
         }
 307  0
         comparison = superCompareTo;
 308  0
         return this;
 309  
     }
 310  
     
 311  
     //-----------------------------------------------------------------------
 312  
     /**
 313  
      * <p>Appends to the <code>builder</code> the comparison of
 314  
      * two <code>Object</code>s.</p>
 315  
      *
 316  
      * <ol>
 317  
      * <li>Check if <code>lhs == rhs</code></li>
 318  
      * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
 319  
      *     a <code>null</code> object is less than a non-<code>null</code> object</li>
 320  
      * <li>Check the object contents</li>
 321  
      * </ol>
 322  
      * 
 323  
      * <p><code>lhs</code> must either be an array or implement {@link Comparable}.</p>
 324  
      *
 325  
      * @param lhs  left-hand object
 326  
      * @param rhs  right-hand object
 327  
      * @return this - used to chain append calls
 328  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 329  
      *  with <code>lhs</code>
 330  
      */
 331  
     public CompareToBuilder append(Object lhs, Object rhs) {
 332  8
         return append(lhs, rhs, null);
 333  
     }
 334  
 
 335  
     /**
 336  
      * <p>Appends to the <code>builder</code> the comparison of
 337  
      * two <code>Object</code>s.</p>
 338  
      *
 339  
      * <ol>
 340  
      * <li>Check if <code>lhs == rhs</code></li>
 341  
      * <li>Check if either <code>lhs</code> or <code>rhs</code> is <code>null</code>,
 342  
      *     a <code>null</code> object is less than a non-<code>null</code> object</li>
 343  
      * <li>Check the object contents</li>
 344  
      * </ol>
 345  
      *
 346  
      * <p>If <code>lhs</code> is an array, array comparison methods will be used.
 347  
      * Otherwise <code>comparator</code> will be used to compare the objects.
 348  
      * If <code>comparator</code> is <code>null</code>, <code>lhs</code> must
 349  
      * implement {@link Comparable} instead.</p>
 350  
      *
 351  
      * @param lhs  left-hand object
 352  
      * @param rhs  right-hand object
 353  
      * @param comparator  <code>Comparator</code> used to compare the objects,
 354  
      *  <code>null</code> means treat lhs as <code>Comparable</code>
 355  
      * @return this - used to chain append calls
 356  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 357  
      *  with <code>lhs</code>
 358  
      * @since 2.0
 359  
      */
 360  
     public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
 361  8
         if (comparison != 0) {
 362  0
             return this;
 363  
         }
 364  8
         if (lhs == rhs) {
 365  4
             return this;
 366  
         }
 367  4
         if (lhs == null) {
 368  0
             comparison = -1;
 369  0
             return this;
 370  
         }
 371  4
         if (rhs == null) {
 372  0
             comparison = +1;
 373  0
             return this;
 374  
         }
 375  4
         if (lhs.getClass().isArray()) {
 376  
             // switch on type of array, to dispatch to the correct handler
 377  
             // handles multi dimensional arrays
 378  
             // throws a ClassCastException if rhs is not the correct array type
 379  0
             if (lhs instanceof long[]) {
 380  0
                 append((long[]) lhs, (class="keyword">long[]) rhs);
 381  0
             } else if (lhs instanceof int[]) {
 382  0
                 append((int[]) lhs, (class="keyword">int[]) rhs);
 383  0
             } else if (lhs instanceof short[]) {
 384  0
                 append((short[]) lhs, (class="keyword">short[]) rhs);
 385  0
             } else if (lhs instanceof char[]) {
 386  0
                 append((char[]) lhs, (class="keyword">char[]) rhs);
 387  0
             } else if (lhs instanceof byte[]) {
 388  0
                 append((byte[]) lhs, (byte[]) rhs);
 389  0
             } else if (lhs instanceof double[]) {
 390  0
                 append((double[]) lhs, (class="keyword">double[]) rhs);
 391  0
             } else if (lhs instanceof float[]) {
 392  0
                 append((float[]) lhs, (class="keyword">float[]) rhs);
 393  0
             } else if (lhs instanceof boolean[]) {
 394  0
                 append((boolean[]) lhs, (class="keyword">boolean[]) rhs);
 395  
             } else {
 396  
                 // not an array of primitives
 397  
                 // throws a ClassCastException if rhs is not an array
 398  0
                 append((Object[]) lhs, (Object[]) rhs, comparator);
 399  
             }
 400  
         } else {
 401  
             // the simple case, not an array, just test the element
 402  4
             if (comparator == null) {
 403  4
                 comparison = ((Comparable) lhs).compareTo(rhs);
 404  
             } else {
 405  0
                 comparison = comparator.compare(lhs, rhs);
 406  
             }
 407  
         }
 408  4
         return this;
 409  
     }
 410  
 
 411  
     //-------------------------------------------------------------------------
 412  
     /**
 413  
      * Appends to the <code>builder</code> the comparison of
 414  
      * two <code>long</code>s.
 415  
      *
 416  
      * @param lhs  left-hand value
 417  
      * @param rhs  right-hand value
 418  
      * @return this - used to chain append calls
 419  
      */
 420  
     public CompareToBuilder append(long lhs, class="keyword">long rhs) {
 421  0
         if (comparison != 0) {
 422  0
             return this;
 423  
         }
 424  0
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 425  0
         return this;
 426  
     }
 427  
 
 428  
     /**
 429  
      * Appends to the <code>builder</code> the comparison of
 430  
      * two <code>int</code>s.
 431  
      *
 432  
      * @param lhs  left-hand value
 433  
      * @param rhs  right-hand value
 434  
      * @return this - used to chain append calls
 435  
      */
 436  
     public CompareToBuilder append(int lhs, class="keyword">int rhs) {
 437  0
         if (comparison != 0) {
 438  0
             return this;
 439  
         }
 440  0
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 441  0
         return this;
 442  
     }
 443  
 
 444  
     /**
 445  
      * Appends to the <code>builder</code> the comparison of
 446  
      * two <code>short</code>s.
 447  
      * 
 448  
      * @param lhs  left-hand value
 449  
      * @param rhs  right-hand value
 450  
      * @return this - used to chain append calls
 451  
      */
 452  
     public CompareToBuilder append(short lhs, class="keyword">short rhs) {
 453  0
         if (comparison != 0) {
 454  0
             return this;
 455  
         }
 456  0
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 457  0
         return this;
 458  
     }
 459  
 
 460  
     /**
 461  
      * Appends to the <code>builder</code> the comparison of
 462  
      * two <code>char</code>s.
 463  
      *
 464  
      * @param lhs  left-hand value
 465  
      * @param rhs  right-hand value
 466  
      * @return this - used to chain append calls
 467  
      */
 468  
     public CompareToBuilder append(char lhs, class="keyword">char rhs) {
 469  0
         if (comparison != 0) {
 470  0
             return this;
 471  
         }
 472  0
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 473  0
         return this;
 474  
     }
 475  
 
 476  
     /**
 477  
      * Appends to the <code>builder</code> the comparison of
 478  
      * two <code>byte</code>s.
 479  
      * 
 480  
      * @param lhs  left-hand value
 481  
      * @param rhs  right-hand value
 482  
      * @return this - used to chain append calls
 483  
      */
 484  
     public CompareToBuilder append(byte lhs, byte rhs) {
 485  0
         if (comparison != 0) {
 486  0
             return this;
 487  
         }
 488  0
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 489  0
         return this;
 490  
     }
 491  
 
 492  
     /**
 493  
      * <p>Appends to the <code>builder</code> the comparison of
 494  
      * two <code>double</code>s.</p>
 495  
      *
 496  
      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
 497  
      *
 498  
      * <p>It is compatible with the hash code generated by
 499  
      * <code>HashCodeBuilder</code>.</p>
 500  
      *
 501  
      * @param lhs  left-hand value
 502  
      * @param rhs  right-hand value
 503  
      * @return this - used to chain append calls
 504  
      */
 505  
     public CompareToBuilder append(double lhs, class="keyword">double rhs) {
 506  0
         if (comparison != 0) {
 507  0
             return this;
 508  
         }
 509  0
         comparison = compare(lhs, rhs);
 510  0
         return this;
 511  
     }
 512  
 
 513  
     /**
 514  
      * <p>Appends to the <code>builder</code> the comparison of
 515  
      * two <code>float</code>s.</p>
 516  
      *
 517  
      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
 518  
      *
 519  
      * <p>It is compatible with the hash code generated by
 520  
      * <code>HashCodeBuilder</code>.</p>
 521  
      *
 522  
      * @param lhs  left-hand value
 523  
      * @param rhs  right-hand value
 524  
      * @return this - used to chain append calls
 525  
      */
 526  
     public CompareToBuilder append(float lhs, class="keyword">float rhs) {
 527  0
         if (comparison != 0) {
 528  0
             return this;
 529  
         }
 530  0
         comparison = compare(lhs, rhs);
 531  0
         return this;
 532  
     }
 533  
 
 534  
     /**
 535  
      * Appends to the <code>builder</code> the comparison of
 536  
      * two <code>booleans</code>s.
 537  
      *
 538  
      * @param lhs  left-hand value
 539  
      * @param rhs  right-hand value
 540  
      * @return this - used to chain append calls
 541  
       */
 542  
     public CompareToBuilder append(boolean lhs, class="keyword">boolean rhs) {
 543  0
         if (comparison != 0) {
 544  0
             return this;
 545  
         }
 546  0
         if (lhs == rhs) {
 547  0
             return this;
 548  
         }
 549  0
         if (lhs == false) {
 550  0
             comparison = -1;
 551  
         } else {
 552  0
             comparison = +1;
 553  
         }
 554  0
         return this;
 555  
     }
 556  
 
 557  
     //-----------------------------------------------------------------------
 558  
     /**
 559  
      * <p>Appends to the <code>builder</code> the deep comparison of
 560  
      * two <code>Object</code> arrays.</p>
 561  
      *
 562  
      * <ol>
 563  
      *  <li>Check if arrays are the same using <code>==</code></li>
 564  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 565  
      *  <li>Check array length, a short length array is less than a long length array</li>
 566  
      *  <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
 567  
      * </ol>
 568  
      *
 569  
      * <p>This method will also will be called for the top level of multi-dimensional,
 570  
      * ragged, and multi-typed arrays.</p>
 571  
      *
 572  
      * @param lhs  left-hand array
 573  
      * @param rhs  right-hand array
 574  
      * @return this - used to chain append calls
 575  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 576  
      *  with <code>lhs</code>
 577  
      */
 578  
     public CompareToBuilder append(Object[] lhs, Object[] rhs) {
 579  0
         return append(lhs, rhs, null);
 580  
     }
 581  
     
 582  
     /**
 583  
      * <p>Appends to the <code>builder</code> the deep comparison of
 584  
      * two <code>Object</code> arrays.</p>
 585  
      *
 586  
      * <ol>
 587  
      *  <li>Check if arrays are the same using <code>==</code></li>
 588  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 589  
      *  <li>Check array length, a short length array is less than a long length array</li>
 590  
      *  <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
 591  
      * </ol>
 592  
      *
 593  
      * <p>This method will also will be called for the top level of multi-dimensional,
 594  
      * ragged, and multi-typed arrays.</p>
 595  
      *
 596  
      * @param lhs  left-hand array
 597  
      * @param rhs  right-hand array
 598  
      * @param comparator  <code>Comparator</code> to use to compare the array elements,
 599  
      *  <code>null</code> means to treat <code>lhs</code> elements as <code>Comparable</code>.
 600  
      * @return this - used to chain append calls
 601  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 602  
      *  with <code>lhs</code>
 603  
      * @since 2.0
 604  
      */
 605  
     public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator comparator) {
 606  0
         if (comparison != 0) {
 607  0
             return this;
 608  
         }
 609  0
         if (lhs == rhs) {
 610  0
             return this;
 611  
         }
 612  0
         if (lhs == null) {
 613  0
             comparison = -1;
 614  0
             return this;
 615  
         }
 616  0
         if (rhs == null) {
 617  0
             comparison = +1;
 618  0
             return this;
 619  
         }
 620  0
         if (lhs.length != rhs.length) {
 621  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 622  0
             return this;
 623  
         }
 624  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 625  0
             append(lhs[i], rhs[i], comparator);
 626  
         }
 627  0
         return this;
 628  
     }
 629  
 
 630  
     /**
 631  
      * <p>Appends to the <code>builder</code> the deep comparison of
 632  
      * two <code>long</code> arrays.</p>
 633  
      *
 634  
      * <ol>
 635  
      *  <li>Check if arrays are the same using <code>==</code></li>
 636  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 637  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 638  
      *  <li>Check array contents element by element using {@link #append(long, long)}</li>
 639  
      * </ol>
 640  
      *
 641  
      * @param lhs  left-hand array
 642  
      * @param rhs  right-hand array
 643  
      * @return this - used to chain append calls
 644  
      */
 645  
     public CompareToBuilder append(long[] lhs, class="keyword">long[] rhs) {
 646  0
         if (comparison != 0) {
 647  0
             return this;
 648  
         }
 649  0
         if (lhs == rhs) {
 650  0
             return this;
 651  
         }
 652  0
         if (lhs == null) {
 653  0
             comparison = -1;
 654  0
             return this;
 655  
         }
 656  0
         if (rhs == null) {
 657  0
             comparison = +1;
 658  0
             return this;
 659  
         }
 660  0
         if (lhs.length != rhs.length) {
 661  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 662  0
             return this;
 663  
         }
 664  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 665  0
             append(lhs[i], rhs[i]);
 666  
         }
 667  0
         return this;
 668  
     }
 669  
 
 670  
     /**
 671  
      * <p>Appends to the <code>builder</code> the deep comparison of
 672  
      * two <code>int</code> arrays.</p>
 673  
      *
 674  
      * <ol>
 675  
      *  <li>Check if arrays are the same using <code>==</code></li>
 676  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 677  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 678  
      *  <li>Check array contents element by element using {@link #append(int, int)}</li>
 679  
      * </ol>
 680  
      *
 681  
      * @param lhs  left-hand array
 682  
      * @param rhs  right-hand array
 683  
      * @return this - used to chain append calls
 684  
      */
 685  
     public CompareToBuilder append(int[] lhs, class="keyword">int[] rhs) {
 686  0
         if (comparison != 0) {
 687  0
             return this;
 688  
         }
 689  0
         if (lhs == rhs) {
 690  0
             return this;
 691  
         }
 692  0
         if (lhs == null) {
 693  0
             comparison = -1;
 694  0
             return this;
 695  
         }
 696  0
         if (rhs == null) {
 697  0
             comparison = +1;
 698  0
             return this;
 699  
         }
 700  0
         if (lhs.length != rhs.length) {
 701  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 702  0
             return this;
 703  
         }
 704  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 705  0
             append(lhs[i], rhs[i]);
 706  
         }
 707  0
         return this;
 708  
     }
 709  
 
 710  
     /**
 711  
      * <p>Appends to the <code>builder</code> the deep comparison of
 712  
      * two <code>short</code> arrays.</p>
 713  
      *
 714  
      * <ol>
 715  
      *  <li>Check if arrays are the same using <code>==</code></li>
 716  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 717  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 718  
      *  <li>Check array contents element by element using {@link #append(short, short)}</li>
 719  
      * </ol>
 720  
      *
 721  
      * @param lhs  left-hand array
 722  
      * @param rhs  right-hand array
 723  
      * @return this - used to chain append calls
 724  
      */
 725  
     public CompareToBuilder append(short[] lhs, class="keyword">short[] rhs) {
 726  0
         if (comparison != 0) {
 727  0
             return this;
 728  
         }
 729  0
         if (lhs == rhs) {
 730  0
             return this;
 731  
         }
 732  0
         if (lhs == null) {
 733  0
             comparison = -1;
 734  0
             return this;
 735  
         }
 736  0
         if (rhs == null) {
 737  0
             comparison = +1;
 738  0
             return this;
 739  
         }
 740  0
         if (lhs.length != rhs.length) {
 741  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 742  0
             return this;
 743  
         }
 744  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 745  0
             append(lhs[i], rhs[i]);
 746  
         }
 747  0
         return this;
 748  
     }
 749  
 
 750  
     /**
 751  
      * <p>Appends to the <code>builder</code> the deep comparison of
 752  
      * two <code>char</code> arrays.</p>
 753  
      *
 754  
      * <ol>
 755  
      *  <li>Check if arrays are the same using <code>==</code></li>
 756  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 757  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 758  
      *  <li>Check array contents element by element using {@link #append(char, char)}</li>
 759  
      * </ol>
 760  
      *
 761  
      * @param lhs  left-hand array
 762  
      * @param rhs  right-hand array
 763  
      * @return this - used to chain append calls
 764  
      */
 765  
     public CompareToBuilder append(char[] lhs, class="keyword">char[] rhs) {
 766  0
         if (comparison != 0) {
 767  0
             return this;
 768  
         }
 769  0
         if (lhs == rhs) {
 770  0
             return this;
 771  
         }
 772  0
         if (lhs == null) {
 773  0
             comparison = -1;
 774  0
             return this;
 775  
         }
 776  0
         if (rhs == null) {
 777  0
             comparison = +1;
 778  0
             return this;
 779  
         }
 780  0
         if (lhs.length != rhs.length) {
 781  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 782  0
             return this;
 783  
         }
 784  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 785  0
             append(lhs[i], rhs[i]);
 786  
         }
 787  0
         return this;
 788  
     }
 789  
 
 790  
     /**
 791  
      * <p>Appends to the <code>builder</code> the deep comparison of
 792  
      * two <code>byte</code> arrays.</p>
 793  
      *
 794  
      * <ol>
 795  
      *  <li>Check if arrays are the same using <code>==</code></li>
 796  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 797  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 798  
      *  <li>Check array contents element by element using {@link #append(byte, byte)}</li>
 799  
      * </ol>
 800  
      *
 801  
      * @param lhs  left-hand array
 802  
      * @param rhs  right-hand array
 803  
      * @return this - used to chain append calls
 804  
      */
 805  
     public CompareToBuilder append(byte[] lhs, byte[] rhs) {
 806  0
         if (comparison != 0) {
 807  0
             return this;
 808  
         }
 809  0
         if (lhs == rhs) {
 810  0
             return this;
 811  
         }
 812  0
         if (lhs == null) {
 813  0
             comparison = -1;
 814  0
             return this;
 815  
         }
 816  0
         if (rhs == null) {
 817  0
             comparison = +1;
 818  0
             return this;
 819  
         }
 820  0
         if (lhs.length != rhs.length) {
 821  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 822  0
             return this;
 823  
         }
 824  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 825  0
             append(lhs[i], rhs[i]);
 826  
         }
 827  0
         return this;
 828  
     }
 829  
 
 830  
     /**
 831  
      * <p>Appends to the <code>builder</code> the deep comparison of
 832  
      * two <code>double</code> arrays.</p>
 833  
      *
 834  
      * <ol>
 835  
      *  <li>Check if arrays are the same using <code>==</code></li>
 836  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 837  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 838  
      *  <li>Check array contents element by element using {@link #append(double, double)}</li>
 839  
      * </ol>
 840  
      *
 841  
      * @param lhs  left-hand array
 842  
      * @param rhs  right-hand array
 843  
      * @return this - used to chain append calls
 844  
      */
 845  
     public CompareToBuilder append(double[] lhs, class="keyword">double[] rhs) {
 846  0
         if (comparison != 0) {
 847  0
             return this;
 848  
         }
 849  0
         if (lhs == rhs) {
 850  0
             return this;
 851  
         }
 852  0
         if (lhs == null) {
 853  0
             comparison = -1;
 854  0
             return this;
 855  
         }
 856  0
         if (rhs == null) {
 857  0
             comparison = +1;
 858  0
             return this;
 859  
         }
 860  0
         if (lhs.length != rhs.length) {
 861  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 862  0
             return this;
 863  
         }
 864  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 865  0
             append(lhs[i], rhs[i]);
 866  
         }
 867  0
         return this;
 868  
     }
 869  
 
 870  
     /**
 871  
      * <p>Appends to the <code>builder</code> the deep comparison of
 872  
      * two <code>float</code> arrays.</p>
 873  
      *
 874  
      * <ol>
 875  
      *  <li>Check if arrays are the same using <code>==</code></li>
 876  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 877  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 878  
      *  <li>Check array contents element by element using {@link #append(float, float)}</li>
 879  
      * </ol>
 880  
      *
 881  
      * @param lhs  left-hand array
 882  
      * @param rhs  right-hand array
 883  
      * @return this - used to chain append calls
 884  
      */
 885  
     public CompareToBuilder append(float[] lhs, class="keyword">float[] rhs) {
 886  0
         if (comparison != 0) {
 887  0
             return this;
 888  
         }
 889  0
         if (lhs == rhs) {
 890  0
             return this;
 891  
         }
 892  0
         if (lhs == null) {
 893  0
             comparison = -1;
 894  0
             return this;
 895  
         }
 896  0
         if (rhs == null) {
 897  0
             comparison = +1;
 898  0
             return this;
 899  
         }
 900  0
         if (lhs.length != rhs.length) {
 901  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 902  0
             return this;
 903  
         }
 904  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 905  0
             append(lhs[i], rhs[i]);
 906  
         }
 907  0
         return this;
 908  
     }
 909  
 
 910  
     /**
 911  
      * <p>Appends to the <code>builder</code> the deep comparison of
 912  
      * two <code>boolean</code> arrays.</p>
 913  
      *
 914  
      * <ol>
 915  
      *  <li>Check if arrays are the same using <code>==</code></li>
 916  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 917  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 918  
      *  <li>Check array contents element by element using {@link #append(boolean, boolean)}</li>
 919  
      * </ol>
 920  
      *
 921  
      * @param lhs  left-hand array
 922  
      * @param rhs  right-hand array
 923  
      * @return this - used to chain append calls
 924  
      */
 925  
     public CompareToBuilder append(boolean[] lhs, class="keyword">boolean[] rhs) {
 926  0
         if (comparison != 0) {
 927  0
             return this;
 928  
         }
 929  0
         if (lhs == rhs) {
 930  0
             return this;
 931  
         }
 932  0
         if (lhs == null) {
 933  0
             comparison = -1;
 934  0
             return this;
 935  
         }
 936  0
         if (rhs == null) {
 937  0
             comparison = +1;
 938  0
             return this;
 939  
         }
 940  0
         if (lhs.length != rhs.length) {
 941  0
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 942  0
             return this;
 943  
         }
 944  0
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 945  0
             append(lhs[i], rhs[i]);
 946  
         }
 947  0
         return this;
 948  
     }
 949  
 
 950  
     //-----------------------------------------------------------------------
 951  
     /**
 952  
      * Returns a negative integer, a positive integer, or zero as
 953  
      * the <code>builder</code> has judged the "left-hand" side
 954  
      * as less than, greater than, or equal to the "right-hand"
 955  
      * side.
 956  
      * 
 957  
      * @return final comparison result
 958  
      */
 959  
     public int toComparison() {
 960  4
         return comparison;
 961  
     }
 962  
 
 963  
 
 964  
     public static int compare(double lhs, class="keyword">double rhs) {
 965  0
         if (lhs < rhs) {
 966  0
             return -1;
 967  
         }
 968  0
         if (lhs > rhs) {
 969  0
             return +1;
 970  
         }
 971  
         // Need to compare bits to handle 0.0 == -0.0 being true
 972  
         // compare should put -0.0 < +0.0
 973  
         // Two NaNs are also == for compare purposes
 974  
         // where NaN == NaN is false
 975  0
         long lhsBits = Double.doubleToLongBits(lhs);
 976  0
         long rhsBits = Double.doubleToLongBits(rhs);
 977  0
         if (lhsBits == rhsBits) {
 978  0
             return 0;
 979  
         }
 980  
         // Something exotic! A comparison to NaN or 0.0 vs -0.0
 981  
         // Fortunately NaN's long is > than everything else
 982  
         // Also negzeros bits < poszero
 983  
         // NAN: 9221120237041090560
 984  
         // MAX: 9218868437227405311
 985  
         // NEGZERO: -9223372036854775808
 986  0
         if (lhsBits < rhsBits) {
 987  0
             return -1;
 988  
         } else {
 989  0
             return +1;
 990  
         }
 991  
     }
 992  
 
 993  
 
 994  
 }

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