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  
  */
 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  
             // switch on type of array, to dispatch to the correct handler
 422  
             // handles multi dimensional arrays
 423  
             // throws a ClassCastException if rhs is not the correct array type
 424  138
             if (lhs instanceof long[]) {
 425  27
                 append((long[]) lhs, (long[]) rhs);
 426  111
             } else if (lhs instanceof int[]) {
 427  13
                 append((int[]) lhs, (int[]) rhs);
 428  98
             } else if (lhs instanceof short[]) {
 429  13
                 append((short[]) lhs, (short[]) rhs);
 430  85
             } else if (lhs instanceof char[]) {
 431  28
                 append((char[]) lhs, (char[]) rhs);
 432  57
             } else if (lhs instanceof byte[]) {
 433  13
                 append((byte[]) lhs, (byte[]) rhs);
 434  44
             } else if (lhs instanceof double[]) {
 435  13
                 append((double[]) lhs, (double[]) rhs);
 436  31
             } else if (lhs instanceof float[]) {
 437  13
                 append((float[]) lhs, (float[]) rhs);
 438  18
             } else if (lhs instanceof boolean[]) {
 439  13
                 append((boolean[]) lhs, (boolean[]) rhs);
 440  
             } else {
 441  
                 // not an array of primitives
 442  
                 // throws a ClassCastException if rhs is not an array
 443  5
                 append((Object[]) lhs, (Object[]) rhs, comparator);
 444  
             }
 445  
         } else {
 446  
             // the simple case, not an array, just test the element
 447  141
             if (comparator == null) {
 448  
                 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc
 449  137
                 final Comparable<Object> comparable = (Comparable<Object>) lhs;
 450  137
                 comparison = comparable.compareTo(rhs);
 451  136
             } else {
 452  
                 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc
 453  4
                 final Comparator<Object> comparator2 = (Comparator<Object>) comparator;
 454  4
                 comparison = comparator2.compare(lhs, rhs);
 455  
             }
 456  
         }
 457  278
         return this;
 458  
     }
 459  
 
 460  
     //-------------------------------------------------------------------------
 461  
     /**
 462  
      * Appends to the <code>builder</code> the comparison of
 463  
      * two <code>long</code>s.
 464  
      *
 465  
      * @param lhs  left-hand value
 466  
      * @param rhs  right-hand value
 467  
      * @return this - used to chain append calls
 468  
      */
 469  
     public CompareToBuilder append(final long lhs, final long rhs) {
 470  55
         if (comparison != 0) {
 471  0
             return this;
 472  
         }
 473  55
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 474  55
         return this;
 475  
     }
 476  
 
 477  
     /**
 478  
      * Appends to the <code>builder</code> the comparison of
 479  
      * two <code>int</code>s.
 480  
      *
 481  
      * @param lhs  left-hand value
 482  
      * @param rhs  right-hand value
 483  
      * @return this - used to chain append calls
 484  
      */
 485  
     public CompareToBuilder append(final int lhs, final int rhs) {
 486  31
         if (comparison != 0) {
 487  0
             return this;
 488  
         }
 489  31
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 490  31
         return this;
 491  
     }
 492  
 
 493  
     /**
 494  
      * Appends to the <code>builder</code> the comparison of
 495  
      * two <code>short</code>s.
 496  
      * 
 497  
      * @param lhs  left-hand value
 498  
      * @param rhs  right-hand value
 499  
      * @return this - used to chain append calls
 500  
      */
 501  
     public CompareToBuilder append(final short lhs, final short rhs) {
 502  31
         if (comparison != 0) {
 503  0
             return this;
 504  
         }
 505  31
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 506  31
         return this;
 507  
     }
 508  
 
 509  
     /**
 510  
      * Appends to the <code>builder</code> the comparison of
 511  
      * two <code>char</code>s.
 512  
      *
 513  
      * @param lhs  left-hand value
 514  
      * @param rhs  right-hand value
 515  
      * @return this - used to chain append calls
 516  
      */
 517  
     public CompareToBuilder append(final char lhs, final char rhs) {
 518  46
         if (comparison != 0) {
 519  0
             return this;
 520  
         }
 521  46
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 522  46
         return this;
 523  
     }
 524  
 
 525  
     /**
 526  
      * Appends to the <code>builder</code> the comparison of
 527  
      * two <code>byte</code>s.
 528  
      * 
 529  
      * @param lhs  left-hand value
 530  
      * @param rhs  right-hand value
 531  
      * @return this - used to chain append calls
 532  
      */
 533  
     public CompareToBuilder append(final byte lhs, final byte rhs) {
 534  31
         if (comparison != 0) {
 535  0
             return this;
 536  
         }
 537  31
         comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
 538  31
         return this;
 539  
     }
 540  
 
 541  
     /**
 542  
      * <p>Appends to the <code>builder</code> the comparison of
 543  
      * two <code>double</code>s.</p>
 544  
      *
 545  
      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
 546  
      *
 547  
      * <p>It is compatible with the hash code generated by
 548  
      * <code>HashCodeBuilder</code>.</p>
 549  
      *
 550  
      * @param lhs  left-hand value
 551  
      * @param rhs  right-hand value
 552  
      * @return this - used to chain append calls
 553  
      */
 554  
     public CompareToBuilder append(final double lhs, final double rhs) {
 555  41
         if (comparison != 0) {
 556  0
             return this;
 557  
         }
 558  41
         comparison = Double.compare(lhs, rhs);
 559  41
         return this;
 560  
     }
 561  
 
 562  
     /**
 563  
      * <p>Appends to the <code>builder</code> the comparison of
 564  
      * two <code>float</code>s.</p>
 565  
      *
 566  
      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
 567  
      *
 568  
      * <p>It is compatible with the hash code generated by
 569  
      * <code>HashCodeBuilder</code>.</p>
 570  
      *
 571  
      * @param lhs  left-hand value
 572  
      * @param rhs  right-hand value
 573  
      * @return this - used to chain append calls
 574  
      */
 575  
     public CompareToBuilder append(final float lhs, final float rhs) {
 576  37
         if (comparison != 0) {
 577  0
             return this;
 578  
         }
 579  37
         comparison = Float.compare(lhs, rhs);
 580  37
         return this;
 581  
     }
 582  
 
 583  
     /**
 584  
      * Appends to the <code>builder</code> the comparison of
 585  
      * two <code>booleans</code>s.
 586  
      *
 587  
      * @param lhs  left-hand value
 588  
      * @param rhs  right-hand value
 589  
      * @return this - used to chain append calls
 590  
       */
 591  
     public CompareToBuilder append(final boolean lhs, final boolean rhs) {
 592  28
         if (comparison != 0) {
 593  0
             return this;
 594  
         }
 595  28
         if (lhs == rhs) {
 596  20
             return this;
 597  
         }
 598  8
         if (lhs == false) {
 599  4
             comparison = -1;
 600  
         } else {
 601  4
             comparison = +1;
 602  
         }
 603  8
         return this;
 604  
     }
 605  
 
 606  
     //-----------------------------------------------------------------------
 607  
     /**
 608  
      * <p>Appends to the <code>builder</code> the deep comparison of
 609  
      * two <code>Object</code> arrays.</p>
 610  
      *
 611  
      * <ol>
 612  
      *  <li>Check if arrays are the same using <code>==</code></li>
 613  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 614  
      *  <li>Check array length, a short length array is less than a long length array</li>
 615  
      *  <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
 616  
      * </ol>
 617  
      *
 618  
      * <p>This method will also will be called for the top level of multi-dimensional,
 619  
      * ragged, and multi-typed arrays.</p>
 620  
      *
 621  
      * @param lhs  left-hand array
 622  
      * @param rhs  right-hand array
 623  
      * @return this - used to chain append calls
 624  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 625  
      *  with <code>lhs</code>
 626  
      */
 627  
     public CompareToBuilder append(final Object[] lhs, final Object[] rhs) {
 628  69
         return append(lhs, rhs, null);
 629  
     }
 630  
     
 631  
     /**
 632  
      * <p>Appends to the <code>builder</code> the deep comparison of
 633  
      * two <code>Object</code> arrays.</p>
 634  
      *
 635  
      * <ol>
 636  
      *  <li>Check if arrays are the same using <code>==</code></li>
 637  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 638  
      *  <li>Check array length, a short length array is less than a long length array</li>
 639  
      *  <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li>
 640  
      * </ol>
 641  
      *
 642  
      * <p>This method will also will be called for the top level of multi-dimensional,
 643  
      * ragged, and multi-typed arrays.</p>
 644  
      *
 645  
      * @param lhs  left-hand array
 646  
      * @param rhs  right-hand array
 647  
      * @param comparator  <code>Comparator</code> to use to compare the array elements,
 648  
      *  <code>null</code> means to treat <code>lhs</code> elements as <code>Comparable</code>.
 649  
      * @return this - used to chain append calls
 650  
      * @throws ClassCastException  if <code>rhs</code> is not assignment-compatible
 651  
      *  with <code>lhs</code>
 652  
      * @since 2.0
 653  
      */
 654  
     public CompareToBuilder append(final Object[] lhs, final Object[] rhs, final Comparator<?> comparator) {
 655  74
         if (comparison != 0) {
 656  0
             return this;
 657  
         }
 658  74
         if (lhs == rhs) {
 659  12
             return this;
 660  
         }
 661  62
         if (lhs == null) {
 662  1
             comparison = -1;
 663  1
             return this;
 664  
         }
 665  61
         if (rhs == null) {
 666  1
             comparison = +1;
 667  1
             return this;
 668  
         }
 669  60
         if (lhs.length != rhs.length) {
 670  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 671  6
             return this;
 672  
         }
 673  144
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 674  90
             append(lhs[i], rhs[i], comparator);
 675  
         }
 676  54
         return this;
 677  
     }
 678  
 
 679  
     /**
 680  
      * <p>Appends to the <code>builder</code> the deep comparison of
 681  
      * two <code>long</code> arrays.</p>
 682  
      *
 683  
      * <ol>
 684  
      *  <li>Check if arrays are the same using <code>==</code></li>
 685  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 686  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 687  
      *  <li>Check array contents element by element using {@link #append(long, long)}</li>
 688  
      * </ol>
 689  
      *
 690  
      * @param lhs  left-hand array
 691  
      * @param rhs  right-hand array
 692  
      * @return this - used to chain append calls
 693  
      */
 694  
     public CompareToBuilder append(final long[] lhs, final long[] rhs) {
 695  36
         if (comparison != 0) {
 696  0
             return this;
 697  
         }
 698  36
         if (lhs == rhs) {
 699  2
             return this;
 700  
         }
 701  34
         if (lhs == null) {
 702  1
             comparison = -1;
 703  1
             return this;
 704  
         }
 705  33
         if (rhs == null) {
 706  1
             comparison = +1;
 707  1
             return this;
 708  
         }
 709  32
         if (lhs.length != rhs.length) {
 710  8
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 711  8
             return this;
 712  
         }
 713  72
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 714  48
             append(lhs[i], rhs[i]);
 715  
         }
 716  24
         return this;
 717  
     }
 718  
 
 719  
     /**
 720  
      * <p>Appends to the <code>builder</code> the deep comparison of
 721  
      * two <code>int</code> arrays.</p>
 722  
      *
 723  
      * <ol>
 724  
      *  <li>Check if arrays are the same using <code>==</code></li>
 725  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 726  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 727  
      *  <li>Check array contents element by element using {@link #append(int, int)}</li>
 728  
      * </ol>
 729  
      *
 730  
      * @param lhs  left-hand array
 731  
      * @param rhs  right-hand array
 732  
      * @return this - used to chain append calls
 733  
      */
 734  
     public CompareToBuilder append(final int[] lhs, final int[] rhs) {
 735  22
         if (comparison != 0) {
 736  0
             return this;
 737  
         }
 738  22
         if (lhs == rhs) {
 739  2
             return this;
 740  
         }
 741  20
         if (lhs == null) {
 742  1
             comparison = -1;
 743  1
             return this;
 744  
         }
 745  19
         if (rhs == null) {
 746  1
             comparison = +1;
 747  1
             return this;
 748  
         }
 749  18
         if (lhs.length != rhs.length) {
 750  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 751  6
             return this;
 752  
         }
 753  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 754  24
             append(lhs[i], rhs[i]);
 755  
         }
 756  12
         return this;
 757  
     }
 758  
 
 759  
     /**
 760  
      * <p>Appends to the <code>builder</code> the deep comparison of
 761  
      * two <code>short</code> arrays.</p>
 762  
      *
 763  
      * <ol>
 764  
      *  <li>Check if arrays are the same using <code>==</code></li>
 765  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 766  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 767  
      *  <li>Check array contents element by element using {@link #append(short, short)}</li>
 768  
      * </ol>
 769  
      *
 770  
      * @param lhs  left-hand array
 771  
      * @param rhs  right-hand array
 772  
      * @return this - used to chain append calls
 773  
      */
 774  
     public CompareToBuilder append(final short[] lhs, final short[] rhs) {
 775  22
         if (comparison != 0) {
 776  0
             return this;
 777  
         }
 778  22
         if (lhs == rhs) {
 779  2
             return this;
 780  
         }
 781  20
         if (lhs == null) {
 782  1
             comparison = -1;
 783  1
             return this;
 784  
         }
 785  19
         if (rhs == null) {
 786  1
             comparison = +1;
 787  1
             return this;
 788  
         }
 789  18
         if (lhs.length != rhs.length) {
 790  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 791  6
             return this;
 792  
         }
 793  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 794  24
             append(lhs[i], rhs[i]);
 795  
         }
 796  12
         return this;
 797  
     }
 798  
 
 799  
     /**
 800  
      * <p>Appends to the <code>builder</code> the deep comparison of
 801  
      * two <code>char</code> arrays.</p>
 802  
      *
 803  
      * <ol>
 804  
      *  <li>Check if arrays are the same using <code>==</code></li>
 805  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 806  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 807  
      *  <li>Check array contents element by element using {@link #append(char, char)}</li>
 808  
      * </ol>
 809  
      *
 810  
      * @param lhs  left-hand array
 811  
      * @param rhs  right-hand array
 812  
      * @return this - used to chain append calls
 813  
      */
 814  
     public CompareToBuilder append(final char[] lhs, final char[] rhs) {
 815  37
         if (comparison != 0) {
 816  0
             return this;
 817  
         }
 818  37
         if (lhs == rhs) {
 819  2
             return this;
 820  
         }
 821  35
         if (lhs == null) {
 822  1
             comparison = -1;
 823  1
             return this;
 824  
         }
 825  34
         if (rhs == null) {
 826  1
             comparison = +1;
 827  1
             return this;
 828  
         }
 829  33
         if (lhs.length != rhs.length) {
 830  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 831  6
             return this;
 832  
         }
 833  66
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 834  39
             append(lhs[i], rhs[i]);
 835  
         }
 836  27
         return this;
 837  
     }
 838  
 
 839  
     /**
 840  
      * <p>Appends to the <code>builder</code> the deep comparison of
 841  
      * two <code>byte</code> arrays.</p>
 842  
      *
 843  
      * <ol>
 844  
      *  <li>Check if arrays are the same using <code>==</code></li>
 845  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 846  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 847  
      *  <li>Check array contents element by element using {@link #append(byte, byte)}</li>
 848  
      * </ol>
 849  
      *
 850  
      * @param lhs  left-hand array
 851  
      * @param rhs  right-hand array
 852  
      * @return this - used to chain append calls
 853  
      */
 854  
     public CompareToBuilder append(final byte[] lhs, final byte[] rhs) {
 855  22
         if (comparison != 0) {
 856  0
             return this;
 857  
         }
 858  22
         if (lhs == rhs) {
 859  2
             return this;
 860  
         }
 861  20
         if (lhs == null) {
 862  1
             comparison = -1;
 863  1
             return this;
 864  
         }
 865  19
         if (rhs == null) {
 866  1
             comparison = +1;
 867  1
             return this;
 868  
         }
 869  18
         if (lhs.length != rhs.length) {
 870  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 871  6
             return this;
 872  
         }
 873  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 874  24
             append(lhs[i], rhs[i]);
 875  
         }
 876  12
         return this;
 877  
     }
 878  
 
 879  
     /**
 880  
      * <p>Appends to the <code>builder</code> the deep comparison of
 881  
      * two <code>double</code> arrays.</p>
 882  
      *
 883  
      * <ol>
 884  
      *  <li>Check if arrays are the same using <code>==</code></li>
 885  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 886  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 887  
      *  <li>Check array contents element by element using {@link #append(double, double)}</li>
 888  
      * </ol>
 889  
      *
 890  
      * @param lhs  left-hand array
 891  
      * @param rhs  right-hand array
 892  
      * @return this - used to chain append calls
 893  
      */
 894  
     public CompareToBuilder append(final double[] lhs, final double[] rhs) {
 895  22
         if (comparison != 0) {
 896  0
             return this;
 897  
         }
 898  22
         if (lhs == rhs) {
 899  2
             return this;
 900  
         }
 901  20
         if (lhs == null) {
 902  1
             comparison = -1;
 903  1
             return this;
 904  
         }
 905  19
         if (rhs == null) {
 906  1
             comparison = +1;
 907  1
             return this;
 908  
         }
 909  18
         if (lhs.length != rhs.length) {
 910  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 911  6
             return this;
 912  
         }
 913  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 914  24
             append(lhs[i], rhs[i]);
 915  
         }
 916  12
         return this;
 917  
     }
 918  
 
 919  
     /**
 920  
      * <p>Appends to the <code>builder</code> the deep comparison of
 921  
      * two <code>float</code> arrays.</p>
 922  
      *
 923  
      * <ol>
 924  
      *  <li>Check if arrays are the same using <code>==</code></li>
 925  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 926  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 927  
      *  <li>Check array contents element by element using {@link #append(float, float)}</li>
 928  
      * </ol>
 929  
      *
 930  
      * @param lhs  left-hand array
 931  
      * @param rhs  right-hand array
 932  
      * @return this - used to chain append calls
 933  
      */
 934  
     public CompareToBuilder append(final float[] lhs, final float[] rhs) {
 935  22
         if (comparison != 0) {
 936  0
             return this;
 937  
         }
 938  22
         if (lhs == rhs) {
 939  2
             return this;
 940  
         }
 941  20
         if (lhs == null) {
 942  1
             comparison = -1;
 943  1
             return this;
 944  
         }
 945  19
         if (rhs == null) {
 946  1
             comparison = +1;
 947  1
             return this;
 948  
         }
 949  18
         if (lhs.length != rhs.length) {
 950  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 951  6
             return this;
 952  
         }
 953  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 954  24
             append(lhs[i], rhs[i]);
 955  
         }
 956  12
         return this;
 957  
     }
 958  
 
 959  
     /**
 960  
      * <p>Appends to the <code>builder</code> the deep comparison of
 961  
      * two <code>boolean</code> arrays.</p>
 962  
      *
 963  
      * <ol>
 964  
      *  <li>Check if arrays are the same using <code>==</code></li>
 965  
      *  <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li>
 966  
      *  <li>Check array length, a shorter length array is less than a longer length array</li>
 967  
      *  <li>Check array contents element by element using {@link #append(boolean, boolean)}</li>
 968  
      * </ol>
 969  
      *
 970  
      * @param lhs  left-hand array
 971  
      * @param rhs  right-hand array
 972  
      * @return this - used to chain append calls
 973  
      */
 974  
     public CompareToBuilder append(final boolean[] lhs, final boolean[] rhs) {
 975  22
         if (comparison != 0) {
 976  0
             return this;
 977  
         }
 978  22
         if (lhs == rhs) {
 979  2
             return this;
 980  
         }
 981  20
         if (lhs == null) {
 982  1
             comparison = -1;
 983  1
             return this;
 984  
         }
 985  19
         if (rhs == null) {
 986  1
             comparison = +1;
 987  1
             return this;
 988  
         }
 989  18
         if (lhs.length != rhs.length) {
 990  6
             comparison = (lhs.length < rhs.length) ? -1 : +1;
 991  6
             return this;
 992  
         }
 993  36
         for (int i = 0; i < lhs.length && comparison == 0; i++) {
 994  24
             append(lhs[i], rhs[i]);
 995  
         }
 996  12
         return this;
 997  
     }
 998  
 
 999  
     //-----------------------------------------------------------------------
 1000  
     /**
 1001  
      * Returns a negative integer, a positive integer, or zero as
 1002  
      * the <code>builder</code> has judged the "left-hand" side
 1003  
      * as less than, greater than, or equal to the "right-hand"
 1004  
      * side.
 1005  
      * 
 1006  
      * @return final comparison result
 1007  
      * @see #build()
 1008  
      */
 1009  
     public int toComparison() {
 1010  439
         return comparison;
 1011  
     }
 1012  
 
 1013  
     /**
 1014  
      * Returns a negative Integer, a positive Integer, or zero as
 1015  
      * the <code>builder</code> has judged the "left-hand" side
 1016  
      * as less than, greater than, or equal to the "right-hand"
 1017  
      * side.
 1018  
      * 
 1019  
      * @return final comparison result as an Integer
 1020  
      * @see #toComparison()
 1021  
      * @since 3.0
 1022  
      */
 1023  
     @Override
 1024  
     public Integer build() {
 1025  7
         return Integer.valueOf(toComparison());
 1026  
     }
 1027  
 }
 1028