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; 024 025import org.apache.commons.lang3.ArrayUtils; 026 027/** 028 * Assists in implementing {@link java.lang.Comparable#compareTo(Object)} methods. 029 * 030 * <p>It is consistent with <code>equals(Object)</code> and 031 * <code>hashcode()</code> built with {@link EqualsBuilder} and 032 * {@link HashCodeBuilder}.</p> 033 * 034 * <p>Two Objects that compare equal using <code>equals(Object)</code> should normally 035 * also compare equal using <code>compareTo(Object)</code>.</p> 036 * 037 * <p>All relevant fields should be included in the calculation of the 038 * comparison. Derived fields may be ignored. The same fields, in the same 039 * order, should be used in both <code>compareTo(Object)</code> and 040 * <code>equals(Object)</code>.</p> 041 * 042 * <p>To use this class write code as follows:</p> 043 * 044 * <pre> 045 * public class MyClass { 046 * String field1; 047 * int field2; 048 * boolean field3; 049 * 050 * ... 051 * 052 * public int compareTo(Object o) { 053 * MyClass myClass = (MyClass) o; 054 * return new CompareToBuilder() 055 * .appendSuper(super.compareTo(o) 056 * .append(this.field1, myClass.field1) 057 * .append(this.field2, myClass.field2) 058 * .append(this.field3, myClass.field3) 059 * .toComparison(); 060 * } 061 * } 062 * </pre> 063 * 064 * <p>Values are compared in the order they are appended to the builder. If any comparison returns 065 * a non-zero result, then that value will be the result returned by {@code toComparison()} and all 066 * subsequent comparisons are skipped.</p> 067 * 068 * <p>Alternatively, there are {@link #reflectionCompare(Object, Object) reflectionCompare} methods that use 069 * reflection to determine the fields to append. Because fields can be private, 070 * <code>reflectionCompare</code> uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to 071 * bypass normal access control checks. This will fail under a security manager, 072 * unless the appropriate permissions are set up correctly. It is also 073 * slower than appending explicitly.</p> 074 * 075 * <p>A typical implementation of <code>compareTo(Object)</code> using 076 * <code>reflectionCompare</code> looks like:</p> 077 078 * <pre> 079 * public int compareTo(Object o) { 080 * return CompareToBuilder.reflectionCompare(this, o); 081 * } 082 * </pre> 083 * 084 * <p>The reflective methods compare object fields in the order returned by 085 * {@link Class#getDeclaredFields()}. The fields of the class are compared first, followed by those 086 * of its parent classes (in order from the bottom to the top of the class hierarchy).</p> 087 * 088 * @see java.lang.Comparable 089 * @see java.lang.Object#equals(Object) 090 * @see java.lang.Object#hashCode() 091 * @see EqualsBuilder 092 * @see HashCodeBuilder 093 * @since 1.0 094 */ 095public class CompareToBuilder implements Builder<Integer> { 096 097 /** 098 * Current state of the comparison as appended fields are checked. 099 */ 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 super(); 111 comparison = 0; 112 } 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 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 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 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 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 if (lhs == rhs) { 283 return 0; 284 } 285 if (lhs == null || rhs == null) { 286 throw new NullPointerException(); 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</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 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</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 if (comparison != 0) { 350 return this; 351 } 352 comparison = superCompareTo; 353 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 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 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 { 424 // the simple case, not an array, just test the element 425 if (comparator == null) { 426 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc 427 final Comparable<Object> comparable = (Comparable<Object>) lhs; 428 comparison = comparable.compareTo(rhs); 429 } else { 430 @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc 431 final Comparator<Object> comparator2 = (Comparator<Object>) comparator; 432 comparison = comparator2.compare(lhs, rhs); 433 } 434 } 435 return this; 436 } 437 438 private void appendArray(final Object lhs, final Object rhs, final Comparator<?> comparator) { 439 // switch on type of array, to dispatch to the correct handler 440 // handles multi dimensional arrays 441 // throws a ClassCastException if rhs is not the correct array type 442 if (lhs instanceof long[]) { 443 append((long[]) lhs, (long[]) rhs); 444 } else if (lhs instanceof int[]) { 445 append((int[]) lhs, (int[]) rhs); 446 } else if (lhs instanceof short[]) { 447 append((short[]) lhs, (short[]) rhs); 448 } else if (lhs instanceof char[]) { 449 append((char[]) lhs, (char[]) rhs); 450 } else if (lhs instanceof byte[]) { 451 append((byte[]) lhs, (byte[]) rhs); 452 } else if (lhs instanceof double[]) { 453 append((double[]) lhs, (double[]) rhs); 454 } else if (lhs instanceof float[]) { 455 append((float[]) lhs, (float[]) rhs); 456 } else if (lhs instanceof boolean[]) { 457 append((boolean[]) lhs, (boolean[]) rhs); 458 } else { 459 // not an array of primitives 460 // throws a ClassCastException if rhs is not an array 461 append((Object[]) lhs, (Object[]) rhs, comparator); 462 } 463 } 464 465 //------------------------------------------------------------------------- 466 /** 467 * Appends to the <code>builder</code> the comparison of 468 * two <code>long</code>s. 469 * 470 * @param lhs left-hand value 471 * @param rhs right-hand value 472 * @return this - used to chain append calls 473 */ 474 public CompareToBuilder append(final long lhs, final long rhs) { 475 if (comparison != 0) { 476 return this; 477 } 478 comparison = lhs < rhs ? -1 : lhs > rhs ? 1 : 0; 479 return this; 480 } 481 482 /** 483 * Appends to the <code>builder</code> the comparison of 484 * two <code>int</code>s. 485 * 486 * @param lhs left-hand value 487 * @param rhs right-hand value 488 * @return this - used to chain append calls 489 */ 490 public CompareToBuilder append(final int lhs, final int rhs) { 491 if (comparison != 0) { 492 return this; 493 } 494 comparison = lhs < rhs ? -1 : lhs > rhs ? 1 : 0; 495 return this; 496 } 497 498 /** 499 * Appends to the <code>builder</code> the comparison of 500 * two <code>short</code>s. 501 * 502 * @param lhs left-hand value 503 * @param rhs right-hand value 504 * @return this - used to chain append calls 505 */ 506 public CompareToBuilder append(final short lhs, final short rhs) { 507 if (comparison != 0) { 508 return this; 509 } 510 comparison = lhs < rhs ? -1 : lhs > rhs ? 1 : 0; 511 return this; 512 } 513 514 /** 515 * Appends to the <code>builder</code> the comparison of 516 * two <code>char</code>s. 517 * 518 * @param lhs left-hand value 519 * @param rhs right-hand value 520 * @return this - used to chain append calls 521 */ 522 public CompareToBuilder append(final char lhs, final char rhs) { 523 if (comparison != 0) { 524 return this; 525 } 526 comparison = lhs < rhs ? -1 : lhs > rhs ? 1 : 0; 527 return this; 528 } 529 530 /** 531 * Appends to the <code>builder</code> the comparison of 532 * two <code>byte</code>s. 533 * 534 * @param lhs left-hand value 535 * @param rhs right-hand value 536 * @return this - used to chain append calls 537 */ 538 public CompareToBuilder append(final byte lhs, final byte rhs) { 539 if (comparison != 0) { 540 return this; 541 } 542 comparison = lhs < rhs ? -1 : lhs > rhs ? 1 : 0; 543 return this; 544 } 545 546 /** 547 * <p>Appends to the <code>builder</code> the comparison of 548 * two <code>double</code>s.</p> 549 * 550 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 551 * 552 * <p>It is compatible with the hash code generated by 553 * <code>HashCodeBuilder</code>.</p> 554 * 555 * @param lhs left-hand value 556 * @param rhs right-hand value 557 * @return this - used to chain append calls 558 */ 559 public CompareToBuilder append(final double lhs, final double rhs) { 560 if (comparison != 0) { 561 return this; 562 } 563 comparison = Double.compare(lhs, rhs); 564 return this; 565 } 566 567 /** 568 * <p>Appends to the <code>builder</code> the comparison of 569 * two <code>float</code>s.</p> 570 * 571 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 572 * 573 * <p>It is compatible with the hash code generated by 574 * <code>HashCodeBuilder</code>.</p> 575 * 576 * @param lhs left-hand value 577 * @param rhs right-hand value 578 * @return this - used to chain append calls 579 */ 580 public CompareToBuilder append(final float lhs, final float rhs) { 581 if (comparison != 0) { 582 return this; 583 } 584 comparison = Float.compare(lhs, rhs); 585 return this; 586 } 587 588 /** 589 * Appends to the <code>builder</code> the comparison of 590 * two <code>booleans</code>s. 591 * 592 * @param lhs left-hand value 593 * @param rhs right-hand value 594 * @return this - used to chain append calls 595 */ 596 public CompareToBuilder append(final boolean lhs, final boolean rhs) { 597 if (comparison != 0) { 598 return this; 599 } 600 if (lhs == rhs) { 601 return this; 602 } 603 if (lhs == false) { 604 comparison = -1; 605 } else { 606 comparison = +1; 607 } 608 return this; 609 } 610 611 //----------------------------------------------------------------------- 612 /** 613 * <p>Appends to the <code>builder</code> the deep comparison of 614 * two <code>Object</code> arrays.</p> 615 * 616 * <ol> 617 * <li>Check if arrays are the same using <code>==</code></li> 618 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 619 * <li>Check array length, a short length array is less than a long length array</li> 620 * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li> 621 * </ol> 622 * 623 * <p>This method will also will be called for the top level of multi-dimensional, 624 * ragged, and multi-typed arrays.</p> 625 * 626 * @param lhs left-hand array 627 * @param rhs right-hand array 628 * @return this - used to chain append calls 629 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible 630 * with <code>lhs</code> 631 */ 632 public CompareToBuilder append(final Object[] lhs, final Object[] rhs) { 633 return append(lhs, rhs, null); 634 } 635 636 /** 637 * <p>Appends to the <code>builder</code> the deep comparison of 638 * two <code>Object</code> arrays.</p> 639 * 640 * <ol> 641 * <li>Check if arrays are the same using <code>==</code></li> 642 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 643 * <li>Check array length, a short length array is less than a long length array</li> 644 * <li>Check array contents element by element using {@link #append(Object, Object, Comparator)}</li> 645 * </ol> 646 * 647 * <p>This method will also will be called for the top level of multi-dimensional, 648 * ragged, and multi-typed arrays.</p> 649 * 650 * @param lhs left-hand array 651 * @param rhs right-hand array 652 * @param comparator <code>Comparator</code> to use to compare the array elements, 653 * <code>null</code> means to treat <code>lhs</code> elements as <code>Comparable</code>. 654 * @return this - used to chain append calls 655 * @throws ClassCastException if <code>rhs</code> is not assignment-compatible 656 * with <code>lhs</code> 657 * @since 2.0 658 */ 659 public CompareToBuilder append(final Object[] lhs, final Object[] rhs, final Comparator<?> comparator) { 660 if (comparison != 0) { 661 return this; 662 } 663 if (lhs == rhs) { 664 return this; 665 } 666 if (lhs == null) { 667 comparison = -1; 668 return this; 669 } 670 if (rhs == null) { 671 comparison = +1; 672 return this; 673 } 674 if (lhs.length != rhs.length) { 675 comparison = lhs.length < rhs.length ? -1 : +1; 676 return this; 677 } 678 for (int i = 0; i < lhs.length && comparison == 0; i++) { 679 append(lhs[i], rhs[i], comparator); 680 } 681 return this; 682 } 683 684 /** 685 * <p>Appends to the <code>builder</code> the deep comparison of 686 * two <code>long</code> arrays.</p> 687 * 688 * <ol> 689 * <li>Check if arrays are the same using <code>==</code></li> 690 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 691 * <li>Check array length, a shorter length array is less than a longer length array</li> 692 * <li>Check array contents element by element using {@link #append(long, long)}</li> 693 * </ol> 694 * 695 * @param lhs left-hand array 696 * @param rhs right-hand array 697 * @return this - used to chain append calls 698 */ 699 public CompareToBuilder append(final long[] lhs, final long[] rhs) { 700 if (comparison != 0) { 701 return this; 702 } 703 if (lhs == rhs) { 704 return this; 705 } 706 if (lhs == null) { 707 comparison = -1; 708 return this; 709 } 710 if (rhs == null) { 711 comparison = +1; 712 return this; 713 } 714 if (lhs.length != rhs.length) { 715 comparison = lhs.length < rhs.length ? -1 : +1; 716 return this; 717 } 718 for (int i = 0; i < lhs.length && comparison == 0; i++) { 719 append(lhs[i], rhs[i]); 720 } 721 return this; 722 } 723 724 /** 725 * <p>Appends to the <code>builder</code> the deep comparison of 726 * two <code>int</code> arrays.</p> 727 * 728 * <ol> 729 * <li>Check if arrays are the same using <code>==</code></li> 730 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 731 * <li>Check array length, a shorter length array is less than a longer length array</li> 732 * <li>Check array contents element by element using {@link #append(int, int)}</li> 733 * </ol> 734 * 735 * @param lhs left-hand array 736 * @param rhs right-hand array 737 * @return this - used to chain append calls 738 */ 739 public CompareToBuilder append(final int[] lhs, final int[] rhs) { 740 if (comparison != 0) { 741 return this; 742 } 743 if (lhs == rhs) { 744 return this; 745 } 746 if (lhs == null) { 747 comparison = -1; 748 return this; 749 } 750 if (rhs == null) { 751 comparison = +1; 752 return this; 753 } 754 if (lhs.length != rhs.length) { 755 comparison = lhs.length < rhs.length ? -1 : +1; 756 return this; 757 } 758 for (int i = 0; i < lhs.length && comparison == 0; i++) { 759 append(lhs[i], rhs[i]); 760 } 761 return this; 762 } 763 764 /** 765 * <p>Appends to the <code>builder</code> the deep comparison of 766 * two <code>short</code> arrays.</p> 767 * 768 * <ol> 769 * <li>Check if arrays are the same using <code>==</code></li> 770 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 771 * <li>Check array length, a shorter length array is less than a longer length array</li> 772 * <li>Check array contents element by element using {@link #append(short, short)}</li> 773 * </ol> 774 * 775 * @param lhs left-hand array 776 * @param rhs right-hand array 777 * @return this - used to chain append calls 778 */ 779 public CompareToBuilder append(final short[] lhs, final short[] rhs) { 780 if (comparison != 0) { 781 return this; 782 } 783 if (lhs == rhs) { 784 return this; 785 } 786 if (lhs == null) { 787 comparison = -1; 788 return this; 789 } 790 if (rhs == null) { 791 comparison = +1; 792 return this; 793 } 794 if (lhs.length != rhs.length) { 795 comparison = lhs.length < rhs.length ? -1 : +1; 796 return this; 797 } 798 for (int i = 0; i < lhs.length && comparison == 0; i++) { 799 append(lhs[i], rhs[i]); 800 } 801 return this; 802 } 803 804 /** 805 * <p>Appends to the <code>builder</code> the deep comparison of 806 * two <code>char</code> arrays.</p> 807 * 808 * <ol> 809 * <li>Check if arrays are the same using <code>==</code></li> 810 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 811 * <li>Check array length, a shorter length array is less than a longer length array</li> 812 * <li>Check array contents element by element using {@link #append(char, char)}</li> 813 * </ol> 814 * 815 * @param lhs left-hand array 816 * @param rhs right-hand array 817 * @return this - used to chain append calls 818 */ 819 public CompareToBuilder append(final char[] lhs, final char[] rhs) { 820 if (comparison != 0) { 821 return this; 822 } 823 if (lhs == rhs) { 824 return this; 825 } 826 if (lhs == null) { 827 comparison = -1; 828 return this; 829 } 830 if (rhs == null) { 831 comparison = +1; 832 return this; 833 } 834 if (lhs.length != rhs.length) { 835 comparison = lhs.length < rhs.length ? -1 : +1; 836 return this; 837 } 838 for (int i = 0; i < lhs.length && comparison == 0; i++) { 839 append(lhs[i], rhs[i]); 840 } 841 return this; 842 } 843 844 /** 845 * <p>Appends to the <code>builder</code> the deep comparison of 846 * two <code>byte</code> arrays.</p> 847 * 848 * <ol> 849 * <li>Check if arrays are the same using <code>==</code></li> 850 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 851 * <li>Check array length, a shorter length array is less than a longer length array</li> 852 * <li>Check array contents element by element using {@link #append(byte, byte)}</li> 853 * </ol> 854 * 855 * @param lhs left-hand array 856 * @param rhs right-hand array 857 * @return this - used to chain append calls 858 */ 859 public CompareToBuilder append(final byte[] lhs, final byte[] rhs) { 860 if (comparison != 0) { 861 return this; 862 } 863 if (lhs == rhs) { 864 return this; 865 } 866 if (lhs == null) { 867 comparison = -1; 868 return this; 869 } 870 if (rhs == null) { 871 comparison = +1; 872 return this; 873 } 874 if (lhs.length != rhs.length) { 875 comparison = lhs.length < rhs.length ? -1 : +1; 876 return this; 877 } 878 for (int i = 0; i < lhs.length && comparison == 0; i++) { 879 append(lhs[i], rhs[i]); 880 } 881 return this; 882 } 883 884 /** 885 * <p>Appends to the <code>builder</code> the deep comparison of 886 * two <code>double</code> arrays.</p> 887 * 888 * <ol> 889 * <li>Check if arrays are the same using <code>==</code></li> 890 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 891 * <li>Check array length, a shorter length array is less than a longer length array</li> 892 * <li>Check array contents element by element using {@link #append(double, double)}</li> 893 * </ol> 894 * 895 * @param lhs left-hand array 896 * @param rhs right-hand array 897 * @return this - used to chain append calls 898 */ 899 public CompareToBuilder append(final double[] lhs, final double[] rhs) { 900 if (comparison != 0) { 901 return this; 902 } 903 if (lhs == rhs) { 904 return this; 905 } 906 if (lhs == null) { 907 comparison = -1; 908 return this; 909 } 910 if (rhs == null) { 911 comparison = +1; 912 return this; 913 } 914 if (lhs.length != rhs.length) { 915 comparison = lhs.length < rhs.length ? -1 : +1; 916 return this; 917 } 918 for (int i = 0; i < lhs.length && comparison == 0; i++) { 919 append(lhs[i], rhs[i]); 920 } 921 return this; 922 } 923 924 /** 925 * <p>Appends to the <code>builder</code> the deep comparison of 926 * two <code>float</code> arrays.</p> 927 * 928 * <ol> 929 * <li>Check if arrays are the same using <code>==</code></li> 930 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 931 * <li>Check array length, a shorter length array is less than a longer length array</li> 932 * <li>Check array contents element by element using {@link #append(float, float)}</li> 933 * </ol> 934 * 935 * @param lhs left-hand array 936 * @param rhs right-hand array 937 * @return this - used to chain append calls 938 */ 939 public CompareToBuilder append(final float[] lhs, final float[] rhs) { 940 if (comparison != 0) { 941 return this; 942 } 943 if (lhs == rhs) { 944 return this; 945 } 946 if (lhs == null) { 947 comparison = -1; 948 return this; 949 } 950 if (rhs == null) { 951 comparison = +1; 952 return this; 953 } 954 if (lhs.length != rhs.length) { 955 comparison = lhs.length < rhs.length ? -1 : +1; 956 return this; 957 } 958 for (int i = 0; i < lhs.length && comparison == 0; i++) { 959 append(lhs[i], rhs[i]); 960 } 961 return this; 962 } 963 964 /** 965 * <p>Appends to the <code>builder</code> the deep comparison of 966 * two <code>boolean</code> arrays.</p> 967 * 968 * <ol> 969 * <li>Check if arrays are the same using <code>==</code></li> 970 * <li>Check if for <code>null</code>, <code>null</code> is less than non-<code>null</code></li> 971 * <li>Check array length, a shorter length array is less than a longer length array</li> 972 * <li>Check array contents element by element using {@link #append(boolean, boolean)}</li> 973 * </ol> 974 * 975 * @param lhs left-hand array 976 * @param rhs right-hand array 977 * @return this - used to chain append calls 978 */ 979 public CompareToBuilder append(final boolean[] lhs, final boolean[] rhs) { 980 if (comparison != 0) { 981 return this; 982 } 983 if (lhs == rhs) { 984 return this; 985 } 986 if (lhs == null) { 987 comparison = -1; 988 return this; 989 } 990 if (rhs == null) { 991 comparison = +1; 992 return this; 993 } 994 if (lhs.length != rhs.length) { 995 comparison = lhs.length < rhs.length ? -1 : +1; 996 return this; 997 } 998 for (int i = 0; i < lhs.length && comparison == 0; i++) { 999 append(lhs[i], rhs[i]); 1000 } 1001 return this; 1002 } 1003 1004 //----------------------------------------------------------------------- 1005 /** 1006 * Returns a negative integer, a positive integer, or zero as 1007 * the <code>builder</code> has judged the "left-hand" side 1008 * as less than, greater than, or equal to the "right-hand" 1009 * side. 1010 * 1011 * @return final comparison result 1012 * @see #build() 1013 */ 1014 public int toComparison() { 1015 return comparison; 1016 } 1017 1018 /** 1019 * Returns a negative Integer, a positive Integer, or zero as 1020 * the <code>builder</code> has judged the "left-hand" side 1021 * as less than, greater than, or equal to the "right-hand" 1022 * side. 1023 * 1024 * @return final comparison result as an Integer 1025 * @see #toComparison() 1026 * @since 3.0 1027 */ 1028 @Override 1029 public Integer build() { 1030 return Integer.valueOf(toComparison()); 1031 } 1032} 1033