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