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