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