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    }