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 *      https://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 */
017package org.apache.commons.lang3.builder;
018
019import java.lang.reflect.Field;
020import java.lang.reflect.Modifier;
021import java.util.ArrayList;
022import java.util.Collection;
023import java.util.HashSet;
024import java.util.List;
025import java.util.Set;
026
027import org.apache.commons.lang3.ArrayUtils;
028import org.apache.commons.lang3.ClassUtils;
029import org.apache.commons.lang3.tuple.Pair;
030
031/**
032 * Assists in implementing {@link Object#equals(Object)} methods.
033 *
034 * <p>
035 * This class provides methods to build a good equals method for any
036 * class. It follows rules laid out in
037 * <a href="https://www.oracle.com/java/technologies/effectivejava.html">Effective Java</a>
038 * , by Joshua Bloch. In particular the rule for comparing {@code doubles},
039 * {@code floats}, and arrays can be tricky. Also, making sure that
040 * {@code equals()} and {@code hashCode()} are consistent can be
041 * difficult.
042 * </p>
043 *
044 * <p>
045 * Two Objects that compare as equals must generate the same hash code,
046 * but two Objects with the same hash code do not have to be equal.
047 * </p>
048 *
049 * <p>
050 * All relevant fields should be included in the calculation of equals.
051 * Derived fields may be ignored. In particular, any field used in
052 * generating a hash code must be used in the equals method, and vice
053 * versa.
054 * </p>
055 *
056 * <p>
057 * Typical use for the code is as follows:
058 * </p>
059 * <pre>
060 * public boolean equals(Object obj) {
061 *   if (obj == null) { return false; }
062 *   if (obj == this) { return true; }
063 *   if (obj.getClass() != getClass()) {
064 *     return false;
065 *   }
066 *   MyClass rhs = (MyClass) obj;
067 *   return new EqualsBuilder()
068 *                 .append(field1, rhs.field1)
069 *                 .append(field2, rhs.field2)
070 *                 .append(field3, rhs.field3)
071 *                 .isEquals();
072 *  }
073 * </pre>
074 *
075 * <p>
076 * To include the superclass's equality check, add {@code appendSuper(super.equals(obj))} to the builder chain.
077 * Omit this call if {@code super.equals(obj)} invokes {@link Object#equals(Object)}: its identity comparison makes distinct instances compare unequal,
078 * even when all their fields are equal. See {@link #appendSuper(boolean)} for details.
079 * </p>
080 * <p>
081 * Alternatively, there is a method that uses reflection to determine
082 * the fields to test. Because these fields are usually private, the method,
083 * {@code reflectionEquals}, uses {@code AccessibleObject.setAccessible} to
084 * change the visibility of the fields. This will fail under a security
085 * manager, unless the appropriate permissions are set up correctly. It is
086 * also slower than testing explicitly.  Non-primitive fields are compared using
087 * {@code equals()}.
088 * </p>
089 * <p>
090 * See also {@link AbstractBuilder#setForceAccessible(boolean)}
091 * </p>
092 *
093 * <p>
094 * A typical invocation for this method would look like:
095 * </p>
096 * <pre>
097 * public boolean equals(Object obj) {
098 *   return EqualsBuilder.reflectionEquals(this, obj);
099 * }
100 * </pre>
101 *
102 * <p>
103 * The {@link EqualsExclude} annotation can be used to exclude fields from being
104 * used by the {@code reflectionEquals} methods.
105 * </p>
106 *
107 * @since 1.0
108 * @see AbstractBuilder#setForceAccessible(boolean)
109 */
110public class EqualsBuilder extends AbstractReflection implements Builder<Boolean> {
111
112    /**
113     * Builds instances of CompareToBuilder.
114     */
115    public static class Builder extends AbstractBuilder<Builder> {
116
117        /**
118         * Constructs a new Builder instance.
119         */
120        private Builder() {
121            // empty
122        }
123
124        @Override
125        public EqualsBuilder get() {
126            return new EqualsBuilder(this);
127        }
128
129    }
130
131    /**
132     * A registry of objects to detect cyclical object references, avoid infinite loops, and stack overflows.
133     */
134    private static final ThreadLocal<Set<Pair<IDKey, IDKey>>> REGISTRY = ThreadLocal.withInitial(HashSet::new);
135
136    /**
137     * Constructs a new Builder.
138     *
139     * @return A new Builder.
140     */
141    public static Builder builder() {
142        return new Builder();
143    }
144
145    /*
146     * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
147     * we are in the process of calculating.
148     *
149     * So we generate a one-to-one mapping from the original object to a new object.
150     *
151     * Now HashSet uses equals() to determine if two elements with the same hash code really
152     * are equal, so we also need to ensure that the replacement objects are only equal
153     * if the original objects are identical.
154     *
155     * The original implementation (2.4 and before) used the System.identityHashCode()
156     * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
157     *
158     * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
159     * to disambiguate the duplicate ids.
160     */
161
162    /**
163     * Gets the registry of object pairs being traversed by the reflection
164     * methods in the current thread.
165     *
166     * @return Set the registry of objects being traversed
167     */
168    static Set<Pair<IDKey, IDKey>> getRegistry() {
169        return REGISTRY.get();
170    }
171
172    /**
173     * Tests whether the registry contains the given object pair.
174     * <p>
175     * Used by the reflection methods to avoid infinite loops.
176     * Objects might be swapped therefore a check is needed if the object pair
177     * is registered in the given or swapped order.
178     * </p>
179     *
180     * @param lhs {@code this} object to lookup in registry
181     * @param rhs The other object to lookup on registry
182     * @return boolean {@code true} if the registry contains the given object.
183     */
184    static boolean isRegistered(final Object lhs, final Object rhs) {
185        return isRegistered(lhs, rhs, getRegistry());
186    }
187
188    /**
189     * Uses reflection to determine if the two {@link Object}s
190     * are equal.
191     *
192     * <p>
193     * It uses {@code AccessibleObject.setAccessible} to gain access to private
194     * fields. This means that it will throw a security exception if run under
195     * a security manager, if the permissions are not set up correctly. It is also
196     * not as efficient as testing explicitly. Non-primitive fields are compared using
197     * {@code equals()}.
198     * </p>
199     *
200     * <p>
201     * If the TestTransients parameter is set to {@code true}, transient
202     * members will be tested, otherwise they are ignored, as they are likely
203     * derived fields, and not part of the value of the {@link Object}.
204     * </p>
205     *
206     * <p>
207     * Static fields will not be tested. Superclass fields will be included.
208     * </p>
209     *
210     * @param lhs  {@code this} object
211     * @param rhs  The other object
212     * @param testTransients  whether to include transient fields
213     * @return {@code true} if the two Objects have tested equals.
214     * @see EqualsExclude
215     */
216    public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients) {
217        return reflectionEquals(lhs, rhs, testTransients, null);
218    }
219
220    /**
221     * Uses reflection to determine if the two {@link Object}s
222     * are equal.
223     *
224     * <p>
225     * It uses {@code AccessibleObject.setAccessible} to gain access to private
226     * fields. This means that it will throw a security exception if run under
227     * a security manager, if the permissions are not set up correctly. It is also
228     * not as efficient as testing explicitly. Non-primitive fields are compared using
229     * {@code equals()}.
230     * </p>
231     *
232     * <p>
233     * If the testTransients parameter is set to {@code true}, transient
234     * members will be tested, otherwise they are ignored, as they are likely
235     * derived fields, and not part of the value of the {@link Object}.
236     * </p>
237     *
238     * <p>
239     * 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.
242     * </p>
243     *
244     * <p>
245     * If the testRecursive parameter is set to {@code true}, non primitive
246     * (and non primitive wrapper) field types will be compared by
247     * {@link EqualsBuilder} recursively instead of invoking their
248     * {@code equals()} method. Leading to a deep reflection equals test.
249     *
250     * <p>
251     * Note on graph shape: the internal registry that prevents infinite recursion on
252     * cyclic object graphs is a visit stack, not a visited set - object pairs reachable
253     * more than once through shared (acyclic) references are re-compared on every path.
254     * On deeply nested graphs with many shared references (reference "diamonds"), the
255     * comparison cost can grow exponentially with nesting depth. Do not use recursive
256     * reflection equality on object graphs built from untrusted input (for example,
257     * graphs materialized by an identity-preserving deserializer).
258     * </p>
259     *
260     * @param lhs  {@code this} object
261     * @param rhs  The other object
262     * @param testTransients  whether to include transient fields
263     * @param reflectUpToClass  The superclass to reflect up to (inclusive),
264     *  may be {@code null}
265     * @param testRecursive  whether to call reflection equals on non-primitive
266     *  fields recursively.
267     * @param excludeFields  array of field names to exclude from testing
268     * @return {@code true} if the two Objects have tested equals.
269     * @see EqualsExclude
270     * @since 3.6
271     */
272    public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass,
273            final boolean testRecursive, final String... excludeFields) {
274        if (lhs == rhs) {
275            return true;
276        }
277        if (lhs == null || rhs == null) {
278            return false;
279        }
280        // @formatter:off
281        return new EqualsBuilder()
282            .setExcludeFields(excludeFields)
283            .setReflectUpToClass(reflectUpToClass)
284            .setTestTransients(testTransients)
285            .setTestRecursive(testRecursive)
286            .reflectionAppend(lhs, rhs)
287            .isEquals();
288        // @formatter:on
289    }
290
291    /**
292     * Uses reflection to determine if the two {@link Object}s
293     * are equal.
294     *
295     * <p>
296     * It uses {@code AccessibleObject.setAccessible} to gain access to private
297     * fields. This means that it will throw a security exception if run under
298     * a security manager, if the permissions are not set up correctly. It is also
299     * not as efficient as testing explicitly. Non-primitive fields are compared using
300     * {@code equals()}.
301     * </p>
302     *
303     * <p>
304     * If the testTransients parameter is set to {@code true}, transient
305     * members will be tested, otherwise they are ignored, as they are likely
306     * derived fields, and not part of the value of the {@link Object}.
307     * </p>
308     *
309     * <p>
310     * Static fields will not be included. Superclass fields will be appended
311     * up to and including the specified superclass. A null superclass is treated
312     * as java.lang.Object.
313     * </p>
314     *
315     * @param lhs  {@code this} object
316     * @param rhs  The other object
317     * @param testTransients  whether to include transient fields
318     * @param reflectUpToClass  The superclass to reflect up to (inclusive),
319     *  may be {@code null}
320     * @param excludeFields  array of field names to exclude from testing
321     * @return {@code true} if the two Objects have tested equals.
322     * @see EqualsExclude
323     * @since 2.0
324     */
325    public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass,
326            final String... excludeFields) {
327        return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, false, excludeFields);
328    }
329
330    /**
331     * Uses reflection to determine if the two {@link Object}s
332     * are equal.
333     *
334     * <p>
335     * It uses {@code AccessibleObject.setAccessible} to gain access to private
336     * fields. This means that it will throw a security exception if run under
337     * a security manager, if the permissions are not set up correctly. It is also
338     * not as efficient as testing explicitly. Non-primitive fields are compared using
339     * {@code equals()}.
340     * </p>
341     *
342     * <p>
343     * Transient members will be not be tested, as they are likely derived
344     * fields, and not part of the value of the Object.
345     * </p>
346     *
347     * <p>
348     * Static fields will not be tested. Superclass fields will be included.
349     * </p>
350     *
351     * @param lhs  {@code this} object
352     * @param rhs  The other object
353     * @param excludeFields  Collection of String field names to exclude from testing
354     * @return {@code true} if the two Objects have tested equals.
355     * @see EqualsExclude
356     */
357    public static boolean reflectionEquals(final Object lhs, final Object rhs, final Collection<String> excludeFields) {
358        return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
359    }
360
361    /**
362     * Uses reflection to determine if the two {@link Object}s
363     * are equal.
364     *
365     * <p>
366     * It uses {@code AccessibleObject.setAccessible} to gain access to private
367     * fields. This means that it will throw a security exception if run under
368     * a security manager, if the permissions are not set up correctly. It is also
369     * not as efficient as testing explicitly. Non-primitive fields are compared using
370     * {@code equals()}.
371     * </p>
372     *
373     * <p>
374     * Transient members will be not be tested, as they are likely derived
375     * fields, and not part of the value of the Object.
376     * </p>
377     *
378     * <p>
379     * Static fields will not be tested. Superclass fields will be included.
380     * </p>
381     *
382     * @param lhs  {@code this} object
383     * @param rhs  The other object
384     * @param excludeFields  array of field names to exclude from testing
385     * @return {@code true} if the two Objects have tested equals.
386     * @see EqualsExclude
387     */
388    public static boolean reflectionEquals(final Object lhs, final Object rhs, final String... excludeFields) {
389        return reflectionEquals(lhs, rhs, false, null, excludeFields);
390    }
391
392    /**
393     * Registers the given object pair.
394     * Used by the reflection methods to avoid infinite loops.
395     *
396     * @param lhs {@code this} object to register
397     * @param rhs The other object to register
398     */
399    private static void register(final Object lhs, final Object rhs) {
400        register(lhs, rhs, getRegistry());
401    }
402
403    /**
404     * Unregisters the given object pair.
405     *
406     * <p>
407     * Used by the reflection methods to avoid infinite loops.
408     * </p>
409     *
410     * @param lhs {@code this} object to unregister
411     * @param rhs The other object to unregister
412     */
413    private static void unregister(final Object lhs, final Object rhs) {
414        unregister(lhs, rhs, getRegistry(), REGISTRY);
415    }
416
417    /**
418     * If the fields tested are equals.
419     * The default value is {@code true}.
420     */
421    private boolean isEquals = true;
422
423    private boolean testTransients;
424
425    private boolean testRecursive;
426
427    private List<Class<?>> bypassReflectionClasses;
428
429    private Class<?> reflectUpToClass;
430
431    private String[] excludeFields;
432
433    /**
434     * Constructor for EqualsBuilder.
435     *
436     * <p>
437     * Starts off assuming that equals is {@code true}.
438     * </p>
439     *
440     * @see Object#equals(Object)
441     */
442    public EqualsBuilder() {
443        super(builder());
444        // set up default classes to bypass reflection for
445        bypassReflectionClasses = new ArrayList<>(1);
446        bypassReflectionClasses.add(String.class); //hashCode field being lazy but not transient
447    }
448
449    private EqualsBuilder(final Builder builder) {
450        super(builder);
451    }
452
453    /**
454     * Test if two {@code booleans}s are equal.
455     *
456     * @param lhs  The left-hand side {@code boolean}
457     * @param rhs  The right-hand side {@code boolean}
458     * @return {@code this} instance.
459      */
460    public EqualsBuilder append(final boolean lhs, final boolean rhs) {
461        if (!isEquals) {
462            return this;
463        }
464        isEquals = lhs == rhs;
465        return this;
466    }
467
468    /**
469     * Deep comparison of array of {@code boolean}. Length and all
470     * values are compared.
471     *
472     * <p>
473     * The method {@link #append(boolean, boolean)} is used.
474     * </p>
475     *
476     * @param lhs  The left-hand side {@code boolean[]}
477     * @param rhs  The right-hand side {@code boolean[]}
478     * @return {@code this} instance.
479     */
480    public EqualsBuilder append(final boolean[] lhs, final boolean[] rhs) {
481        if (!isEquals || lhs == rhs) {
482            return this;
483        }
484        if (lhs == null || rhs == null || lhs.length != rhs.length) {
485            setEquals(false);
486            return this;
487        }
488        for (int i = 0; i < lhs.length && isEquals; ++i) {
489            append(lhs[i], rhs[i]);
490        }
491        return this;
492    }
493
494    /**
495     * Test if two {@code byte}s are equal.
496     *
497     * @param lhs  The left-hand side {@code byte}
498     * @param rhs  The right-hand side {@code byte}
499     * @return {@code this} instance.
500     */
501    public EqualsBuilder append(final byte lhs, final byte rhs) {
502        if (isEquals) {
503            isEquals = lhs == rhs;
504        }
505        return this;
506    }
507
508    /**
509     * Deep comparison of array of {@code byte}. Length and all
510     * values are compared.
511     *
512     * <p>
513     * The method {@link #append(byte, byte)} is used.
514     * </p>
515     *
516     * @param lhs  The left-hand side {@code byte[]}
517     * @param rhs  The right-hand side {@code byte[]}
518     * @return {@code this} instance.
519     */
520    public EqualsBuilder append(final byte[] lhs, final byte[] rhs) {
521        if (!isEquals || lhs == rhs) {
522            return this;
523        }
524        if (lhs == null || rhs == null || lhs.length != rhs.length) {
525            setEquals(false);
526            return this;
527        }
528        for (int i = 0; i < lhs.length && isEquals; ++i) {
529            append(lhs[i], rhs[i]);
530        }
531        return this;
532    }
533
534    /**
535     * Test if two {@code char}s are equal.
536     *
537     * @param lhs  The left-hand side {@code char}
538     * @param rhs  The right-hand side {@code char}
539     * @return {@code this} instance.
540     */
541    public EqualsBuilder append(final char lhs, final char rhs) {
542        if (isEquals) {
543            isEquals = lhs == rhs;
544        }
545        return this;
546    }
547
548    /**
549     * Deep comparison of array of {@code char}. Length and all
550     * values are compared.
551     *
552     * <p>
553     * The method {@link #append(char, char)} is used.
554     * </p>
555     *
556     * @param lhs  The left-hand side {@code char[]}
557     * @param rhs  The right-hand side {@code char[]}
558     * @return {@code this} instance.
559     */
560    public EqualsBuilder append(final char[] lhs, final char[] rhs) {
561        if (!isEquals || lhs == rhs) {
562            return this;
563        }
564        if (lhs == null || rhs == null || lhs.length != rhs.length) {
565            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     * Test if two {@code double}s are equal by testing that the
576     * pattern of bits returned by {@code doubleToLong} are equal.
577     *
578     * <p>
579     * This handles NaNs, Infinities, and {@code -0.0}.
580     * </p>
581     *
582     * <p>
583     * It is compatible with the hash code generated by
584     * {@link HashCodeBuilder}.
585     * </p>
586     *
587     * @param lhs  The left-hand side {@code double}
588     * @param rhs  The right-hand side {@code double}
589     * @return {@code this} instance.
590     */
591    public EqualsBuilder append(final double lhs, final double rhs) {
592        if (isEquals) {
593            return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
594        }
595        return this;
596    }
597
598    /**
599     * Deep comparison of array of {@code double}. Length and all
600     * values are compared.
601     *
602     * <p>
603     * The method {@link #append(double, double)} is used.
604     * </p>
605     *
606     * @param lhs  The left-hand side {@code double[]}
607     * @param rhs  The right-hand side {@code double[]}
608     * @return {@code this} instance.
609     */
610    public EqualsBuilder append(final double[] lhs, final double[] rhs) {
611        if (!isEquals || lhs == rhs) {
612            return this;
613        }
614        if (lhs == null || rhs == null || lhs.length != rhs.length) {
615            setEquals(false);
616            return this;
617        }
618        for (int i = 0; i < lhs.length && isEquals; ++i) {
619            append(lhs[i], rhs[i]);
620        }
621        return this;
622    }
623
624    /**
625     * Test if two {@code float}s are equal by testing that the
626     * pattern of bits returned by doubleToLong are equal.
627     *
628     * <p>
629     * This handles NaNs, Infinities, and {@code -0.0}.
630     * </p>
631     *
632     * <p>
633     * It is compatible with the hash code generated by
634     * {@link HashCodeBuilder}.
635     * </p>
636     *
637     * @param lhs  The left-hand side {@code float}
638     * @param rhs  The right-hand side {@code float}
639     * @return {@code this} instance.
640     */
641    public EqualsBuilder append(final float lhs, final float rhs) {
642        if (isEquals) {
643            return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
644        }
645        return this;
646    }
647
648    /**
649     * Deep comparison of array of {@code float}. Length and all
650     * values are compared.
651     *
652     * <p>
653     * The method {@link #append(float, float)} is used.
654     * </p>
655     *
656     * @param lhs  The left-hand side {@code float[]}
657     * @param rhs  The right-hand side {@code float[]}
658     * @return {@code this} instance.
659     */
660    public EqualsBuilder append(final float[] lhs, final float[] rhs) {
661        if (!isEquals || lhs == rhs) {
662            return this;
663        }
664        if (lhs == null || rhs == null || lhs.length != rhs.length) {
665            setEquals(false);
666            return this;
667        }
668        for (int i = 0; i < lhs.length && isEquals; ++i) {
669            append(lhs[i], rhs[i]);
670        }
671        return this;
672    }
673
674    /**
675     * Test if two {@code int}s are equal.
676     *
677     * @param lhs  The left-hand side {@code int}
678     * @param rhs  The right-hand side {@code int}
679     * @return {@code this} instance.
680     */
681    public EqualsBuilder append(final int lhs, final int rhs) {
682        if (isEquals) {
683            isEquals = lhs == rhs;
684        }
685        return this;
686    }
687
688    /**
689     * Deep comparison of array of {@code int}. Length and all
690     * values are compared.
691     *
692     * <p>
693     * The method {@link #append(int, int)} is used.
694     * </p>
695     *
696     * @param lhs  The left-hand side {@code int[]}
697     * @param rhs  The right-hand side {@code int[]}
698     * @return {@code this} instance.
699     */
700    public EqualsBuilder append(final int[] lhs, final int[] rhs) {
701        if (!isEquals || lhs == rhs) {
702            return this;
703        }
704        if (lhs == null || rhs == null || lhs.length != rhs.length) {
705            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     * Test if two {@code long}s are equal.
716     *
717     * @param lhs
718     *                  the left-hand side {@code long}
719     * @param rhs
720     *                  the right-hand side {@code long}
721     * @return {@code this} instance.
722     */
723    public EqualsBuilder append(final long lhs, final long rhs) {
724        if (isEquals) {
725            isEquals = lhs == rhs;
726        }
727        return this;
728    }
729
730    /**
731     * Deep comparison of array of {@code long}. Length and all
732     * values are compared.
733     *
734     * <p>
735     * The method {@link #append(long, long)} is used.
736     * </p>
737     *
738     * @param lhs  The left-hand side {@code long[]}
739     * @param rhs  The right-hand side {@code long[]}
740     * @return {@code this} instance.
741     */
742    public EqualsBuilder append(final long[] lhs, final long[] rhs) {
743        if (!isEquals || lhs == rhs) {
744            return this;
745        }
746        if (lhs == null || rhs == null || lhs.length != rhs.length) {
747            setEquals(false);
748            return this;
749        }
750        for (int i = 0; i < lhs.length && isEquals; ++i) {
751            append(lhs[i], rhs[i]);
752        }
753        return this;
754    }
755
756    /**
757     * Test if two {@link Object}s are equal using either
758     * #{@link #reflectionAppend(Object, Object)}, if object are non
759     * primitives (or wrapper of primitives) or if field {@code testRecursive}
760     * is set to {@code false}. Otherwise, using their
761     * {@code equals} method.
762     *
763     * @param lhs  The left-hand side object
764     * @param rhs  The right-hand side object
765     * @return {@code this} instance.
766     */
767    public EqualsBuilder append(final Object lhs, final Object rhs) {
768        if (!isEquals || lhs == rhs) {
769            return this;
770        }
771        if (lhs == null || rhs == null) {
772            setEquals(false);
773            return this;
774        }
775        final Class<?> lhsClass = lhs.getClass();
776        if (lhsClass.isArray()) {
777            // factor out array case in order to keep method small enough
778            // to be inlined
779            appendArray(lhs, rhs);
780        } else // The simple case, not an array, just test the element
781        if (testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) {
782            reflectionAppend(lhs, rhs);
783        } else {
784            isEquals = lhs.equals(rhs);
785        }
786        return this;
787    }
788
789    /**
790     * Performs a deep comparison of two {@link Object} arrays.
791     *
792     * <p>
793     * This also will be called for the top level of
794     * multi-dimensional, ragged, and multi-typed arrays.
795     * </p>
796     *
797     * <p>
798     * Note that this method does not compare the type of the arrays; it only
799     * compares the contents.
800     * </p>
801     *
802     * @param lhs  The left-hand side {@code Object[]}
803     * @param rhs  The right-hand side {@code Object[]}
804     * @return {@code this} instance.
805     */
806    public EqualsBuilder append(final Object[] lhs, final Object[] rhs) {
807        if (!isEquals || isRegistered(lhs, rhs)) {
808            return this;
809        }
810        try {
811            register(lhs, rhs);
812            if (lhs == rhs) {
813                return this;
814            }
815            if (lhs == null || rhs == null || lhs.length != rhs.length) {
816                setEquals(false);
817                return this;
818            }
819            for (int i = 0; i < lhs.length && isEquals; ++i) {
820                append(lhs[i], rhs[i]);
821            }
822            return this;
823        } finally {
824            unregister(lhs, rhs);
825        }
826    }
827
828    /**
829     * Test if two {@code short}s are equal.
830     *
831     * @param lhs  The left-hand side {@code short}
832     * @param rhs  The right-hand side {@code short}
833     * @return {@code this} instance.
834     */
835    public EqualsBuilder append(final short lhs, final short rhs) {
836        if (isEquals) {
837            isEquals = lhs == rhs;
838        }
839        return this;
840    }
841
842    /**
843     * Deep comparison of array of {@code short}. Length and all
844     * values are compared.
845     *
846     * <p>
847     * The method {@link #append(short, short)} is used.
848     * </p>
849     *
850     * @param lhs  The left-hand side {@code short[]}
851     * @param rhs  The right-hand side {@code short[]}
852     * @return {@code this} instance.
853     */
854    public EqualsBuilder append(final short[] lhs, final short[] rhs) {
855        if (!isEquals || lhs == rhs) {
856            return this;
857        }
858        if (lhs == null || rhs == null || lhs.length != rhs.length) {
859            setEquals(false);
860            return this;
861        }
862        for (int i = 0; i < lhs.length && isEquals; ++i) {
863            append(lhs[i], rhs[i]);
864        }
865        return this;
866    }
867
868    /**
869     * Test if an {@link Object} is equal to an array.
870     *
871     * @param lhs  The left-hand side object, an array
872     * @param rhs  The right-hand side object
873     */
874    private void appendArray(final Object lhs, final Object rhs) {
875        // First we compare different dimensions, for example: a boolean[][] to a boolean[]
876        // then we 'Switch' on type of array, to dispatch to the correct handler
877        // This handles multidimensional arrays of the same depth
878        if (lhs.getClass() != rhs.getClass()) {
879            setEquals(false);
880        } else if (lhs instanceof long[]) {
881            append((long[]) lhs, (long[]) rhs);
882        } else if (lhs instanceof int[]) {
883            append((int[]) lhs, (int[]) rhs);
884        } else if (lhs instanceof short[]) {
885            append((short[]) lhs, (short[]) rhs);
886        } else if (lhs instanceof char[]) {
887            append((char[]) lhs, (char[]) rhs);
888        } else if (lhs instanceof byte[]) {
889            append((byte[]) lhs, (byte[]) rhs);
890        } else if (lhs instanceof double[]) {
891            append((double[]) lhs, (double[]) rhs);
892        } else if (lhs instanceof float[]) {
893            append((float[]) lhs, (float[]) rhs);
894        } else if (lhs instanceof boolean[]) {
895            append((boolean[]) lhs, (boolean[]) rhs);
896        } else {
897            // Not an array of primitives
898            append((Object[]) lhs, (Object[]) rhs);
899        }
900    }
901
902    /**
903     * Includes the result of the superclass's equality check.
904     * <p>
905     * Passing {@code false} makes {@link #isEquals()} return {@code false}. Passing {@code true} leaves the current result unchanged.
906     * </p>
907     * <p>
908     * Pass {@code super.equals(obj)} to include the superclass's equality check. The {@code equals(Object)} implementation may be declared by the superclass or
909     * inherited from an ancestor.
910     * </p>
911     * <p>
912     * When implementing field-based equality, omit this call if {@code super.equals(obj)} invokes {@link Object#equals(Object)}. That implementation compares
913     * object identity and returns {@code false} for distinct instances, even when all their fields are equal.
914     * </p>
915     *
916     * @param superEquals the result of calling {@code super.equals(obj)}
917     * @return {@code this} instance.
918     * @since 2.0
919     */
920    public EqualsBuilder appendSuper(final boolean superEquals) {
921        if (!isEquals) {
922            return this;
923        }
924        isEquals = superEquals;
925        return this;
926    }
927
928    /**
929     * Returns {@code true} if the fields that have been checked
930     * are all equal.
931     *
932     * @return {@code true} if all of the fields that have been checked
933     *         are equal, {@code false} otherwise.
934     *
935     * @since 3.0
936     */
937    @Override
938    public Boolean build() {
939        return Boolean.valueOf(isEquals());
940    }
941
942    /**
943     * Tests whether all fields checked so far are equal.
944     *
945     * @return boolean
946     */
947    public boolean isEquals() {
948        return isEquals;
949    }
950
951    /**
952     * Tests if two {@code objects} by using reflection.
953     *
954     * <p>
955     * It uses {@code AccessibleObject.setAccessible} to gain access to private
956     * fields. This means that it will throw a security exception if run under
957     * a security manager, if the permissions are not set up correctly. It is also
958     * not as efficient as testing explicitly. Non-primitive fields are compared using
959     * {@code equals()}.
960     * </p>
961     *
962     * <p>
963     * If the testTransients field is set to {@code true}, transient
964     * members will be tested, otherwise they are ignored, as they are likely
965     * derived fields, and not part of the value of the {@link Object}.
966     * </p>
967     *
968     * <p>
969     * Static fields will not be included. Superclass fields will be appended
970     * up to and including the specified superclass in field {@code reflectUpToClass}.
971     * A null superclass is treated as java.lang.Object.
972     * </p>
973     *
974     * <p>
975     * Field names listed in field {@code excludeFields} will be ignored.
976     * </p>
977     *
978     * <p>
979     * If either class of the compared objects is contained in
980     * {@code bypassReflectionClasses}, both objects are compared by calling
981     * the equals method of the left-hand side object with the right-hand side object as an argument.
982     * </p>
983     *
984     * @param lhs  The left-hand side object
985     * @param rhs  The right-hand side object
986     * @return {@code this} instance.
987     */
988    public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) {
989        if (!isEquals || lhs == rhs) {
990            return this;
991        }
992        if (lhs == null || rhs == null) {
993            isEquals = false;
994            return this;
995        }
996        // Find the leaf class since there may be transients in the leaf
997        // class or in classes between the leaf and root.
998        // If we are not testing transients or a subclass has no ivars,
999        // then a subclass can test equals to a superclass.
1000        final Class<?> lhsClass = lhs.getClass();
1001        final Class<?> rhsClass = rhs.getClass();
1002        Class<?> testClass;
1003        if (lhsClass.isInstance(rhs)) {
1004            testClass = lhsClass;
1005            if (!rhsClass.isInstance(lhs)) {
1006                // rhsClass is a subclass of lhsClass
1007                testClass = rhsClass;
1008            }
1009        } else if (rhsClass.isInstance(lhs)) {
1010            testClass = rhsClass;
1011            if (!lhsClass.isInstance(rhs)) {
1012                // lhsClass is a subclass of rhsClass
1013                testClass = lhsClass;
1014            }
1015        } else {
1016            // The two classes are not related.
1017            isEquals = false;
1018            return this;
1019        }
1020        try {
1021            if (testClass.isArray()) {
1022                append(lhs, rhs);
1023            } else // If either class is being excluded, call normal object equals method on lhsClass.
1024            if (bypassReflectionClasses != null && (bypassReflectionClasses.contains(lhsClass) || bypassReflectionClasses.contains(rhsClass))) {
1025                isEquals = lhs.equals(rhs);
1026            } else {
1027                reflectionAppend(lhs, rhs, testClass);
1028                while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
1029                    testClass = testClass.getSuperclass();
1030                    reflectionAppend(lhs, rhs, testClass);
1031                }
1032            }
1033        } catch (final IllegalArgumentException e) {
1034            // In this case, we tried to test a subclass vs. a superclass and
1035            // the subclass has ivars or the ivars are transient and
1036            // we are testing transients.
1037            // If a subclass has ivars that we are trying to test them, we get an
1038            // exception and we know that the objects are not equal.
1039            isEquals = false;
1040        }
1041        return this;
1042    }
1043
1044    /**
1045     * Appends the fields and values defined by the given object of the
1046     * given Class.
1047     *
1048     * @param lhs  The left-hand side object.
1049     * @param rhs  The right-hand side object.
1050     * @param clazz  The class to append details of.
1051     */
1052    private void reflectionAppend(final Object lhs, final Object rhs, final Class<?> clazz) {
1053        if (isRegistered(lhs, rhs)) {
1054            return;
1055        }
1056        try {
1057            register(lhs, rhs);
1058            final Field[] fields = clazz.getDeclaredFields();
1059            for (int i = 0; i < fields.length && isEquals; i++) {
1060                final Field field = fields[i];
1061                if (!ArrayUtils.contains(excludeFields, field.getName())
1062                    && !field.getName().contains("$")
1063                    && (testTransients || !Modifier.isTransient(field.getModifiers()))
1064                    && !Modifier.isStatic(field.getModifiers())
1065                    && !field.isAnnotationPresent(EqualsExclude.class)) {
1066                    if (setAccessible(field)) {
1067                        append(Reflection.getUnchecked(field, lhs), Reflection.getUnchecked(field, rhs));
1068                    }
1069                }
1070            }
1071        } finally {
1072            unregister(lhs, rhs);
1073        }
1074    }
1075
1076    /**
1077     * Reset the EqualsBuilder so you can use the same object again.
1078     *
1079     * @since 2.5
1080     */
1081    public void reset() {
1082        isEquals = true;
1083    }
1084
1085    /**
1086     * Sets {@link Class}es whose instances should be compared by calling their {@code equals}
1087     * although being in recursive mode. So the fields of these classes will not be compared recursively by reflection.
1088     *
1089     * <p>
1090     * Here you should name classes having non-transient fields which are cache fields being set lazily.<br>
1091     * Prominent example being {@link String} class with its hash code cache field. Due to the importance
1092     * of the {@link String} class, it is included in the default bypasses classes. Usually, if you use
1093     * your own set of classes here, remember to include {@link String} class, too.
1094     * </p>
1095     *
1096     * @param bypassReflectionClasses  classes to bypass reflection test
1097     * @return {@code this} instance.
1098     * @see #setTestRecursive(boolean)
1099     * @since 3.8
1100     */
1101    public EqualsBuilder setBypassReflectionClasses(final List<Class<?>> bypassReflectionClasses) {
1102        this.bypassReflectionClasses = bypassReflectionClasses;
1103        return this;
1104    }
1105
1106    /**
1107     * Sets the {@code isEquals} value.
1108     *
1109     * @param isEquals The value to set.
1110     * @since 2.1
1111     */
1112    protected void setEquals(final boolean isEquals) {
1113        this.isEquals = isEquals;
1114    }
1115
1116    /**
1117     * Sets field names to be excluded by reflection tests.
1118     *
1119     * @param excludeFields The fields to exclude
1120     * @return {@code this} instance.
1121     * @since 3.6
1122     */
1123    public EqualsBuilder setExcludeFields(final String... excludeFields) {
1124        this.excludeFields = excludeFields;
1125        return this;
1126    }
1127
1128    /**
1129     * Sets the superclass to reflect up to at reflective tests.
1130     *
1131     * @param reflectUpToClass The super class to reflect up to
1132     * @return {@code this} instance.
1133     * @since 3.6
1134     */
1135    public EqualsBuilder setReflectUpToClass(final Class<?> reflectUpToClass) {
1136        this.reflectUpToClass = reflectUpToClass;
1137        return this;
1138    }
1139
1140    /**
1141     * Sets whether to test fields recursively, instead of using their equals method, when reflectively comparing objects.
1142     * String objects, which cache a hash value, are automatically excluded from recursive testing.
1143     * You may specify other exceptions by calling {@link #setBypassReflectionClasses(List)}.
1144     *
1145     * <p>
1146     * Cycle protection is a visit stack, not a visited set: shared (acyclic) references are
1147     * re-compared on every path, so deeply nested graphs with many shared references can be
1148     * exponentially expensive to compare. Avoid on object graphs built from untrusted input.
1149     * </p>
1150     *
1151     * @param testRecursive whether to do a recursive test
1152     * @return {@code this} instance.
1153     * @see #setBypassReflectionClasses(List)
1154     * @since 3.6
1155     */
1156    public EqualsBuilder setTestRecursive(final boolean testRecursive) {
1157        this.testRecursive = testRecursive;
1158        return this;
1159    }
1160
1161    /**
1162     * Sets whether to include transient fields when reflectively comparing objects.
1163     *
1164     * @param testTransients whether to test transient fields
1165     * @return {@code this} instance.
1166     * @since 3.6
1167     */
1168    public EqualsBuilder setTestTransients(final boolean testTransients) {
1169        this.testTransients = testTransients;
1170        return this;
1171    }
1172}