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