001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.ldap.util; 021 022 023 import java.lang.reflect.AccessibleObject; 024 import java.lang.reflect.Field; 025 import java.lang.reflect.Modifier; 026 027 import org.apache.directory.shared.i18n.I18n; 028 029 030 /** 031 * <p> 032 * Assists in implementing {@link Object#equals(Object)} methods. 033 * </p> 034 * <p> 035 * This class provides methods to build a good equals method for any class. It 036 * follows rules laid out in <a 037 * href="http://java.sun.com/docs/books/effective/index.html">Effective Java</a> , 038 * by Joshua Bloch. In particular the rule for comparing <code>doubles</code>, 039 * <code>floats</code>, and arrays can be tricky. Also, making sure that 040 * <code>equals()</code> and <code>hashCode()</code> are consistent can be 041 * difficult. 042 * </p> 043 * <p> 044 * Two Objects that compare as equals must generate the same hash code, but two 045 * Objects with the same hash code do not have to be equal. 046 * </p> 047 * <p> 048 * All relevant fields should be included in the calculation of equals. Derived 049 * fields may be ignored. In particular, any field used in generating a hash 050 * code must be used in the equals method, and vice versa. 051 * </p> 052 * <p> 053 * Typical use for the code is as follows: 054 * </p> 055 * 056 * <pre> 057 * public boolean equals( Object o ) 058 * { 059 * if ( !( o instanceof MyClass ) ) 060 * { 061 * return false; 062 * } 063 * MyClass rhs = ( MyClass ) o; 064 * return new EqualsBuilder().appendSuper( super.equals( o ) ).append( field1, rhs.field1 ) 065 * .append( field2, rhs.field2 ).append( field3, rhs.field3 ).isEquals(); 066 * } 067 * </pre> 068 * 069 * <p> 070 * Alternatively, there is a method that uses reflection to determine the fields 071 * to test. Because these fields are usually private, the method, 072 * <code>reflectionEquals</code>, uses 073 * <code>AccessibleObject.setAccessible</code> to change the visibility of the 074 * fields. This will fail under a security manager, unless the appropriate 075 * permissions are set up correctly. It is also slower than testing explicitly. 076 * </p> 077 * <p> 078 * A typical invocation for this method would look like: 079 * </p> 080 * 081 * <pre> 082 * public boolean equals( Object o ) 083 * { 084 * return EqualsBuilder.reflectionEquals( this, o ); 085 * } 086 * </pre> 087 * 088 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 089 */ 090 public class EqualsBuilder 091 { 092 093 /** 094 * If the fields tested are equals. The default value is <code>true</code>. 095 */ 096 private boolean isEquals = true; 097 098 099 /** 100 * <p> 101 * Constructor for EqualsBuilder. 102 * </p> 103 * <p> 104 * Starts off assuming that equals is <code>true</code>. 105 * </p> 106 * 107 * @see Object#equals(Object) 108 */ 109 public EqualsBuilder() 110 { 111 // do nothing for now. 112 } 113 114 115 // ------------------------------------------------------------------------- 116 117 /** 118 * <p> 119 * This method uses reflection to determine if the two <code>Object</code>s 120 * are equal. 121 * </p> 122 * <p> 123 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 124 * private fields. This means that it will throw a security exception if run 125 * under a security manager, if the permissions are not set up correctly. It 126 * is also not as efficient as testing explicitly. 127 * </p> 128 * <p> 129 * Transient members will be not be tested, as they are likely derived 130 * fields, and not part of the value of the Object. 131 * </p> 132 * <p> 133 * Static fields will not be tested. Superclass fields will be included. 134 * </p> 135 * 136 * @param lhs 137 * <code>this</code> object 138 * @param rhs 139 * the other object 140 * @return <code>true</code> if the two Objects have tested equals. 141 */ 142 public static boolean reflectionEquals( Object lhs, Object rhs ) 143 { 144 return reflectionEquals( lhs, rhs, false, null ); 145 } 146 147 148 /** 149 * <p> 150 * This method uses reflection to determine if the two <code>Object</code>s 151 * are equal. 152 * </p> 153 * <p> 154 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 155 * private fields. This means that it will throw a security exception if run 156 * under a security manager, if the permissions are not set up correctly. It 157 * is also not as efficient as testing explicitly. 158 * </p> 159 * <p> 160 * If the TestTransients parameter is set to <code>true</code>, transient 161 * members will be tested, otherwise they are ignored, as they are likely 162 * derived fields, and not part of the value of the <code>Object</code>. 163 * </p> 164 * <p> 165 * Static fields will not be tested. Superclass fields will be included. 166 * </p> 167 * 168 * @param lhs 169 * <code>this</code> object 170 * @param rhs 171 * the other object 172 * @param testTransients 173 * whether to include transient fields 174 * @return <code>true</code> if the two Objects have tested equals. 175 */ 176 public static boolean reflectionEquals( Object lhs, Object rhs, boolean testTransients ) 177 { 178 return reflectionEquals( lhs, rhs, testTransients, null ); 179 } 180 181 182 /** 183 * <p> 184 * This method uses reflection to determine if the two <code>Object</code>s 185 * are equal. 186 * </p> 187 * <p> 188 * It uses <code>AccessibleObject.setAccessible</code> to gain access to 189 * private fields. This means that it will throw a security exception if run 190 * under a security manager, if the permissions are not set up correctly. It 191 * is also not as efficient as testing explicitly. 192 * </p> 193 * <p> 194 * If the testTransients parameter is set to <code>true</code>, transient 195 * members will be tested, otherwise they are ignored, as they are likely 196 * derived fields, and not part of the value of the <code>Object</code>. 197 * </p> 198 * <p> 199 * Static fields will not be included. Superclass fields will be appended up 200 * to and including the specified superclass. A null superclass is treated 201 * as java.lang.Object. 202 * </p> 203 * 204 * @param lhs 205 * <code>this</code> object 206 * @param rhs 207 * the other object 208 * @param testTransients 209 * whether to include transient fields 210 * @param reflectUpToClass 211 * the superclass to reflect up to (inclusive), may be 212 * <code>null</code> 213 * @return <code>true</code> if the two Objects have tested equals. 214 * @since 2.0 215 */ 216 public static boolean reflectionEquals( Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass ) 217 { 218 if ( lhs == rhs ) 219 { 220 return true; 221 } 222 if ( lhs == null || rhs == null ) 223 { 224 return false; 225 } 226 // Find the leaf class since there may be transients in the leaf 227 // class or in classes between the leaf and root. 228 // If we are not testing transients or a subclass has no ivars, 229 // then a subclass can test equals to a superclass. 230 Class lhsClass = lhs.getClass(); 231 Class rhsClass = rhs.getClass(); 232 Class testClass; 233 if ( lhsClass.isInstance( rhs ) ) 234 { 235 testClass = lhsClass; 236 if ( !rhsClass.isInstance( lhs ) ) 237 { 238 // rhsClass is a subclass of lhsClass 239 testClass = rhsClass; 240 } 241 } 242 else if ( rhsClass.isInstance( lhs ) ) 243 { 244 testClass = rhsClass; 245 if ( !lhsClass.isInstance( rhs ) ) 246 { 247 // lhsClass is a subclass of rhsClass 248 testClass = lhsClass; 249 } 250 } 251 else 252 { 253 // The two classes are not related. 254 return false; 255 } 256 EqualsBuilder equalsBuilder = new EqualsBuilder(); 257 try 258 { 259 reflectionAppend( lhs, rhs, testClass, equalsBuilder, testTransients ); 260 while ( testClass.getSuperclass() != null && testClass != reflectUpToClass ) 261 { 262 testClass = testClass.getSuperclass(); 263 reflectionAppend( lhs, rhs, testClass, equalsBuilder, testTransients ); 264 } 265 } 266 catch ( IllegalArgumentException e ) 267 { 268 // In this case, we tried to test a subclass vs. a superclass and 269 // the subclass has ivars or the ivars are transient and 270 // we are testing transients. 271 // If a subclass has ivars that we are trying to test them, we get 272 // an 273 // exception and we know that the objects are not equal. 274 return false; 275 } 276 return equalsBuilder.isEquals(); 277 } 278 279 280 /** 281 * <p> 282 * Appends the fields and values defined by the given object of the given 283 * Class. 284 * </p> 285 * 286 * @param lhs 287 * the left hand object 288 * @param rhs 289 * the right hand object 290 * @param clazz 291 * the class to append details of 292 * @param builder 293 * the builder to append to 294 * @param useTransients 295 * whether to test transient fields 296 */ 297 private static void reflectionAppend( Object lhs, Object rhs, Class clazz, EqualsBuilder builder, 298 boolean useTransients ) 299 { 300 Field[] fields = clazz.getDeclaredFields(); 301 AccessibleObject.setAccessible( fields, true ); 302 for ( int i = 0; i < fields.length && builder.isEquals; i++ ) 303 { 304 Field f = fields[i]; 305 if ( ( f.getName().indexOf( '$' ) == -1 ) && ( useTransients || !Modifier.isTransient( f.getModifiers() ) ) 306 && ( !Modifier.isStatic( f.getModifiers() ) ) ) 307 { 308 try 309 { 310 builder.append( f.get( lhs ), f.get( rhs ) ); 311 } 312 catch ( IllegalAccessException e ) 313 { 314 // this can't happen. Would get a Security exception instead 315 // throw a runtime exception in case the impossible happens. 316 throw new InternalError( I18n.err( I18n.ERR_04355 ) ); 317 } 318 } 319 } 320 } 321 322 323 // ------------------------------------------------------------------------- 324 325 /** 326 * <p> 327 * Adds the result of <code>super.equals()</code> to this builder. 328 * </p> 329 * 330 * @param superEquals 331 * the result of calling <code>super.equals()</code> 332 * @return EqualsBuilder - used to chain calls. 333 * @since 2.0 334 */ 335 public EqualsBuilder appendSuper( boolean superEquals ) 336 { 337 if ( isEquals == false ) 338 { 339 return this; 340 } 341 isEquals = superEquals; 342 return this; 343 } 344 345 346 // ------------------------------------------------------------------------- 347 348 /** 349 * <p> 350 * Test if two <code>Object</code>s are equal using their 351 * <code>equals</code> method. 352 * </p> 353 * 354 * @param lhs 355 * the left hand object 356 * @param rhs 357 * the right hand object 358 * @return EqualsBuilder - used to chain calls. 359 */ 360 public EqualsBuilder append( Object lhs, Object rhs ) 361 { 362 if ( isEquals == false ) 363 { 364 return this; 365 } 366 if ( lhs == rhs ) 367 { 368 return this; 369 } 370 if ( lhs == null || rhs == null ) 371 { 372 this.setEquals( false ); 373 return this; 374 } 375 Class lhsClass = lhs.getClass(); 376 if ( !lhsClass.isArray() ) 377 { 378 // The simple case, not an array, just test the element 379 isEquals = lhs.equals( rhs ); 380 } 381 else if ( lhs.getClass() != rhs.getClass() ) 382 { 383 // Here when we compare different dimensions, for example: a 384 // boolean[][] to a boolean[] 385 this.setEquals( false ); 386 } 387 // 'Switch' on type of array, to dispatch to the correct handler 388 // This handles multi dimensional arrays of the same depth 389 else if ( lhs instanceof long[] ) 390 { 391 append( ( long[] ) lhs, ( long[] ) rhs ); 392 } 393 else if ( lhs instanceof int[] ) 394 { 395 append( ( int[] ) lhs, ( int[] ) rhs ); 396 } 397 else if ( lhs instanceof short[] ) 398 { 399 append( ( short[] ) lhs, ( short[] ) rhs ); 400 } 401 else if ( lhs instanceof char[] ) 402 { 403 append( ( char[] ) lhs, ( char[] ) rhs ); 404 } 405 else if ( lhs instanceof byte[] ) 406 { 407 append( ( byte[] ) lhs, ( byte[] ) rhs ); 408 } 409 else if ( lhs instanceof double[] ) 410 { 411 append( ( double[] ) lhs, ( double[] ) rhs ); 412 } 413 else if ( lhs instanceof float[] ) 414 { 415 append( ( float[] ) lhs, ( float[] ) rhs ); 416 } 417 else if ( lhs instanceof boolean[] ) 418 { 419 append( ( boolean[] ) lhs, ( boolean[] ) rhs ); 420 } 421 else 422 { 423 // Not an array of primitives 424 append( ( Object[] ) lhs, ( Object[] ) rhs ); 425 } 426 return this; 427 } 428 429 430 /** 431 * <p> 432 * Test if two <code>long</code> s are equal. 433 * </p> 434 * 435 * @param lhs 436 * the left hand <code>long</code> 437 * @param rhs 438 * the right hand <code>long</code> 439 * @return EqualsBuilder - used to chain calls. 440 */ 441 public EqualsBuilder append( long lhs, long rhs ) 442 { 443 if ( isEquals == false ) 444 { 445 return this; 446 } 447 isEquals = ( lhs == rhs ); 448 return this; 449 } 450 451 452 /** 453 * <p> 454 * Test if two <code>int</code>s are equal. 455 * </p> 456 * 457 * @param lhs 458 * the left hand <code>int</code> 459 * @param rhs 460 * the right hand <code>int</code> 461 * @return EqualsBuilder - used to chain calls. 462 */ 463 public EqualsBuilder append( int lhs, int rhs ) 464 { 465 if ( isEquals == false ) 466 { 467 return this; 468 } 469 isEquals = ( lhs == rhs ); 470 return this; 471 } 472 473 474 /** 475 * <p> 476 * Test if two <code>short</code>s are equal. 477 * </p> 478 * 479 * @param lhs 480 * the left hand <code>short</code> 481 * @param rhs 482 * the right hand <code>short</code> 483 * @return EqualsBuilder - used to chain calls. 484 */ 485 public EqualsBuilder append( short lhs, short rhs ) 486 { 487 if ( isEquals == false ) 488 { 489 return this; 490 } 491 isEquals = ( lhs == rhs ); 492 return this; 493 } 494 495 496 /** 497 * <p> 498 * Test if two <code>char</code>s are equal. 499 * </p> 500 * 501 * @param lhs 502 * the left hand <code>char</code> 503 * @param rhs 504 * the right hand <code>char</code> 505 * @return EqualsBuilder - used to chain calls. 506 */ 507 public EqualsBuilder append( char lhs, char rhs ) 508 { 509 if ( isEquals == false ) 510 { 511 return this; 512 } 513 isEquals = ( lhs == rhs ); 514 return this; 515 } 516 517 518 /** 519 * <p> 520 * Test if two <code>byte</code>s are equal. 521 * </p> 522 * 523 * @param lhs 524 * the left hand <code>byte</code> 525 * @param rhs 526 * the right hand <code>byte</code> 527 * @return EqualsBuilder - used to chain calls. 528 */ 529 public EqualsBuilder append( byte lhs, byte rhs ) 530 { 531 if ( isEquals == false ) 532 { 533 return this; 534 } 535 isEquals = ( lhs == rhs ); 536 return this; 537 } 538 539 540 /** 541 * <p> 542 * Test if two <code>double</code>s are equal by testing that the pattern 543 * of bits returned by <code>doubleToLong</code> are equal. 544 * </p> 545 * <p> 546 * This handles NaNs, Infinities, and <code>-0.0</code>. 547 * </p> 548 * <p> 549 * It is compatible with the hash code generated by 550 * <code>HashCodeBuilder</code>. 551 * </p> 552 * 553 * @param lhs 554 * the left hand <code>double</code> 555 * @param rhs 556 * the right hand <code>double</code> 557 * @return EqualsBuilder - used to chain calls. 558 */ 559 public EqualsBuilder append( double lhs, double rhs ) 560 { 561 if ( isEquals == false ) 562 { 563 return this; 564 } 565 return append( Double.doubleToLongBits( lhs ), Double.doubleToLongBits( rhs ) ); 566 } 567 568 569 /** 570 * <p> 571 * Test if two <code>float</code>s are equal byt testing that the pattern 572 * of bits returned by doubleToLong are equal. 573 * </p> 574 * <p> 575 * This handles NaNs, Infinities, and <code>-0.0</code>. 576 * </p> 577 * <p> 578 * It is compatible with the hash code generated by 579 * <code>HashCodeBuilder</code>. 580 * </p> 581 * 582 * @param lhs 583 * the left hand <code>float</code> 584 * @param rhs 585 * the right hand <code>float</code> 586 * @return EqualsBuilder - used to chain calls. 587 */ 588 public EqualsBuilder append( float lhs, float rhs ) 589 { 590 if ( isEquals == false ) 591 { 592 return this; 593 } 594 return append( Float.floatToIntBits( lhs ), Float.floatToIntBits( rhs ) ); 595 } 596 597 598 /** 599 * <p> 600 * Test if two <code>booleans</code>s are equal. 601 * </p> 602 * 603 * @param lhs 604 * the left hand <code>boolean</code> 605 * @param rhs 606 * the right hand <code>boolean</code> 607 * @return EqualsBuilder - used to chain calls. 608 */ 609 public EqualsBuilder append( boolean lhs, boolean rhs ) 610 { 611 if ( isEquals == false ) 612 { 613 return this; 614 } 615 isEquals = ( lhs == rhs ); 616 return this; 617 } 618 619 620 /** 621 * <p> 622 * Performs a deep comparison of two <code>Object</code> arrays. 623 * </p> 624 * <p> 625 * This also will be called for the top level of multi-dimensional, ragged, 626 * and multi-typed arrays. 627 * </p> 628 * 629 * @param lhs 630 * the left hand <code>Object[]</code> 631 * @param rhs 632 * the right hand <code>Object[]</code> 633 * @return EqualsBuilder - used to chain calls. 634 */ 635 public EqualsBuilder append( Object[] lhs, Object[] rhs ) 636 { 637 if ( isEquals == false ) 638 { 639 return this; 640 } 641 if ( lhs == rhs ) 642 { 643 return this; 644 } 645 if ( lhs == null || rhs == null ) 646 { 647 this.setEquals( false ); 648 return this; 649 } 650 if ( lhs.length != rhs.length ) 651 { 652 this.setEquals( false ); 653 return this; 654 } 655 for ( int i = 0; i < lhs.length && isEquals; ++i ) 656 { 657 append( lhs[i], rhs[i] ); 658 } 659 return this; 660 } 661 662 663 /** 664 * <p> 665 * Deep comparison of array of <code>long</code>. Length and all values 666 * are compared. 667 * </p> 668 * <p> 669 * The method {@link #append(long, long)} is used. 670 * </p> 671 * 672 * @param lhs 673 * the left hand <code>long[]</code> 674 * @param rhs 675 * the right hand <code>long[]</code> 676 * @return EqualsBuilder - used to chain calls. 677 */ 678 public EqualsBuilder append( long[] lhs, long[] rhs ) 679 { 680 if ( isEquals == false ) 681 { 682 return this; 683 } 684 if ( lhs == rhs ) 685 { 686 return this; 687 } 688 if ( lhs == null || rhs == null ) 689 { 690 this.setEquals( false ); 691 return this; 692 } 693 if ( lhs.length != rhs.length ) 694 { 695 this.setEquals( false ); 696 return this; 697 } 698 for ( int i = 0; i < lhs.length && isEquals; ++i ) 699 { 700 append( lhs[i], rhs[i] ); 701 } 702 return this; 703 } 704 705 706 /** 707 * <p> 708 * Deep comparison of array of <code>int</code>. Length and all values 709 * are compared. 710 * </p> 711 * <p> 712 * The method {@link #append(int, int)} is used. 713 * </p> 714 * 715 * @param lhs 716 * the left hand <code>int[]</code> 717 * @param rhs 718 * the right hand <code>int[]</code> 719 * @return EqualsBuilder - used to chain calls. 720 */ 721 public EqualsBuilder append( int[] lhs, int[] rhs ) 722 { 723 if ( isEquals == false ) 724 { 725 return this; 726 } 727 if ( lhs == rhs ) 728 { 729 return this; 730 } 731 if ( lhs == null || rhs == null ) 732 { 733 this.setEquals( false ); 734 return this; 735 } 736 if ( lhs.length != rhs.length ) 737 { 738 this.setEquals( false ); 739 return this; 740 } 741 for ( int i = 0; i < lhs.length && isEquals; ++i ) 742 { 743 append( lhs[i], rhs[i] ); 744 } 745 return this; 746 } 747 748 749 /** 750 * <p> 751 * Deep comparison of array of <code>short</code>. Length and all values 752 * are compared. 753 * </p> 754 * <p> 755 * The method {@link #append(short, short)} is used. 756 * </p> 757 * 758 * @param lhs 759 * the left hand <code>short[]</code> 760 * @param rhs 761 * the right hand <code>short[]</code> 762 * @return EqualsBuilder - used to chain calls. 763 */ 764 public EqualsBuilder append( short[] lhs, short[] rhs ) 765 { 766 if ( isEquals == false ) 767 { 768 return this; 769 } 770 if ( lhs == rhs ) 771 { 772 return this; 773 } 774 if ( lhs == null || rhs == null ) 775 { 776 this.setEquals( false ); 777 return this; 778 } 779 if ( lhs.length != rhs.length ) 780 { 781 this.setEquals( false ); 782 return this; 783 } 784 for ( int i = 0; i < lhs.length && isEquals; ++i ) 785 { 786 append( lhs[i], rhs[i] ); 787 } 788 return this; 789 } 790 791 792 /** 793 * <p> 794 * Deep comparison of array of <code>char</code>. Length and all values 795 * are compared. 796 * </p> 797 * <p> 798 * The method {@link #append(char, char)} is used. 799 * </p> 800 * 801 * @param lhs 802 * the left hand <code>char[]</code> 803 * @param rhs 804 * the right hand <code>char[]</code> 805 * @return EqualsBuilder - used to chain calls. 806 */ 807 public EqualsBuilder append( char[] lhs, char[] rhs ) 808 { 809 if ( isEquals == false ) 810 { 811 return this; 812 } 813 if ( lhs == rhs ) 814 { 815 return this; 816 } 817 if ( lhs == null || rhs == null ) 818 { 819 this.setEquals( false ); 820 return this; 821 } 822 if ( lhs.length != rhs.length ) 823 { 824 this.setEquals( false ); 825 return this; 826 } 827 for ( int i = 0; i < lhs.length && isEquals; ++i ) 828 { 829 append( lhs[i], rhs[i] ); 830 } 831 return this; 832 } 833 834 835 /** 836 * <p> 837 * Deep comparison of array of <code>byte</code>. Length and all values 838 * are compared. 839 * </p> 840 * <p> 841 * The method {@link #append(byte, byte)} is used. 842 * </p> 843 * 844 * @param lhs 845 * the left hand <code>byte[]</code> 846 * @param rhs 847 * the right hand <code>byte[]</code> 848 * @return EqualsBuilder - used to chain calls. 849 */ 850 public EqualsBuilder append( byte[] lhs, byte[] rhs ) 851 { 852 if ( isEquals == false ) 853 { 854 return this; 855 } 856 if ( lhs == rhs ) 857 { 858 return this; 859 } 860 if ( lhs == null || rhs == null ) 861 { 862 this.setEquals( false ); 863 return this; 864 } 865 if ( lhs.length != rhs.length ) 866 { 867 this.setEquals( false ); 868 return this; 869 } 870 for ( int i = 0; i < lhs.length && isEquals; ++i ) 871 { 872 append( lhs[i], rhs[i] ); 873 } 874 return this; 875 } 876 877 878 /** 879 * <p> 880 * Deep comparison of array of <code>double</code>. Length and all values 881 * are compared. 882 * </p> 883 * <p> 884 * The method {@link #append(double, double)} is used. 885 * </p> 886 * 887 * @param lhs 888 * the left hand <code>double[]</code> 889 * @param rhs 890 * the right hand <code>double[]</code> 891 * @return EqualsBuilder - used to chain calls. 892 */ 893 public EqualsBuilder append( double[] lhs, double[] rhs ) 894 { 895 if ( isEquals == false ) 896 { 897 return this; 898 } 899 if ( lhs == rhs ) 900 { 901 return this; 902 } 903 if ( lhs == null || rhs == null ) 904 { 905 this.setEquals( false ); 906 return this; 907 } 908 if ( lhs.length != rhs.length ) 909 { 910 this.setEquals( false ); 911 return this; 912 } 913 for ( int i = 0; i < lhs.length && isEquals; ++i ) 914 { 915 append( lhs[i], rhs[i] ); 916 } 917 return this; 918 } 919 920 921 /** 922 * <p> 923 * Deep comparison of array of <code>float</code>. Length and all values 924 * are compared. 925 * </p> 926 * <p> 927 * The method {@link #append(float, float)} is used. 928 * </p> 929 * 930 * @param lhs 931 * the left hand <code>float[]</code> 932 * @param rhs 933 * the right hand <code>float[]</code> 934 * @return EqualsBuilder - used to chain calls. 935 */ 936 public EqualsBuilder append( float[] lhs, float[] rhs ) 937 { 938 if ( isEquals == false ) 939 { 940 return this; 941 } 942 if ( lhs == rhs ) 943 { 944 return this; 945 } 946 if ( lhs == null || rhs == null ) 947 { 948 this.setEquals( false ); 949 return this; 950 } 951 if ( lhs.length != rhs.length ) 952 { 953 this.setEquals( false ); 954 return this; 955 } 956 for ( int i = 0; i < lhs.length && isEquals; ++i ) 957 { 958 append( lhs[i], rhs[i] ); 959 } 960 return this; 961 } 962 963 964 /** 965 * <p> 966 * Deep comparison of array of <code>boolean</code>. Length and all 967 * values are compared. 968 * </p> 969 * <p> 970 * The method {@link #append(boolean, boolean)} is used. 971 * </p> 972 * 973 * @param lhs 974 * the left hand <code>boolean[]</code> 975 * @param rhs 976 * the right hand <code>boolean[]</code> 977 * @return EqualsBuilder - used to chain calls. 978 */ 979 public EqualsBuilder append( boolean[] lhs, boolean[] rhs ) 980 { 981 if ( isEquals == false ) 982 { 983 return this; 984 } 985 if ( lhs == rhs ) 986 { 987 return this; 988 } 989 if ( lhs == null || rhs == null ) 990 { 991 this.setEquals( false ); 992 return this; 993 } 994 if ( lhs.length != rhs.length ) 995 { 996 this.setEquals( false ); 997 return this; 998 } 999 for ( int i = 0; i < lhs.length && isEquals; ++i ) 1000 { 1001 append( lhs[i], rhs[i] ); 1002 } 1003 return this; 1004 } 1005 1006 1007 /** 1008 * <p> 1009 * Returns <code>true</code> if the fields that have been checked are all 1010 * equal. 1011 * </p> 1012 * 1013 * @return boolean 1014 */ 1015 public boolean isEquals() 1016 { 1017 return this.isEquals; 1018 } 1019 1020 1021 /** 1022 * Sets the <code>isEquals</code> value. 1023 * 1024 * @param isEquals 1025 * The value to set. 1026 */ 1027 protected void setEquals( boolean isEquals ) 1028 { 1029 this.isEquals = isEquals; 1030 } 1031 }