1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 6 //NON-STANDARD LICENCE HEADER HERE - THAT'S OK 7 //Class comes from Apache Commons Lang, added some tiny changes 8 package org.mockito.internal.matchers.apachecommons; 9 10 import java.lang.reflect.AccessibleObject; 11 import java.lang.reflect.Field; 12 import java.lang.reflect.Modifier; 13 import java.util.Arrays; 14 import java.util.Collections; 15 import java.util.List; 16 17 /** 18 * <p>Assists in implementing {@link Object#equals(Object)} methods.</p> 19 * 20 * <p> This class provides methods to build a good equals method for any 21 * class. It follows rules laid out in 22 * <a href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> 23 * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>, 24 * <code>floats</code>, and arrays can be tricky. Also, making sure that 25 * <code>equals()</code> and <code>hashCode()</code> are consistent can be 26 * difficult.</p> 27 * 28 * <p>Two Objects that compare as equals must generate the same hash code, 29 * but two Objects with the same hash code do not have to be equal.</p> 30 * 31 * <p>All relevant fields should be included in the calculation of equals. 32 * Derived fields may be ignored. In particular, any field used in 33 * generating a hash code must be used in the equals method, and vice 34 * versa.</p> 35 * 36 * <p>Typical use for the code is as follows:</p> 37 * <pre class="code"><code class="java"> 38 * public boolean equals(Object obj) { 39 * if (obj == null) { return false; } 40 * if (obj == this) { return true; } 41 * if (obj.getClass() != getClass()) { 42 * return false; 43 * } 44 * MyClass rhs = (MyClass) obj; 45 * return new EqualsBuilder() 46 * .appendSuper(super.equals(obj)) 47 * .append(field1, rhs.field1) 48 * .append(field2, rhs.field2) 49 * .append(field3, rhs.field3) 50 * .isEquals(); 51 * } 52 * </code></pre> 53 * 54 * <p> Alternatively, there is a method that uses reflection to determine 55 * the fields to test. Because these fields are usually private, the method, 56 * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to 57 * change the visibility of the fields. This will fail under a security 58 * manager, unless the appropriate permissions are set up correctly. It is 59 * also slower than testing explicitly.</p> 60 * 61 * <p> A typical invocation for this method would look like:</p> 62 * <pre class="code"><code class="java"> 63 * public boolean equals(Object obj) { 64 * return EqualsBuilder.reflectionEquals(this, obj); 65 * } 66 * </code></pre> 67 * 68 * @author <a href="mailto:steve.downey (at) netfolio.com">Steve Downey</a> 69 * @author Stephen Colebourne 70 * @author Gary Gregory 71 * @author Pete Gieser 72 * @author Arun Mammen Thomas 73 * @since 1.0 74 * @version $Id: EqualsBuilder.java 611543 2008-01-13 07:00:22Z bayard $ 75 */ 76 @SuppressWarnings("unchecked") 77 class EqualsBuilder { 78 79 /** 80 * If the fields tested are equals. 81 * The default value is <code>true</code>. 82 */ 83 private boolean isEquals = true; 84 85 /** 86 * <p>Constructor for EqualsBuilder.</p> 87 * 88 * <p>Starts off assuming that equals is <code>true</code>.</p> 89 * @see Object#equals(Object) 90 */ 91 public EqualsBuilder() { 92 // do nothing for now. 93 } 94 95 //------------------------------------------------------------------------- 96 97 /** 98 * <p>This method uses reflection to determine if the two <code>Object</code>s 99 * are equal.</p> 100 * 101 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 102 * fields. This means that it will throw a security exception if run under 103 * a security manager, if the permissions are not set up correctly. It is also 104 * not as efficient as testing explicitly.</p> 105 * 106 * <p>Transient members will be not be tested, as they are likely derived 107 * fields, and not part of the value of the Object.</p> 108 * 109 * <p>Static fields will not be tested. Superclass fields will be included.</p> 110 * 111 * @param lhs <code>this</code> object 112 * @param rhs the other object 113 * @return <code>true</code> if the two Objects have tested equals. 114 */ 115 public static boolean reflectionEquals(Object lhs, Object rhs) { 116 return reflectionEquals(lhs, rhs, false, null, null); 117 } 118 119 /** 120 * <p>This method uses reflection to determine if the two <code>Object</code>s 121 * are equal.</p> 122 * 123 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 124 * fields. This means that it will throw a security exception if run under 125 * a security manager, if the permissions are not set up correctly. It is also 126 * not as efficient as testing explicitly.</p> 127 * 128 * <p>Transient members will be not be tested, as they are likely derived 129 * fields, and not part of the value of the Object.</p> 130 * 131 * <p>Static fields will not be tested. Superclass fields will be included.</p> 132 * 133 * @param lhs <code>this</code> object 134 * @param rhs the other object 135 * @param excludeFields array of field names to exclude from testing 136 * @return <code>true</code> if the two Objects have tested equals. 137 */ 138 public static boolean reflectionEquals(Object lhs, Object rhs, String[] excludeFields) { 139 return reflectionEquals(lhs, rhs, false, null, excludeFields); 140 } 141 142 /** 143 * <p>This method uses reflection to determine if the two <code>Object</code>s 144 * are equal.</p> 145 * 146 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 147 * fields. This means that it will throw a security exception if run under 148 * a security manager, if the permissions are not set up correctly. It is also 149 * not as efficient as testing explicitly.</p> 150 * 151 * <p>If the TestTransients parameter is set to <code>true</code>, transient 152 * members will be tested, otherwise they are ignored, as they are likely 153 * derived fields, and not part of the value of the <code>Object</code>.</p> 154 * 155 * <p>Static fields will not be tested. Superclass fields will be included.</p> 156 * 157 * @param lhs <code>this</code> object 158 * @param rhs the other object 159 * @param testTransients whether to include transient fields 160 * @return <code>true</code> if the two Objects have tested equals. 161 */ 162 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) { 163 return reflectionEquals(lhs, rhs, testTransients, null, null); 164 } 165 166 /** 167 * <p>This method uses reflection to determine if the two <code>Object</code>s 168 * are equal.</p> 169 * 170 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 171 * fields. This means that it will throw a security exception if run under 172 * a security manager, if the permissions are not set up correctly. It is also 173 * not as efficient as testing explicitly.</p> 174 * 175 * <p>If the testTransients parameter is set to <code>true</code>, transient 176 * members will be tested, otherwise they are ignored, as they are likely 177 * derived fields, and not part of the value of the <code>Object</code>.</p> 178 * 179 * <p>Static fields will not be included. Superclass fields will be appended 180 * up to and including the specified superclass. A null superclass is treated 181 * as java.lang.Object.</p> 182 * 183 * @param lhs <code>this</code> object 184 * @param rhs the other object 185 * @param testTransients whether to include transient fields 186 * @param reflectUpToClass the superclass to reflect up to (inclusive), 187 * may be <code>null</code> 188 * @return <code>true</code> if the two Objects have tested equals. 189 * @since 2.0 190 */ 191 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) { 192 return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, null); 193 } 194 195 /** 196 * <p>This method uses reflection to determine if the two <code>Object</code>s 197 * are equal.</p> 198 * 199 * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private 200 * fields. This means that it will throw a security exception if run under 201 * a security manager, if the permissions are not set up correctly. It is also 202 * not as efficient as testing explicitly.</p> 203 * 204 * <p>If the testTransients parameter is set to <code>true</code>, transient 205 * members will be tested, otherwise they are ignored, as they are likely 206 * derived fields, and not part of the value of the <code>Object</code>.</p> 207 * 208 * <p>Static fields will not be included. Superclass fields will be appended 209 * up to and including the specified superclass. A null superclass is treated 210 * as java.lang.Object.</p> 211 * 212 * @param lhs <code>this</code> object 213 * @param rhs the other object 214 * @param testTransients whether to include transient fields 215 * @param reflectUpToClass the superclass to reflect up to (inclusive), 216 * may be <code>null</code> 217 * @param excludeFields array of field names to exclude from testing 218 * @return <code>true</code> if the two Objects have tested equals. 219 * @since 2.0 220 */ 221 public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass, 222 String[] excludeFields) { 223 if (lhs == rhs) { 224 return true; 225 } 226 if (lhs == null || rhs == null) { 227 return false; 228 } 229 // Find the leaf class since there may be transients in the leaf 230 // class or in classes between the leaf and root. 231 // If we are not testing transients or a subclass has no ivars, 232 // then a subclass can test equals to a superclass. 233 Class lhsClass = lhs.getClass(); 234 Class rhsClass = rhs.getClass(); 235 Class testClass; 236 if (lhsClass.isInstance(rhs)) { 237 testClass = lhsClass; 238 if (!rhsClass.isInstance(lhs)) { 239 // rhsClass is a subclass of lhsClass 240 testClass = rhsClass; 241 } 242 } else if (rhsClass.isInstance(lhs)) { 243 testClass = rhsClass; 244 if (!lhsClass.isInstance(rhs)) { 245 // lhsClass is a subclass of rhsClass 246 testClass = lhsClass; 247 } 248 } else { 249 // The two classes are not related. 250 return false; 251 } 252 EqualsBuilder equalsBuilder = new EqualsBuilder(); 253 try { 254 reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields); 255 while (testClass.getSuperclass() != null && testClass != reflectUpToClass) { 256 testClass = testClass.getSuperclass(); 257 reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients, excludeFields); 258 } 259 } catch (IllegalArgumentException e) { 260 // In this case, we tried to test a subclass vs. a superclass and 261 // the subclass has ivars or the ivars are transient and 262 // we are testing transients. 263 // If a subclass has ivars that we are trying to test them, we get an 264 // exception and we know that the objects are not equal. 265 return false; 266 } 267 return equalsBuilder.isEquals(); 268 } 269 270 /** 271 * <p>Appends the fields and values defined by the given object of the 272 * given Class.</p> 273 * 274 * @param lhs the left hand object 275 * @param rhs the right hand object 276 * @param clazz the class to append details of 277 * @param builder the builder to append to 278 * @param useTransients whether to test transient fields 279 * @param excludeFields array of field names to exclude from testing 280 */ 281 private static void reflectionAppend( 282 Object lhs, 283 Object rhs, 284 Class clazz, 285 EqualsBuilder builder, 286 boolean useTransients, 287 String[] excludeFields) { 288 Field[] fields = clazz.getDeclaredFields(); 289 List excludedFieldList = excludeFields != null ? Arrays.asList(excludeFields) : Collections.EMPTY_LIST; 290 AccessibleObject.setAccessible(fields, true); 291 for (int i = 0; i < fields.length && builder.isEquals; i++) { 292 Field f = fields[i]; 293 if (!excludedFieldList.contains(f.getName()) 294 && (f.getName().indexOf('$') == -1) 295 && (useTransients || !Modifier.isTransient(f.getModifiers())) 296 && (!Modifier.isStatic(f.getModifiers()))) { 297 try { 298 builder.append(f.get(lhs), f.get(rhs)); 299 } catch (IllegalAccessException e) { 300 //this can't happen. Would get a Security exception instead 301 //throw a runtime exception in case the impossible happens. 302 throw new InternalError("Unexpected IllegalAccessException"); 303 } 304 } 305 } 306 } 307 308 //------------------------------------------------------------------------- 309 310 /** 311 * <p>Adds the result of <code>super.equals()</code> to this builder.</p> 312 * 313 * @param superEquals the result of calling <code>super.equals()</code> 314 * @return EqualsBuilder - used to chain calls. 315 * @since 2.0 316 */ 317 public EqualsBuilder appendSuper(boolean superEquals) { 318 if (isEquals == false) { 319 return this; 320 } 321 isEquals = superEquals; 322 return this; 323 } 324 325 //------------------------------------------------------------------------- 326 327 /** 328 * <p>Test if two <code>Object</code>s are equal using their 329 * <code>equals</code> method.</p> 330 * 331 * @param lhs the left hand object 332 * @param rhs the right hand object 333 * @return EqualsBuilder - used to chain calls. 334 */ 335 public EqualsBuilder append(Object lhs, Object rhs) { 336 if (isEquals == false) { 337 return this; 338 } 339 if (lhs == rhs) { 340 return this; 341 } 342 if (lhs == null || rhs == null) { 343 this.setEquals(false); 344 return this; 345 } 346 Class lhsClass = lhs.getClass(); 347 if (!lhsClass.isArray()) { 348 if (lhs instanceof java.math.BigDecimal && rhs instanceof java.math.BigDecimal) { 349 isEquals = (((java.math.BigDecimal) lhs).compareTo((java.math.BigDecimal) rhs) == 0); 350 } else { 351 // The simple case, not an array, just test the element 352 isEquals = lhs.equals(rhs); 353 } 354 } else if (lhs.getClass() != rhs.getClass()) { 355 // Here when we compare different dimensions, for example: a boolean[][] to a boolean[] 356 this.setEquals(false); 357 358 // 'Switch' on type of array, to dispatch to the correct handler 359 // This handles multi dimensional arrays of the same depth 360 } else if (lhs instanceof long[]) { 361 append((long[]) lhs, (long[]) rhs); 362 } else if (lhs instanceof int[]) { 363 append((int[]) lhs, (int[]) rhs); 364 } else if (lhs instanceof short[]) { 365 append((short[]) lhs, (short[]) rhs); 366 } else if (lhs instanceof char[]) { 367 append((char[]) lhs, (char[]) rhs); 368 } else if (lhs instanceof byte[]) { 369 append((byte[]) lhs, (byte[]) rhs); 370 } else if (lhs instanceof double[]) { 371 append((double[]) lhs, (double[]) rhs); 372 } else if (lhs instanceof float[]) { 373 append((float[]) lhs, (float[]) rhs); 374 } else if (lhs instanceof boolean[]) { 375 append((boolean[]) lhs, (boolean[]) rhs); 376 } else { 377 // Not an array of primitives 378 append((Object[]) lhs, (Object[]) rhs); 379 } 380 return this; 381 } 382 383 /** 384 * <p> 385 * Test if two <code>long</code> s are equal. 386 * </p> 387 * 388 * @param lhs 389 * the left hand <code>long</code> 390 * @param rhs 391 * the right hand <code>long</code> 392 * @return EqualsBuilder - used to chain calls. 393 */ 394 public EqualsBuilder append(long lhs, long rhs) { 395 if (isEquals == false) { 396 return this; 397 } 398 isEquals = (lhs == rhs); 399 return this; 400 } 401 402 /** 403 * <p>Test if two <code>int</code>s are equal.</p> 404 * 405 * @param lhs the left hand <code>int</code> 406 * @param rhs the right hand <code>int</code> 407 * @return EqualsBuilder - used to chain calls. 408 */ 409 public EqualsBuilder append(int lhs, int rhs) { 410 if (isEquals == false) { 411 return this; 412 } 413 isEquals = (lhs == rhs); 414 return this; 415 } 416 417 /** 418 * <p>Test if two <code>short</code>s are equal.</p> 419 * 420 * @param lhs the left hand <code>short</code> 421 * @param rhs the right hand <code>short</code> 422 * @return EqualsBuilder - used to chain calls. 423 */ 424 public EqualsBuilder append(short lhs, short rhs) { 425 if (isEquals == false) { 426 return this; 427 } 428 isEquals = (lhs == rhs); 429 return this; 430 } 431 432 /** 433 * <p>Test if two <code>char</code>s are equal.</p> 434 * 435 * @param lhs the left hand <code>char</code> 436 * @param rhs the right hand <code>char</code> 437 * @return EqualsBuilder - used to chain calls. 438 */ 439 public EqualsBuilder append(char lhs, char rhs) { 440 if (isEquals == false) { 441 return this; 442 } 443 isEquals = (lhs == rhs); 444 return this; 445 } 446 447 /** 448 * <p>Test if two <code>byte</code>s are equal.</p> 449 * 450 * @param lhs the left hand <code>byte</code> 451 * @param rhs the right hand <code>byte</code> 452 * @return EqualsBuilder - used to chain calls. 453 */ 454 public EqualsBuilder append(byte lhs, byte rhs) { 455 if (isEquals == false) { 456 return this; 457 } 458 isEquals = (lhs == rhs); 459 return this; 460 } 461 462 /** 463 * <p>Test if two <code>double</code>s are equal by testing that the 464 * pattern of bits returned by <code>doubleToLong</code> are equal.</p> 465 * 466 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 467 * 468 * <p>It is compatible with the hash code generated by 469 * <code>HashCodeBuilder</code>.</p> 470 * 471 * @param lhs the left hand <code>double</code> 472 * @param rhs the right hand <code>double</code> 473 * @return EqualsBuilder - used to chain calls. 474 */ 475 public EqualsBuilder append(double lhs, double rhs) { 476 if (isEquals == false) { 477 return this; 478 } 479 return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs)); 480 } 481 482 /** 483 * <p>Test if two <code>float</code>s are equal byt testing that the 484 * pattern of bits returned by doubleToLong are equal.</p> 485 * 486 * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p> 487 * 488 * <p>It is compatible with the hash code generated by 489 * <code>HashCodeBuilder</code>.</p> 490 * 491 * @param lhs the left hand <code>float</code> 492 * @param rhs the right hand <code>float</code> 493 * @return EqualsBuilder - used to chain calls. 494 */ 495 public EqualsBuilder append(float lhs, float rhs) { 496 if (isEquals == false) { 497 return this; 498 } 499 return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs)); 500 } 501 502 /** 503 * <p>Test if two <code>booleans</code>s are equal.</p> 504 * 505 * @param lhs the left hand <code>boolean</code> 506 * @param rhs the right hand <code>boolean</code> 507 * @return EqualsBuilder - used to chain calls. 508 */ 509 public EqualsBuilder append(boolean lhs, boolean rhs) { 510 if (isEquals == false) { 511 return this; 512 } 513 isEquals = (lhs == rhs); 514 return this; 515 } 516 517 /** 518 * <p>Performs a deep comparison of two <code>Object</code> arrays.</p> 519 * 520 * <p>This also will be called for the top level of 521 * multi-dimensional, ragged, and multi-typed arrays.</p> 522 * 523 * @param lhs the left hand <code>Object[]</code> 524 * @param rhs the right hand <code>Object[]</code> 525 * @return EqualsBuilder - used to chain calls. 526 */ 527 public EqualsBuilder append(Object[] lhs, Object[] rhs) { 528 if (isEquals == false) { 529 return this; 530 } 531 if (lhs == rhs) { 532 return this; 533 } 534 if (lhs == null || rhs == null) { 535 this.setEquals(false); 536 return this; 537 } 538 if (lhs.length != rhs.length) { 539 this.setEquals(false); 540 return this; 541 } 542 for (int i = 0; i < lhs.length && isEquals; ++i) { 543 append(lhs[i], rhs[i]); 544 } 545 return this; 546 } 547 548 /** 549 * <p>Deep comparison of array of <code>long</code>. Length and all 550 * values are compared.</p> 551 * 552 * <p>The method {@link #append(long, long)} is used.</p> 553 * 554 * @param lhs the left hand <code>long[]</code> 555 * @param rhs the right hand <code>long[]</code> 556 * @return EqualsBuilder - used to chain calls. 557 */ 558 public EqualsBuilder append(long[] lhs, long[] rhs) { 559 if (isEquals == false) { 560 return this; 561 } 562 if (lhs == rhs) { 563 return this; 564 } 565 if (lhs == null || rhs == null) { 566 this.setEquals(false); 567 return this; 568 } 569 if (lhs.length != rhs.length) { 570 this.setEquals(false); 571 return this; 572 } 573 for (int i = 0; i < lhs.length && isEquals; ++i) { 574 append(lhs[i], rhs[i]); 575 } 576 return this; 577 } 578 579 /** 580 * <p>Deep comparison of array of <code>int</code>. Length and all 581 * values are compared.</p> 582 * 583 * <p>The method {@link #append(int, int)} is used.</p> 584 * 585 * @param lhs the left hand <code>int[]</code> 586 * @param rhs the right hand <code>int[]</code> 587 * @return EqualsBuilder - used to chain calls. 588 */ 589 public EqualsBuilder append(int[] lhs, int[] rhs) { 590 if (isEquals == false) { 591 return this; 592 } 593 if (lhs == rhs) { 594 return this; 595 } 596 if (lhs == null || rhs == null) { 597 this.setEquals(false); 598 return this; 599 } 600 if (lhs.length != rhs.length) { 601 this.setEquals(false); 602 return this; 603 } 604 for (int i = 0; i < lhs.length && isEquals; ++i) { 605 append(lhs[i], rhs[i]); 606 } 607 return this; 608 } 609 610 /** 611 * <p>Deep comparison of array of <code>short</code>. Length and all 612 * values are compared.</p> 613 * 614 * <p>The method {@link #append(short, short)} is used.</p> 615 * 616 * @param lhs the left hand <code>short[]</code> 617 * @param rhs the right hand <code>short[]</code> 618 * @return EqualsBuilder - used to chain calls. 619 */ 620 public EqualsBuilder append(short[] lhs, short[] rhs) { 621 if (isEquals == false) { 622 return this; 623 } 624 if (lhs == rhs) { 625 return this; 626 } 627 if (lhs == null || rhs == null) { 628 this.setEquals(false); 629 return this; 630 } 631 if (lhs.length != rhs.length) { 632 this.setEquals(false); 633 return this; 634 } 635 for (int i = 0; i < lhs.length && isEquals; ++i) { 636 append(lhs[i], rhs[i]); 637 } 638 return this; 639 } 640 641 /** 642 * <p>Deep comparison of array of <code>char</code>. Length and all 643 * values are compared.</p> 644 * 645 * <p>The method {@link #append(char, char)} is used.</p> 646 * 647 * @param lhs the left hand <code>char[]</code> 648 * @param rhs the right hand <code>char[]</code> 649 * @return EqualsBuilder - used to chain calls. 650 */ 651 public EqualsBuilder append(char[] lhs, char[] rhs) { 652 if (isEquals == false) { 653 return this; 654 } 655 if (lhs == rhs) { 656 return this; 657 } 658 if (lhs == null || rhs == null) { 659 this.setEquals(false); 660 return this; 661 } 662 if (lhs.length != rhs.length) { 663 this.setEquals(false); 664 return this; 665 } 666 for (int i = 0; i < lhs.length && isEquals; ++i) { 667 append(lhs[i], rhs[i]); 668 } 669 return this; 670 } 671 672 /** 673 * <p>Deep comparison of array of <code>byte</code>. Length and all 674 * values are compared.</p> 675 * 676 * <p>The method {@link #append(byte, byte)} is used.</p> 677 * 678 * @param lhs the left hand <code>byte[]</code> 679 * @param rhs the right hand <code>byte[]</code> 680 * @return EqualsBuilder - used to chain calls. 681 */ 682 public EqualsBuilder append(byte[] lhs, byte[] rhs) { 683 if (isEquals == false) { 684 return this; 685 } 686 if (lhs == rhs) { 687 return this; 688 } 689 if (lhs == null || rhs == null) { 690 this.setEquals(false); 691 return this; 692 } 693 if (lhs.length != rhs.length) { 694 this.setEquals(false); 695 return this; 696 } 697 for (int i = 0; i < lhs.length && isEquals; ++i) { 698 append(lhs[i], rhs[i]); 699 } 700 return this; 701 } 702 703 /** 704 * <p>Deep comparison of array of <code>double</code>. Length and all 705 * values are compared.</p> 706 * 707 * <p>The method {@link #append(double, double)} is used.</p> 708 * 709 * @param lhs the left hand <code>double[]</code> 710 * @param rhs the right hand <code>double[]</code> 711 * @return EqualsBuilder - used to chain calls. 712 */ 713 public EqualsBuilder append(double[] lhs, double[] rhs) { 714 if (isEquals == false) { 715 return this; 716 } 717 if (lhs == rhs) { 718 return this; 719 } 720 if (lhs == null || rhs == null) { 721 this.setEquals(false); 722 return this; 723 } 724 if (lhs.length != rhs.length) { 725 this.setEquals(false); 726 return this; 727 } 728 for (int i = 0; i < lhs.length && isEquals; ++i) { 729 append(lhs[i], rhs[i]); 730 } 731 return this; 732 } 733 734 /** 735 * <p>Deep comparison of array of <code>float</code>. Length and all 736 * values are compared.</p> 737 * 738 * <p>The method {@link #append(float, float)} is used.</p> 739 * 740 * @param lhs the left hand <code>float[]</code> 741 * @param rhs the right hand <code>float[]</code> 742 * @return EqualsBuilder - used to chain calls. 743 */ 744 public EqualsBuilder append(float[] lhs, float[] rhs) { 745 if (isEquals == false) { 746 return this; 747 } 748 if (lhs == rhs) { 749 return this; 750 } 751 if (lhs == null || rhs == null) { 752 this.setEquals(false); 753 return this; 754 } 755 if (lhs.length != rhs.length) { 756 this.setEquals(false); 757 return this; 758 } 759 for (int i = 0; i < lhs.length && isEquals; ++i) { 760 append(lhs[i], rhs[i]); 761 } 762 return this; 763 } 764 765 /** 766 * <p>Deep comparison of array of <code>boolean</code>. Length and all 767 * values are compared.</p> 768 * 769 * <p>The method {@link #append(boolean, boolean)} is used.</p> 770 * 771 * @param lhs the left hand <code>boolean[]</code> 772 * @param rhs the right hand <code>boolean[]</code> 773 * @return EqualsBuilder - used to chain calls. 774 */ 775 public EqualsBuilder append(boolean[] lhs, boolean[] rhs) { 776 if (isEquals == false) { 777 return this; 778 } 779 if (lhs == rhs) { 780 return this; 781 } 782 if (lhs == null || rhs == null) { 783 this.setEquals(false); 784 return this; 785 } 786 if (lhs.length != rhs.length) { 787 this.setEquals(false); 788 return this; 789 } 790 for (int i = 0; i < lhs.length && isEquals; ++i) { 791 append(lhs[i], rhs[i]); 792 } 793 return this; 794 } 795 796 /** 797 * <p>Returns <code>true</code> if the fields that have been checked 798 * are all equal.</p> 799 * 800 * @return boolean 801 */ 802 public boolean isEquals() { 803 return this.isEquals; 804 } 805 806 /** 807 * Sets the <code>isEquals</code> value. 808 * 809 * @param isEquals The value to set. 810 * @since 2.1 811 */ 812 protected void setEquals(boolean isEquals) { 813 this.isEquals = isEquals; 814 } 815 } 816