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