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