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