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.ArrayList; 023import java.util.Collection; 024import java.util.HashSet; 025import java.util.List; 026import java.util.Set; 027 028import org.apache.commons.lang3.ArrayUtils; 029import org.apache.commons.lang3.ClassUtils; 030import org.apache.commons.lang3.tuple.Pair; 031 032/** 033 * <p>Assists in implementing {@link Object#equals(Object)} methods.</p> 034 * 035 * <p> This class provides methods to build a good equals method for any 036 * class. It follows rules laid out in 037 * <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a> 038 * , by Joshua Bloch. In particular the rule for comparing {@code doubles}, 039 * {@code floats}, and arrays can be tricky. Also, making sure that 040 * {@code equals()} and {@code hashCode()} are consistent can be 041 * difficult.</p> 042 * 043 * <p>Two Objects that compare as equals must generate the same hash code, 044 * but two Objects with the same hash code do not have to be equal.</p> 045 * 046 * <p>All relevant fields should be included in the calculation of equals. 047 * Derived fields may be ignored. In particular, any field used in 048 * generating a hash code must be used in the equals method, and vice 049 * versa.</p> 050 * 051 * <p>Typical use for the code is as follows:</p> 052 * <pre> 053 * public boolean equals(Object obj) { 054 * if (obj == null) { return false; } 055 * if (obj == this) { return true; } 056 * if (obj.getClass() != getClass()) { 057 * return false; 058 * } 059 * MyClass rhs = (MyClass) obj; 060 * return new EqualsBuilder() 061 * .appendSuper(super.equals(obj)) 062 * .append(field1, rhs.field1) 063 * .append(field2, rhs.field2) 064 * .append(field3, rhs.field3) 065 * .isEquals(); 066 * } 067 * </pre> 068 * 069 * <p> Alternatively, there is a method that uses reflection to determine 070 * the fields to test. Because these fields are usually private, the method, 071 * {@code reflectionEquals}, uses {@code AccessibleObject.setAccessible} to 072 * change the visibility of the fields. This will fail under a security 073 * manager, unless the appropriate permissions are set up correctly. It is 074 * also slower than testing explicitly. Non-primitive fields are compared using 075 * {@code equals()}.</p> 076 * 077 * <p> A typical invocation for this method would look like:</p> 078 * <pre> 079 * public boolean equals(Object obj) { 080 * return EqualsBuilder.reflectionEquals(this, obj); 081 * } 082 * </pre> 083 * 084 * <p>The {@link EqualsExclude} annotation can be used to exclude fields from being 085 * used by the {@code reflectionEquals} methods.</p> 086 * 087 * @since 1.0 088 */ 089public class EqualsBuilder implements Builder<Boolean> { 090 091 /** 092 * <p> 093 * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. 094 * </p> 095 * 096 * @since 3.0 097 */ 098 private static final ThreadLocal<Set<Pair<IDKey, IDKey>>> REGISTRY = new ThreadLocal<>(); 099 100 /* 101 * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode() 102 * we are in the process of calculating. 103 * 104 * So we generate a one-to-one mapping from the original object to a new object. 105 * 106 * Now HashSet uses equals() to determine if two elements with the same hash code really 107 * are equal, so we also need to ensure that the replacement objects are only equal 108 * if the original objects are identical. 109 * 110 * The original implementation (2.4 and before) used the System.identityHashCode() 111 * method - however this is not guaranteed to generate unique ids (e.g. LANG-459) 112 * 113 * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey) 114 * to disambiguate the duplicate ids. 115 */ 116 117 /** 118 * <p> 119 * Returns the registry of object pairs being traversed by the reflection 120 * methods in the current thread. 121 * </p> 122 * 123 * @return Set the registry of objects being traversed 124 * @since 3.0 125 */ 126 static Set<Pair<IDKey, IDKey>> getRegistry() { 127 return REGISTRY.get(); 128 } 129 130 /** 131 * <p> 132 * Converters value pair into a register pair. 133 * </p> 134 * 135 * @param lhs {@code this} object 136 * @param rhs the other object 137 * 138 * @return the pair 139 */ 140 static Pair<IDKey, IDKey> getRegisterPair(final Object lhs, final Object rhs) { 141 final IDKey left = new IDKey(lhs); 142 final IDKey right = new IDKey(rhs); 143 return Pair.of(left, right); 144 } 145 146 /** 147 * <p> 148 * Returns {@code true} if the registry contains the given object pair. 149 * Used by the reflection methods to avoid infinite loops. 150 * Objects might be swapped therefore a check is needed if the object pair 151 * is registered in given or swapped order. 152 * </p> 153 * 154 * @param lhs {@code this} object to lookup in registry 155 * @param rhs the other object to lookup on registry 156 * @return boolean {@code true} if the registry contains the given object. 157 * @since 3.0 158 */ 159 static boolean isRegistered(final Object lhs, final Object rhs) { 160 final Set<Pair<IDKey, IDKey>> registry = getRegistry(); 161 final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs); 162 final Pair<IDKey, IDKey> swappedPair = Pair.of(pair.getRight(), pair.getLeft()); 163 164 return registry != null 165 && (registry.contains(pair) || registry.contains(swappedPair)); 166 } 167 168 /** 169 * <p> 170 * Registers the given object pair. 171 * Used by the reflection methods to avoid infinite loops. 172 * </p> 173 * 174 * @param lhs {@code this} object to register 175 * @param rhs the other object to register 176 */ 177 private static void register(final Object lhs, final Object rhs) { 178 Set<Pair<IDKey, IDKey>> registry = getRegistry(); 179 if (registry == null) { 180 registry = new HashSet<>(); 181 REGISTRY.set(registry); 182 } 183 final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs); 184 registry.add(pair); 185 } 186 187 /** 188 * <p> 189 * Unregisters the given object pair. 190 * </p> 191 * 192 * <p> 193 * Used by the reflection methods to avoid infinite loops. 194 * 195 * @param lhs {@code this} object to unregister 196 * @param rhs the other object to unregister 197 * @since 3.0 198 */ 199 private static void unregister(final Object lhs, final Object rhs) { 200 final Set<Pair<IDKey, IDKey>> registry = getRegistry(); 201 if (registry != null) { 202 final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs); 203 registry.remove(pair); 204 if (registry.isEmpty()) { 205 REGISTRY.remove(); 206 } 207 } 208 } 209 210 /** 211 * If the fields tested are equals. 212 * The default value is {@code true}. 213 */ 214 private boolean isEquals = true; 215 216 private boolean testTransients; 217 private boolean testRecursive; 218 private List<Class<?>> bypassReflectionClasses; 219 private Class<?> reflectUpToClass; 220 private String[] excludeFields; 221 222 /** 223 * <p>Constructor for EqualsBuilder.</p> 224 * 225 * <p>Starts off assuming that equals is {@code true}.</p> 226 * @see Object#equals(Object) 227 */ 228 public EqualsBuilder() { 229 // set up default classes to bypass reflection for 230 bypassReflectionClasses = new ArrayList<>(); 231 bypassReflectionClasses.add(String.class); //hashCode field being lazy but not transient 232 } 233 234 //------------------------------------------------------------------------- 235 236 /** 237 * Set whether to include transient fields when reflectively comparing objects. 238 * @param testTransients whether to test transient fields 239 * @return EqualsBuilder - used to chain calls. 240 * @since 3.6 241 */ 242 public EqualsBuilder setTestTransients(final boolean testTransients) { 243 this.testTransients = testTransients; 244 return this; 245 } 246 247 /** 248 * Set whether to test fields recursively, instead of using their equals method, when reflectively comparing objects. 249 * String objects, which cache a hash value, are automatically excluded from recursive testing. 250 * You may specify other exceptions by calling {@link #setBypassReflectionClasses(List)}. 251 * @param testRecursive whether to do a recursive test 252 * @return EqualsBuilder - used to chain calls. 253 * @see #setBypassReflectionClasses(List) 254 * @since 3.6 255 */ 256 public EqualsBuilder setTestRecursive(final boolean testRecursive) { 257 this.testRecursive = testRecursive; 258 return this; 259 } 260 261 /** 262 * <p>Set {@code Class}es whose instances should be compared by calling their {@code equals} 263 * although being in recursive mode. So the fields of theses classes will not be compared recursively by reflection.</p> 264 * 265 * <p>Here you should name classes having non-transient fields which are cache fields being set lazily.<br> 266 * Prominent example being {@link String} class with its hash code cache field. Due to the importance 267 * of the {@code String} class, it is included in the default bypasses classes. Usually, if you use 268 * your own set of classes here, remember to include {@code String} class, too.</p> 269 * @param bypassReflectionClasses classes to bypass reflection test 270 * @return EqualsBuilder - used to chain calls. 271 * @see #setTestRecursive(boolean) 272 * @since 3.8 273 */ 274 public EqualsBuilder setBypassReflectionClasses(final List<Class<?>> bypassReflectionClasses) { 275 this.bypassReflectionClasses = bypassReflectionClasses; 276 return this; 277 } 278 279 /** 280 * Set the superclass to reflect up to at reflective tests. 281 * @param reflectUpToClass the super class to reflect up to 282 * @return EqualsBuilder - used to chain calls. 283 * @since 3.6 284 */ 285 public EqualsBuilder setReflectUpToClass(final Class<?> reflectUpToClass) { 286 this.reflectUpToClass = reflectUpToClass; 287 return this; 288 } 289 290 /** 291 * Set field names to be excluded by reflection tests. 292 * @param excludeFields the fields to exclude 293 * @return EqualsBuilder - used to chain calls. 294 * @since 3.6 295 */ 296 public EqualsBuilder setExcludeFields(final String... excludeFields) { 297 this.excludeFields = excludeFields; 298 return this; 299 } 300 301 302 /** 303 * <p>This method uses reflection to determine if the two {@code Object}s 304 * are equal.</p> 305 * 306 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 307 * fields. This means that it will throw a security exception if run under 308 * a security manager, if the permissions are not set up correctly. It is also 309 * not as efficient as testing explicitly. Non-primitive fields are compared using 310 * {@code equals()}.</p> 311 * 312 * <p>Transient members will be not be tested, as they are likely derived 313 * fields, and not part of the value of the Object.</p> 314 * 315 * <p>Static fields will not be tested. Superclass fields will be included.</p> 316 * 317 * @param lhs {@code this} object 318 * @param rhs the other object 319 * @param excludeFields Collection of String field names to exclude from testing 320 * @return {@code true} if the two Objects have tested equals. 321 * 322 * @see EqualsExclude 323 */ 324 public static boolean reflectionEquals(final Object lhs, final Object rhs, final Collection<String> excludeFields) { 325 return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields)); 326 } 327 328 /** 329 * <p>This method uses reflection to determine if the two {@code Object}s 330 * are equal.</p> 331 * 332 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 333 * fields. This means that it will throw a security exception if run under 334 * a security manager, if the permissions are not set up correctly. It is also 335 * not as efficient as testing explicitly. Non-primitive fields are compared using 336 * {@code equals()}.</p> 337 * 338 * <p>Transient members will be not be tested, as they are likely derived 339 * fields, and not part of the value of the Object.</p> 340 * 341 * <p>Static fields will not be tested. Superclass fields will be included.</p> 342 * 343 * @param lhs {@code this} object 344 * @param rhs the other object 345 * @param excludeFields array of field names to exclude from testing 346 * @return {@code true} if the two Objects have tested equals. 347 * 348 * @see EqualsExclude 349 */ 350 public static boolean reflectionEquals(final Object lhs, final Object rhs, final String... excludeFields) { 351 return reflectionEquals(lhs, rhs, false, null, excludeFields); 352 } 353 354 /** 355 * <p>This method uses reflection to determine if the two {@code Object}s 356 * are equal.</p> 357 * 358 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 359 * fields. This means that it will throw a security exception if run under 360 * a security manager, if the permissions are not set up correctly. It is also 361 * not as efficient as testing explicitly. Non-primitive fields are compared using 362 * {@code equals()}.</p> 363 * 364 * <p>If the TestTransients parameter is set to {@code true}, transient 365 * members will be tested, otherwise they are ignored, as they are likely 366 * derived fields, and not part of the value of the {@code Object}.</p> 367 * 368 * <p>Static fields will not be tested. Superclass fields will be included.</p> 369 * 370 * @param lhs {@code this} object 371 * @param rhs the other object 372 * @param testTransients whether to include transient fields 373 * @return {@code true} if the two Objects have tested equals. 374 * 375 * @see EqualsExclude 376 */ 377 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients) { 378 return reflectionEquals(lhs, rhs, testTransients, null); 379 } 380 381 /** 382 * <p>This method uses reflection to determine if the two {@code Object}s 383 * are equal.</p> 384 * 385 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 386 * fields. This means that it will throw a security exception if run under 387 * a security manager, if the permissions are not set up correctly. It is also 388 * not as efficient as testing explicitly. Non-primitive fields are compared using 389 * {@code equals()}.</p> 390 * 391 * <p>If the testTransients parameter is set to {@code true}, transient 392 * members will be tested, otherwise they are ignored, as they are likely 393 * derived fields, and not part of the value of the {@code Object}.</p> 394 * 395 * <p>Static fields will not be included. Superclass fields will be appended 396 * up to and including the specified superclass. A null superclass is treated 397 * as java.lang.Object.</p> 398 * 399 * @param lhs {@code this} object 400 * @param rhs the other object 401 * @param testTransients whether to include transient fields 402 * @param reflectUpToClass the superclass to reflect up to (inclusive), 403 * may be {@code null} 404 * @param excludeFields array of field names to exclude from testing 405 * @return {@code true} if the two Objects have tested equals. 406 * 407 * @see EqualsExclude 408 * @since 2.0 409 */ 410 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass, 411 final String... excludeFields) { 412 return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, false, excludeFields); 413 } 414 415 /** 416 * <p>This method uses reflection to determine if the two {@code Object}s 417 * are equal.</p> 418 * 419 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 420 * fields. This means that it will throw a security exception if run under 421 * a security manager, if the permissions are not set up correctly. It is also 422 * not as efficient as testing explicitly. Non-primitive fields are compared using 423 * {@code equals()}.</p> 424 * 425 * <p>If the testTransients parameter is set to {@code true}, transient 426 * members will be tested, otherwise they are ignored, as they are likely 427 * derived fields, and not part of the value of the {@code Object}.</p> 428 * 429 * <p>Static fields will not be included. Superclass fields will be appended 430 * up to and including the specified superclass. A null superclass is treated 431 * as java.lang.Object.</p> 432 * 433 * <p>If the testRecursive parameter is set to {@code true}, non primitive 434 * (and non primitive wrapper) field types will be compared by 435 * {@code EqualsBuilder} recursively instead of invoking their 436 * {@code equals()} method. Leading to a deep reflection equals test. 437 * 438 * @param lhs {@code this} object 439 * @param rhs the other object 440 * @param testTransients whether to include transient fields 441 * @param reflectUpToClass the superclass to reflect up to (inclusive), 442 * may be {@code null} 443 * @param testRecursive whether to call reflection equals on non primitive 444 * fields recursively. 445 * @param excludeFields array of field names to exclude from testing 446 * @return {@code true} if the two Objects have tested equals. 447 * 448 * @see EqualsExclude 449 * @since 3.6 450 */ 451 public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass, 452 final boolean testRecursive, final String... excludeFields) { 453 if (lhs == rhs) { 454 return true; 455 } 456 if (lhs == null || rhs == null) { 457 return false; 458 } 459 return new EqualsBuilder() 460 .setExcludeFields(excludeFields) 461 .setReflectUpToClass(reflectUpToClass) 462 .setTestTransients(testTransients) 463 .setTestRecursive(testRecursive) 464 .reflectionAppend(lhs, rhs) 465 .isEquals(); 466 } 467 468 /** 469 * <p>Tests if two {@code objects} by using reflection.</p> 470 * 471 * <p>It uses {@code AccessibleObject.setAccessible} to gain access to private 472 * fields. This means that it will throw a security exception if run under 473 * a security manager, if the permissions are not set up correctly. It is also 474 * not as efficient as testing explicitly. Non-primitive fields are compared using 475 * {@code equals()}.</p> 476 * 477 * <p>If the testTransients field is set to {@code true}, transient 478 * members will be tested, otherwise they are ignored, as they are likely 479 * derived fields, and not part of the value of the {@code Object}.</p> 480 * 481 * <p>Static fields will not be included. Superclass fields will be appended 482 * up to and including the specified superclass in field {@code reflectUpToClass}. 483 * A null superclass is treated as java.lang.Object.</p> 484 * 485 * <p>Field names listed in field {@code excludeFields} will be ignored.</p> 486 * 487 * <p>If either class of the compared objects is contained in 488 * {@code bypassReflectionClasses}, both objects are compared by calling 489 * the equals method of the left hand object with the right hand object as an argument.</p> 490 * 491 * @param lhs the left hand object 492 * @param rhs the left hand object 493 * @return EqualsBuilder - used to chain calls. 494 */ 495 public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) { 496 if (!isEquals) { 497 return this; 498 } 499 if (lhs == rhs) { 500 return this; 501 } 502 if (lhs == null || rhs == null) { 503 isEquals = false; 504 return this; 505 } 506 507 // Find the leaf class since there may be transients in the leaf 508 // class or in classes between the leaf and root. 509 // If we are not testing transients or a subclass has no ivars, 510 // then a subclass can test equals to a superclass. 511 final Class<?> lhsClass = lhs.getClass(); 512 final Class<?> rhsClass = rhs.getClass(); 513 Class<?> testClass; 514 if (lhsClass.isInstance(rhs)) { 515 testClass = lhsClass; 516 if (!rhsClass.isInstance(lhs)) { 517 // rhsClass is a subclass of lhsClass 518 testClass = rhsClass; 519 } 520 } else if (rhsClass.isInstance(lhs)) { 521 testClass = rhsClass; 522 if (!lhsClass.isInstance(rhs)) { 523 // lhsClass is a subclass of rhsClass 524 testClass = lhsClass; 525 } 526 } else { 527 // The two classes are not related. 528 isEquals = false; 529 return this; 530 } 531 532 try { 533 if (testClass.isArray()) { 534 append(lhs, rhs); 535 } else //If either class is being excluded, call normal object equals method on lhsClass. 536 if (bypassReflectionClasses != null 537 && (bypassReflectionClasses.contains(lhsClass) || bypassReflectionClasses.contains(rhsClass))) { 538 isEquals = lhs.equals(rhs); 539 } else { 540 reflectionAppend(lhs, rhs, testClass); 541 while (testClass.getSuperclass() != null && testClass != reflectUpToClass) { 542 testClass = testClass.getSuperclass(); 543 reflectionAppend(lhs, rhs, testClass); 544 } 545 } 546 } catch (final IllegalArgumentException e) { 547 // In this case, we tried to test a subclass vs. a superclass and 548 // the subclass has ivars or the ivars are transient and 549 // we are testing transients. 550 // If a subclass has ivars that we are trying to test them, we get an 551 // exception and we know that the objects are not equal. 552 isEquals = false; 553 } 554 return this; 555 } 556 557 /** 558 * <p>Appends the fields and values defined by the given object of the 559 * given Class.</p> 560 * 561 * @param lhs the left hand object 562 * @param rhs the right hand object 563 * @param clazz the class to append details of 564 */ 565 private void reflectionAppend( 566 final Object lhs, 567 final Object rhs, 568 final Class<?> clazz) { 569 570 if (isRegistered(lhs, rhs)) { 571 return; 572 } 573 574 try { 575 register(lhs, rhs); 576 final Field[] fields = clazz.getDeclaredFields(); 577 AccessibleObject.setAccessible(fields, true); 578 for (int i = 0; i < fields.length && isEquals; i++) { 579 final Field f = fields[i]; 580 if (!ArrayUtils.contains(excludeFields, f.getName()) 581 && !f.getName().contains("$") 582 && (testTransients || !Modifier.isTransient(f.getModifiers())) 583 && !Modifier.isStatic(f.getModifiers()) 584 && !f.isAnnotationPresent(EqualsExclude.class)) { 585 try { 586 append(f.get(lhs), f.get(rhs)); 587 } catch (final IllegalAccessException e) { 588 //this can't happen. Would get a Security exception instead 589 //throw a runtime exception in case the impossible happens. 590 throw new InternalError("Unexpected IllegalAccessException"); 591 } 592 } 593 } 594 } finally { 595 unregister(lhs, rhs); 596 } 597 } 598 599 //------------------------------------------------------------------------- 600 601 /** 602 * <p>Adds the result of {@code super.equals()} to this builder.</p> 603 * 604 * @param superEquals the result of calling {@code super.equals()} 605 * @return EqualsBuilder - used to chain calls. 606 * @since 2.0 607 */ 608 public EqualsBuilder appendSuper(final boolean superEquals) { 609 if (!isEquals) { 610 return this; 611 } 612 isEquals = superEquals; 613 return this; 614 } 615 616 //------------------------------------------------------------------------- 617 618 /** 619 * <p>Test if two {@code Object}s are equal using either 620 * #{@link #reflectionAppend(Object, Object)}, if object are non 621 * primitives (or wrapper of primitives) or if field {@code testRecursive} 622 * is set to {@code false}. Otherwise, using their 623 * {@code equals} method.</p> 624 * 625 * @param lhs the left hand object 626 * @param rhs the right hand object 627 * @return EqualsBuilder - used to chain calls. 628 */ 629 public EqualsBuilder append(final Object lhs, final Object rhs) { 630 if (!isEquals) { 631 return this; 632 } 633 if (lhs == rhs) { 634 return this; 635 } 636 if (lhs == null || rhs == null) { 637 this.setEquals(false); 638 return this; 639 } 640 final Class<?> lhsClass = lhs.getClass(); 641 if (lhsClass.isArray()) { 642 // factor out array case in order to keep method small enough 643 // to be inlined 644 appendArray(lhs, rhs); 645 } else // The simple case, not an array, just test the element 646 if (testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) { 647 reflectionAppend(lhs, rhs); 648 } else { 649 isEquals = lhs.equals(rhs); 650 } 651 return this; 652 } 653 654 /** 655 * <p>Test if an {@code Object} is equal to an array.</p> 656 * 657 * @param lhs the left hand object, an array 658 * @param rhs the right hand object 659 */ 660 private void appendArray(final Object lhs, final Object rhs) { 661 // First we compare different dimensions, for example: a boolean[][] to a boolean[] 662 // then we 'Switch' on type of array, to dispatch to the correct handler 663 // This handles multi dimensional arrays of the same depth 664 if (lhs.getClass() != rhs.getClass()) { 665 this.setEquals(false); 666 } else if (lhs instanceof long[]) { 667 append((long[]) lhs, (long[]) rhs); 668 } else if (lhs instanceof int[]) { 669 append((int[]) lhs, (int[]) rhs); 670 } else if (lhs instanceof short[]) { 671 append((short[]) lhs, (short[]) rhs); 672 } else if (lhs instanceof char[]) { 673 append((char[]) lhs, (char[]) rhs); 674 } else if (lhs instanceof byte[]) { 675 append((byte[]) lhs, (byte[]) rhs); 676 } else if (lhs instanceof double[]) { 677 append((double[]) lhs, (double[]) rhs); 678 } else if (lhs instanceof float[]) { 679 append((float[]) lhs, (float[]) rhs); 680 } else if (lhs instanceof boolean[]) { 681 append((boolean[]) lhs, (boolean[]) rhs); 682 } else { 683 // Not an array of primitives 684 append((Object[]) lhs, (Object[]) rhs); 685 } 686 } 687 688 /** 689 * <p> 690 * Test if two {@code long} s are equal. 691 * </p> 692 * 693 * @param lhs 694 * the left hand {@code long} 695 * @param rhs 696 * the right hand {@code long} 697 * @return EqualsBuilder - used to chain calls. 698 */ 699 public EqualsBuilder append(final long lhs, final long rhs) { 700 if (!isEquals) { 701 return this; 702 } 703 isEquals = lhs == rhs; 704 return this; 705 } 706 707 /** 708 * <p>Test if two {@code int}s are equal.</p> 709 * 710 * @param lhs the left hand {@code int} 711 * @param rhs the right hand {@code int} 712 * @return EqualsBuilder - used to chain calls. 713 */ 714 public EqualsBuilder append(final int lhs, final int rhs) { 715 if (!isEquals) { 716 return this; 717 } 718 isEquals = lhs == rhs; 719 return this; 720 } 721 722 /** 723 * <p>Test if two {@code short}s are equal.</p> 724 * 725 * @param lhs the left hand {@code short} 726 * @param rhs the right hand {@code short} 727 * @return EqualsBuilder - used to chain calls. 728 */ 729 public EqualsBuilder append(final short lhs, final short rhs) { 730 if (!isEquals) { 731 return this; 732 } 733 isEquals = lhs == rhs; 734 return this; 735 } 736 737 /** 738 * <p>Test if two {@code char}s are equal.</p> 739 * 740 * @param lhs the left hand {@code char} 741 * @param rhs the right hand {@code char} 742 * @return EqualsBuilder - used to chain calls. 743 */ 744 public EqualsBuilder append(final char lhs, final char rhs) { 745 if (!isEquals) { 746 return this; 747 } 748 isEquals = lhs == rhs; 749 return this; 750 } 751 752 /** 753 * <p>Test if two {@code byte}s are equal.</p> 754 * 755 * @param lhs the left hand {@code byte} 756 * @param rhs the right hand {@code byte} 757 * @return EqualsBuilder - used to chain calls. 758 */ 759 public EqualsBuilder append(final byte lhs, final byte rhs) { 760 if (!isEquals) { 761 return this; 762 } 763 isEquals = lhs == rhs; 764 return this; 765 } 766 767 /** 768 * <p>Test if two {@code double}s are equal by testing that the 769 * pattern of bits returned by {@code doubleToLong} are equal.</p> 770 * 771 * <p>This handles NaNs, Infinities, and {@code -0.0}.</p> 772 * 773 * <p>It is compatible with the hash code generated by 774 * {@code HashCodeBuilder}.</p> 775 * 776 * @param lhs the left hand {@code double} 777 * @param rhs the right hand {@code double} 778 * @return EqualsBuilder - used to chain calls. 779 */ 780 public EqualsBuilder append(final double lhs, final double rhs) { 781 if (!isEquals) { 782 return this; 783 } 784 return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs)); 785 } 786 787 /** 788 * <p>Test if two {@code float}s are equal by testing that the 789 * pattern of bits returned by doubleToLong are equal.</p> 790 * 791 * <p>This handles NaNs, Infinities, and {@code -0.0}.</p> 792 * 793 * <p>It is compatible with the hash code generated by 794 * {@code HashCodeBuilder}.</p> 795 * 796 * @param lhs the left hand {@code float} 797 * @param rhs the right hand {@code float} 798 * @return EqualsBuilder - used to chain calls. 799 */ 800 public EqualsBuilder append(final float lhs, final float rhs) { 801 if (!isEquals) { 802 return this; 803 } 804 return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs)); 805 } 806 807 /** 808 * <p>Test if two {@code booleans}s are equal.</p> 809 * 810 * @param lhs the left hand {@code boolean} 811 * @param rhs the right hand {@code boolean} 812 * @return EqualsBuilder - used to chain calls. 813 */ 814 public EqualsBuilder append(final boolean lhs, final boolean rhs) { 815 if (!isEquals) { 816 return this; 817 } 818 isEquals = lhs == rhs; 819 return this; 820 } 821 822 /** 823 * <p>Performs a deep comparison of two {@code Object} arrays.</p> 824 * 825 * <p>This also will be called for the top level of 826 * multi-dimensional, ragged, and multi-typed arrays.</p> 827 * 828 * <p>Note that this method does not compare the type of the arrays; it only 829 * compares the contents.</p> 830 * 831 * @param lhs the left hand {@code Object[]} 832 * @param rhs the right hand {@code Object[]} 833 * @return EqualsBuilder - used to chain calls. 834 */ 835 public EqualsBuilder append(final Object[] lhs, final Object[] rhs) { 836 if (!isEquals) { 837 return this; 838 } 839 if (lhs == rhs) { 840 return this; 841 } 842 if (lhs == null || rhs == null) { 843 this.setEquals(false); 844 return this; 845 } 846 if (lhs.length != rhs.length) { 847 this.setEquals(false); 848 return this; 849 } 850 for (int i = 0; i < lhs.length && isEquals; ++i) { 851 append(lhs[i], rhs[i]); 852 } 853 return this; 854 } 855 856 /** 857 * <p>Deep comparison of array of {@code long}. Length and all 858 * values are compared.</p> 859 * 860 * <p>The method {@link #append(long, long)} is used.</p> 861 * 862 * @param lhs the left hand {@code long[]} 863 * @param rhs the right hand {@code long[]} 864 * @return EqualsBuilder - used to chain calls. 865 */ 866 public EqualsBuilder append(final long[] lhs, final long[] rhs) { 867 if (!isEquals) { 868 return this; 869 } 870 if (lhs == rhs) { 871 return this; 872 } 873 if (lhs == null || rhs == null) { 874 this.setEquals(false); 875 return this; 876 } 877 if (lhs.length != rhs.length) { 878 this.setEquals(false); 879 return this; 880 } 881 for (int i = 0; i < lhs.length && isEquals; ++i) { 882 append(lhs[i], rhs[i]); 883 } 884 return this; 885 } 886 887 /** 888 * <p>Deep comparison of array of {@code int}. Length and all 889 * values are compared.</p> 890 * 891 * <p>The method {@link #append(int, int)} is used.</p> 892 * 893 * @param lhs the left hand {@code int[]} 894 * @param rhs the right hand {@code int[]} 895 * @return EqualsBuilder - used to chain calls. 896 */ 897 public EqualsBuilder append(final int[] lhs, final int[] rhs) { 898 if (!isEquals) { 899 return this; 900 } 901 if (lhs == rhs) { 902 return this; 903 } 904 if (lhs == null || rhs == null) { 905 this.setEquals(false); 906 return this; 907 } 908 if (lhs.length != rhs.length) { 909 this.setEquals(false); 910 return this; 911 } 912 for (int i = 0; i < lhs.length && isEquals; ++i) { 913 append(lhs[i], rhs[i]); 914 } 915 return this; 916 } 917 918 /** 919 * <p>Deep comparison of array of {@code short}. Length and all 920 * values are compared.</p> 921 * 922 * <p>The method {@link #append(short, short)} is used.</p> 923 * 924 * @param lhs the left hand {@code short[]} 925 * @param rhs the right hand {@code short[]} 926 * @return EqualsBuilder - used to chain calls. 927 */ 928 public EqualsBuilder append(final short[] lhs, final short[] rhs) { 929 if (!isEquals) { 930 return this; 931 } 932 if (lhs == rhs) { 933 return this; 934 } 935 if (lhs == null || rhs == null) { 936 this.setEquals(false); 937 return this; 938 } 939 if (lhs.length != rhs.length) { 940 this.setEquals(false); 941 return this; 942 } 943 for (int i = 0; i < lhs.length && isEquals; ++i) { 944 append(lhs[i], rhs[i]); 945 } 946 return this; 947 } 948 949 /** 950 * <p>Deep comparison of array of {@code char}. Length and all 951 * values are compared.</p> 952 * 953 * <p>The method {@link #append(char, char)} is used.</p> 954 * 955 * @param lhs the left hand {@code char[]} 956 * @param rhs the right hand {@code char[]} 957 * @return EqualsBuilder - used to chain calls. 958 */ 959 public EqualsBuilder append(final char[] lhs, final char[] rhs) { 960 if (!isEquals) { 961 return this; 962 } 963 if (lhs == rhs) { 964 return this; 965 } 966 if (lhs == null || rhs == null) { 967 this.setEquals(false); 968 return this; 969 } 970 if (lhs.length != rhs.length) { 971 this.setEquals(false); 972 return this; 973 } 974 for (int i = 0; i < lhs.length && isEquals; ++i) { 975 append(lhs[i], rhs[i]); 976 } 977 return this; 978 } 979 980 /** 981 * <p>Deep comparison of array of {@code byte}. Length and all 982 * values are compared.</p> 983 * 984 * <p>The method {@link #append(byte, byte)} is used.</p> 985 * 986 * @param lhs the left hand {@code byte[]} 987 * @param rhs the right hand {@code byte[]} 988 * @return EqualsBuilder - used to chain calls. 989 */ 990 public EqualsBuilder append(final byte[] lhs, final byte[] rhs) { 991 if (!isEquals) { 992 return this; 993 } 994 if (lhs == rhs) { 995 return this; 996 } 997 if (lhs == null || rhs == null) { 998 this.setEquals(false); 999 return this; 1000 } 1001 if (lhs.length != rhs.length) { 1002 this.setEquals(false); 1003 return this; 1004 } 1005 for (int i = 0; i < lhs.length && isEquals; ++i) { 1006 append(lhs[i], rhs[i]); 1007 } 1008 return this; 1009 } 1010 1011 /** 1012 * <p>Deep comparison of array of {@code double}. Length and all 1013 * values are compared.</p> 1014 * 1015 * <p>The method {@link #append(double, double)} is used.</p> 1016 * 1017 * @param lhs the left hand {@code double[]} 1018 * @param rhs the right hand {@code double[]} 1019 * @return EqualsBuilder - used to chain calls. 1020 */ 1021 public EqualsBuilder append(final double[] lhs, final double[] rhs) { 1022 if (!isEquals) { 1023 return this; 1024 } 1025 if (lhs == rhs) { 1026 return this; 1027 } 1028 if (lhs == null || rhs == null) { 1029 this.setEquals(false); 1030 return this; 1031 } 1032 if (lhs.length != rhs.length) { 1033 this.setEquals(false); 1034 return this; 1035 } 1036 for (int i = 0; i < lhs.length && isEquals; ++i) { 1037 append(lhs[i], rhs[i]); 1038 } 1039 return this; 1040 } 1041 1042 /** 1043 * <p>Deep comparison of array of {@code float}. Length and all 1044 * values are compared.</p> 1045 * 1046 * <p>The method {@link #append(float, float)} is used.</p> 1047 * 1048 * @param lhs the left hand {@code float[]} 1049 * @param rhs the right hand {@code float[]} 1050 * @return EqualsBuilder - used to chain calls. 1051 */ 1052 public EqualsBuilder append(final float[] lhs, final float[] rhs) { 1053 if (!isEquals) { 1054 return this; 1055 } 1056 if (lhs == rhs) { 1057 return this; 1058 } 1059 if (lhs == null || rhs == null) { 1060 this.setEquals(false); 1061 return this; 1062 } 1063 if (lhs.length != rhs.length) { 1064 this.setEquals(false); 1065 return this; 1066 } 1067 for (int i = 0; i < lhs.length && isEquals; ++i) { 1068 append(lhs[i], rhs[i]); 1069 } 1070 return this; 1071 } 1072 1073 /** 1074 * <p>Deep comparison of array of {@code boolean}. Length and all 1075 * values are compared.</p> 1076 * 1077 * <p>The method {@link #append(boolean, boolean)} is used.</p> 1078 * 1079 * @param lhs the left hand {@code boolean[]} 1080 * @param rhs the right hand {@code boolean[]} 1081 * @return EqualsBuilder - used to chain calls. 1082 */ 1083 public EqualsBuilder append(final boolean[] lhs, final boolean[] rhs) { 1084 if (!isEquals) { 1085 return this; 1086 } 1087 if (lhs == rhs) { 1088 return this; 1089 } 1090 if (lhs == null || rhs == null) { 1091 this.setEquals(false); 1092 return this; 1093 } 1094 if (lhs.length != rhs.length) { 1095 this.setEquals(false); 1096 return this; 1097 } 1098 for (int i = 0; i < lhs.length && isEquals; ++i) { 1099 append(lhs[i], rhs[i]); 1100 } 1101 return this; 1102 } 1103 1104 /** 1105 * <p>Returns {@code true} if the fields that have been checked 1106 * are all equal.</p> 1107 * 1108 * @return boolean 1109 */ 1110 public boolean isEquals() { 1111 return this.isEquals; 1112 } 1113 1114 /** 1115 * <p>Returns {@code true} if the fields that have been checked 1116 * are all equal.</p> 1117 * 1118 * @return {@code true} if all of the fields that have been checked 1119 * are equal, {@code false} otherwise. 1120 * 1121 * @since 3.0 1122 */ 1123 @Override 1124 public Boolean build() { 1125 return Boolean.valueOf(isEquals()); 1126 } 1127 1128 /** 1129 * Sets the {@code isEquals} value. 1130 * 1131 * @param isEquals The value to set. 1132 * @since 2.1 1133 */ 1134 protected void setEquals(final boolean isEquals) { 1135 this.isEquals = isEquals; 1136 } 1137 1138 /** 1139 * Reset the EqualsBuilder so you can use the same object again 1140 * @since 2.5 1141 */ 1142 public void reset() { 1143 this.isEquals = true; 1144 } 1145}