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