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    }