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