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