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 }