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