View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.builder;
18  
19  import java.lang.reflect.AccessibleObject;
20  import java.lang.reflect.Field;
21  import java.lang.reflect.Modifier;
22  import java.util.Collection;
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  import org.apache.commons.lang3.ArrayUtils;
27  import org.apache.commons.lang3.ClassUtils;
28  import org.apache.commons.lang3.tuple.Pair;
29  
30  /**
31   * <p>Assists in implementing {@link Object#equals(Object)} methods.</p>
32   *
33   * <p> This class provides methods to build a good equals method for any
34   * class. It follows rules laid out in
35   * <a href="http://www.oracle.com/technetwork/java/effectivejava-136174.html">Effective Java</a>
36   * , by Joshua Bloch. In particular the rule for comparing <code>doubles</code>,
37   * <code>floats</code>, and arrays can be tricky. Also, making sure that
38   * <code>equals()</code> and <code>hashCode()</code> are consistent can be
39   * difficult.</p>
40   *
41   * <p>Two Objects that compare as equals must generate the same hash code,
42   * but two Objects with the same hash code do not have to be equal.</p>
43   *
44   * <p>All relevant fields should be included in the calculation of equals.
45   * Derived fields may be ignored. In particular, any field used in
46   * generating a hash code must be used in the equals method, and vice
47   * versa.</p>
48   *
49   * <p>Typical use for the code is as follows:</p>
50   * <pre>
51   * public boolean equals(Object obj) {
52   *   if (obj == null) { return false; }
53   *   if (obj == this) { return true; }
54   *   if (obj.getClass() != getClass()) {
55   *     return false;
56   *   }
57   *   MyClass rhs = (MyClass) obj;
58   *   return new EqualsBuilder()
59   *                 .appendSuper(super.equals(obj))
60   *                 .append(field1, rhs.field1)
61   *                 .append(field2, rhs.field2)
62   *                 .append(field3, rhs.field3)
63   *                 .isEquals();
64   *  }
65   * </pre>
66   *
67   * <p> Alternatively, there is a method that uses reflection to determine
68   * the fields to test. Because these fields are usually private, the method,
69   * <code>reflectionEquals</code>, uses <code>AccessibleObject.setAccessible</code> to
70   * change the visibility of the fields. This will fail under a security
71   * manager, unless the appropriate permissions are set up correctly. It is
72   * also slower than testing explicitly.  Non-primitive fields are compared using
73   * <code>equals()</code>.</p>
74   *
75   * <p> A typical invocation for this method would look like:</p>
76   * <pre>
77   * public boolean equals(Object obj) {
78   *   return EqualsBuilder.reflectionEquals(this, obj);
79   * }
80   * </pre>
81   *
82   * <p>The {@link EqualsExclude} annotation can be used to exclude fields from being
83   * used by the <code>reflectionEquals</code> methods.</p>
84   *
85   * @since 1.0
86   */
87  public class EqualsBuilder implements Builder<Boolean> {
88  
89      /**
90       * <p>
91       * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
92       * </p>
93       *
94       * @since 3.0
95       */
96      private static final ThreadLocal<Set<Pair<IDKey, IDKey>>> REGISTRY = new ThreadLocal<>();
97  
98      /*
99       * NOTE: we cannot store the actual objects in a HashSet, as that would use the very hashCode()
100      * we are in the process of calculating.
101      *
102      * So we generate a one-to-one mapping from the original object to a new object.
103      *
104      * Now HashSet uses equals() to determine if two elements with the same hash code really
105      * are equal, so we also need to ensure that the replacement objects are only equal
106      * if the original objects are identical.
107      *
108      * The original implementation (2.4 and before) used the System.identityHashCode()
109      * method - however this is not guaranteed to generate unique ids (e.g. LANG-459)
110      *
111      * We now use the IDKey helper class (adapted from org.apache.axis.utils.IDKey)
112      * to disambiguate the duplicate ids.
113      */
114 
115     /**
116      * <p>
117      * Returns the registry of object pairs being traversed by the reflection
118      * methods in the current thread.
119      * </p>
120      *
121      * @return Set the registry of objects being traversed
122      * @since 3.0
123      */
124     static Set<Pair<IDKey, IDKey>> getRegistry() {
125         return REGISTRY.get();
126     }
127 
128     /**
129      * <p>
130      * Converters value pair into a register pair.
131      * </p>
132      *
133      * @param lhs <code>this</code> object
134      * @param rhs the other object
135      *
136      * @return the pair
137      */
138     static Pair<IDKey, IDKey> getRegisterPair(final Object lhs, final Object rhs) {
139         final IDKey left = new IDKey(lhs);
140         final IDKey right = new IDKey(rhs);
141         return Pair.of(left, right);
142     }
143 
144     /**
145      * <p>
146      * Returns <code>true</code> if the registry contains the given object pair.
147      * Used by the reflection methods to avoid infinite loops.
148      * Objects might be swapped therefore a check is needed if the object pair
149      * is registered in given or swapped order.
150      * </p>
151      *
152      * @param lhs <code>this</code> object to lookup in registry
153      * @param rhs the other object to lookup on registry
154      * @return boolean <code>true</code> if the registry contains the given object.
155      * @since 3.0
156      */
157     static boolean isRegistered(final Object lhs, final Object rhs) {
158         final Set<Pair<IDKey, IDKey>> registry = getRegistry();
159         final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs);
160         final Pair<IDKey, IDKey> swappedPair = Pair.of(pair.getLeft(), pair.getRight());
161 
162         return registry != null
163                 && (registry.contains(pair) || registry.contains(swappedPair));
164     }
165 
166     /**
167      * <p>
168      * Registers the given object pair.
169      * Used by the reflection methods to avoid infinite loops.
170      * </p>
171      *
172      * @param lhs <code>this</code> object to register
173      * @param rhs the other object to register
174      */
175     private static void register(final Object lhs, final Object rhs) {
176         Set<Pair<IDKey, IDKey>> registry = getRegistry();
177         if (registry == null) {
178             registry = new HashSet<>();
179             REGISTRY.set(registry);
180         }
181         final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs);
182         registry.add(pair);
183     }
184 
185     /**
186      * <p>
187      * Unregisters the given object pair.
188      * </p>
189      *
190      * <p>
191      * Used by the reflection methods to avoid infinite loops.
192      *
193      * @param lhs <code>this</code> object to unregister
194      * @param rhs the other object to unregister
195      * @since 3.0
196      */
197     private static void unregister(final Object lhs, final Object rhs) {
198         final Set<Pair<IDKey, IDKey>> registry = getRegistry();
199         if (registry != null) {
200             final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs);
201             registry.remove(pair);
202             if (registry.isEmpty()) {
203                 REGISTRY.remove();
204             }
205         }
206     }
207 
208     /**
209      * If the fields tested are equals.
210      * The default value is <code>true</code>.
211      */
212     private boolean isEquals = true;
213 
214     private boolean testTransients = false;
215     private boolean testRecursive = false;
216     private Class<?> reflectUpToClass = null;
217     private String[] excludeFields = null;
218 
219     /**
220      * <p>Constructor for EqualsBuilder.</p>
221      *
222      * <p>Starts off assuming that equals is <code>true</code>.</p>
223      * @see Object#equals(Object)
224      */
225     public EqualsBuilder() {
226         // do nothing for now.
227     }
228 
229     //-------------------------------------------------------------------------
230 
231     /**
232      * Set whether to include transient fields when reflectively comparing objects.
233      * @param testTransients whether to test transient fields
234      * @return EqualsBuilder - used to chain calls.
235      * @since 3.6
236      */
237     public EqualsBuilder setTestTransients(final boolean testTransients) {
238         this.testTransients = testTransients;
239         return this;
240     }
241 
242     /**
243      * Set whether to include transient fields when reflectively comparing objects.
244      * @param testRecursive  whether to do a recursive test
245      * @return EqualsBuilder - used to chain calls.
246      * @since 3.6
247      */
248     public EqualsBuilder setTestRecursive(final boolean testRecursive) {
249         this.testRecursive = testRecursive;
250         return this;
251     }
252 
253     /**
254      * Set the superclass to reflect up to at reflective tests.
255      * @param reflectUpToClass the super class to reflect up to
256      * @return EqualsBuilder - used to chain calls.
257      * @since 3.6
258      */
259     public EqualsBuilder setReflectUpToClass(final Class<?> reflectUpToClass) {
260         this.reflectUpToClass = reflectUpToClass;
261         return this;
262     }
263 
264     /**
265      * Set field names to be excluded by reflection tests.
266      * @param excludeFields the fields to exclude
267      * @return EqualsBuilder - used to chain calls.
268      * @since 3.6
269      */
270     public EqualsBuilder setExcludeFields(final String... excludeFields) {
271         this.excludeFields = excludeFields;
272         return this;
273     }
274 
275 
276     /**
277      * <p>This method uses reflection to determine if the two <code>Object</code>s
278      * are equal.</p>
279      *
280      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
281      * fields. This means that it will throw a security exception if run under
282      * a security manager, if the permissions are not set up correctly. It is also
283      * not as efficient as testing explicitly. Non-primitive fields are compared using
284      * <code>equals()</code>.</p>
285      *
286      * <p>Transient members will be not be tested, as they are likely derived
287      * fields, and not part of the value of the Object.</p>
288      *
289      * <p>Static fields will not be tested. Superclass fields will be included.</p>
290      *
291      * @param lhs  <code>this</code> object
292      * @param rhs  the other object
293      * @param excludeFields  Collection of String field names to exclude from testing
294      * @return <code>true</code> if the two Objects have tested equals.
295      *
296      * @see EqualsExclude
297      */
298     public static boolean reflectionEquals(final Object lhs, final Object rhs, final Collection<String> excludeFields) {
299         return reflectionEquals(lhs, rhs, ReflectionToStringBuilder.toNoNullStringArray(excludeFields));
300     }
301 
302     /**
303      * <p>This method uses reflection to determine if the two <code>Object</code>s
304      * are equal.</p>
305      *
306      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
307      * fields. This means that it will throw a security exception if run under
308      * a security manager, if the permissions are not set up correctly. It is also
309      * not as efficient as testing explicitly. Non-primitive fields are compared using
310      * <code>equals()</code>.</p>
311      *
312      * <p>Transient members will be not be tested, as they are likely derived
313      * fields, and not part of the value of the Object.</p>
314      *
315      * <p>Static fields will not be tested. Superclass fields will be included.</p>
316      *
317      * @param lhs  <code>this</code> object
318      * @param rhs  the other object
319      * @param excludeFields  array of field names to exclude from testing
320      * @return <code>true</code> if the two Objects have tested equals.
321      *
322      * @see EqualsExclude
323      */
324     public static boolean reflectionEquals(final Object lhs, final Object rhs, final String... excludeFields) {
325         return reflectionEquals(lhs, rhs, false, null, excludeFields);
326     }
327 
328     /**
329      * <p>This method uses reflection to determine if the two <code>Object</code>s
330      * are equal.</p>
331      *
332      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
333      * fields. This means that it will throw a security exception if run under
334      * a security manager, if the permissions are not set up correctly. It is also
335      * not as efficient as testing explicitly. Non-primitive fields are compared using
336      * <code>equals()</code>.</p>
337      *
338      * <p>If the TestTransients parameter is set to <code>true</code>, transient
339      * members will be tested, otherwise they are ignored, as they are likely
340      * derived fields, and not part of the value of the <code>Object</code>.</p>
341      *
342      * <p>Static fields will not be tested. Superclass fields will be included.</p>
343      *
344      * @param lhs  <code>this</code> object
345      * @param rhs  the other object
346      * @param testTransients  whether to include transient fields
347      * @return <code>true</code> if the two Objects have tested equals.
348      *
349      * @see EqualsExclude
350      */
351     public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients) {
352         return reflectionEquals(lhs, rhs, testTransients, null);
353     }
354 
355     /**
356      * <p>This method uses reflection to determine if the two <code>Object</code>s
357      * are equal.</p>
358      *
359      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
360      * fields. This means that it will throw a security exception if run under
361      * a security manager, if the permissions are not set up correctly. It is also
362      * not as efficient as testing explicitly. Non-primitive fields are compared using
363      * <code>equals()</code>.</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      *
381      * @see EqualsExclude
382      * @since 2.0
383      */
384     public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass,
385             final String... excludeFields) {
386         return reflectionEquals(lhs, rhs, testTransients, reflectUpToClass, false, excludeFields);
387     }
388 
389     /**
390      * <p>This method uses reflection to determine if the two <code>Object</code>s
391      * are equal.</p>
392      *
393      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
394      * fields. This means that it will throw a security exception if run under
395      * a security manager, if the permissions are not set up correctly. It is also
396      * not as efficient as testing explicitly. Non-primitive fields are compared using
397      * <code>equals()</code>.</p>
398      *
399      * <p>If the testTransients parameter is set to <code>true</code>, transient
400      * members will be tested, otherwise they are ignored, as they are likely
401      * derived fields, and not part of the value of the <code>Object</code>.</p>
402      *
403      * <p>Static fields will not be included. Superclass fields will be appended
404      * up to and including the specified superclass. A null superclass is treated
405      * as java.lang.Object.</p>
406      *
407      * <p>If the testRecursive parameter is set to <code>true</code>, non primitive
408      * (and non primitive wrapper) field types will be compared by
409      * <code>EqualsBuilder</code> recursively instead of invoking their
410      * <code>equals()</code> method. Leading to a deep reflection equals test.
411      *
412      * @param lhs  <code>this</code> object
413      * @param rhs  the other object
414      * @param testTransients  whether to include transient fields
415      * @param reflectUpToClass  the superclass to reflect up to (inclusive),
416      *  may be <code>null</code>
417      * @param testRecursive  whether to call reflection equals on non primitive
418      *  fields recursively.
419      * @param excludeFields  array of field names to exclude from testing
420      * @return <code>true</code> if the two Objects have tested equals.
421      *
422      * @see EqualsExclude
423      * @since 3.6
424      */
425     public static boolean reflectionEquals(final Object lhs, final Object rhs, final boolean testTransients, final Class<?> reflectUpToClass,
426             final boolean testRecursive, final String... excludeFields) {
427         if (lhs == rhs) {
428             return true;
429         }
430         if (lhs == null || rhs == null) {
431             return false;
432         }
433         return new EqualsBuilder()
434                     .setExcludeFields(excludeFields)
435                     .setReflectUpToClass(reflectUpToClass)
436                     .setTestTransients(testTransients)
437                     .setTestRecursive(testRecursive)
438                     .reflectionAppend(lhs, rhs)
439                     .isEquals();
440     }
441 
442     /**
443      * <p>Tests if two <code>objects</code> by using reflection.</p>
444      *
445      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access to private
446      * fields. This means that it will throw a security exception if run under
447      * a security manager, if the permissions are not set up correctly. It is also
448      * not as efficient as testing explicitly. Non-primitive fields are compared using
449      * <code>equals()</code>.</p>
450      *
451      * <p>If the testTransients field is set to <code>true</code>, transient
452      * members will be tested, otherwise they are ignored, as they are likely
453      * derived fields, and not part of the value of the <code>Object</code>.</p>
454      *
455      * <p>Static fields will not be included. Superclass fields will be appended
456      * up to and including the specified superclass in field <code>reflectUpToClass</code>.
457      * A null superclass is treated as java.lang.Object.</p>
458      *
459      * <p>Field names listed in field <code>excludeFields</code> will be ignored.</p>
460      *
461      * @param lhs  the left hand object
462      * @param rhs  the left hand object
463      * @return EqualsBuilder - used to chain calls.
464      */
465     public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) {
466         if (!isEquals) {
467             return this;
468         }
469         if (lhs == rhs) {
470             return this;
471         }
472         if (lhs == null || rhs == null) {
473             isEquals = false;
474             return this;
475         }
476 
477         // Find the leaf class since there may be transients in the leaf
478         // class or in classes between the leaf and root.
479         // If we are not testing transients or a subclass has no ivars,
480         // then a subclass can test equals to a superclass.
481         final Class<?> lhsClass = lhs.getClass();
482         final Class<?> rhsClass = rhs.getClass();
483         Class<?> testClass;
484         if (lhsClass.isInstance(rhs)) {
485             testClass = lhsClass;
486             if (!rhsClass.isInstance(lhs)) {
487                 // rhsClass is a subclass of lhsClass
488                 testClass = rhsClass;
489             }
490         } else if (rhsClass.isInstance(lhs)) {
491             testClass = rhsClass;
492             if (!lhsClass.isInstance(rhs)) {
493                 // lhsClass is a subclass of rhsClass
494                 testClass = lhsClass;
495             }
496         } else {
497             // The two classes are not related.
498             isEquals = false;
499             return this;
500         }
501 
502         try {
503             if (testClass.isArray()) {
504                 append(lhs, rhs);
505             } else {
506                 reflectionAppend(lhs, rhs, testClass);
507                 while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
508                     testClass = testClass.getSuperclass();
509                     reflectionAppend(lhs, rhs, testClass);
510                 }
511             }
512         } catch (final IllegalArgumentException e) {
513             // In this case, we tried to test a subclass vs. a superclass and
514             // the subclass has ivars or the ivars are transient and
515             // we are testing transients.
516             // If a subclass has ivars that we are trying to test them, we get an
517             // exception and we know that the objects are not equal.
518             isEquals = false;
519             return this;
520         }
521         return this;
522     }
523 
524     /**
525      * <p>Appends the fields and values defined by the given object of the
526      * given Class.</p>
527      *
528      * @param lhs  the left hand object
529      * @param rhs  the right hand object
530      * @param clazz  the class to append details of
531      */
532     private void reflectionAppend(
533         final Object lhs,
534         final Object rhs,
535         final Class<?> clazz) {
536 
537         if (isRegistered(lhs, rhs)) {
538             return;
539         }
540 
541         try {
542             register(lhs, rhs);
543             final Field[] fields = clazz.getDeclaredFields();
544             AccessibleObject.setAccessible(fields, true);
545             for (int i = 0; i < fields.length && isEquals; i++) {
546                 final Field f = fields[i];
547                 if (!ArrayUtils.contains(excludeFields, f.getName())
548                     && !f.getName().contains("$")
549                     && (testTransients || !Modifier.isTransient(f.getModifiers()))
550                     && !Modifier.isStatic(f.getModifiers())
551                     && !f.isAnnotationPresent(EqualsExclude.class)) {
552                     try {
553                         append(f.get(lhs), f.get(rhs));
554                     } catch (final IllegalAccessException e) {
555                         //this can't happen. Would get a Security exception instead
556                         //throw a runtime exception in case the impossible happens.
557                         throw new InternalError("Unexpected IllegalAccessException");
558                     }
559                 }
560             }
561         } finally {
562             unregister(lhs, rhs);
563         }
564     }
565 
566     //-------------------------------------------------------------------------
567 
568     /**
569      * <p>Adds the result of <code>super.equals()</code> to this builder.</p>
570      *
571      * @param superEquals  the result of calling <code>super.equals()</code>
572      * @return EqualsBuilder - used to chain calls.
573      * @since 2.0
574      */
575     public EqualsBuilder appendSuper(final boolean superEquals) {
576         if (!isEquals) {
577             return this;
578         }
579         isEquals = superEquals;
580         return this;
581     }
582 
583     //-------------------------------------------------------------------------
584 
585     /**
586      * <p>Test if two <code>Object</code>s are equal using either
587      * #{@link #reflectionAppend(Object, Object)}, if object are non
588      * primitives (or wrapper of primitives) or if field <code>testRecursive</code>
589      * is set to <code>false</code>. Otherwise, using their
590      * <code>equals</code> method.</p>
591      *
592      * @param lhs  the left hand object
593      * @param rhs  the right hand object
594      * @return EqualsBuilder - used to chain calls.
595      */
596     public EqualsBuilder append(final Object lhs, final Object rhs) {
597         if (!isEquals) {
598             return this;
599         }
600         if (lhs == rhs) {
601             return this;
602         }
603         if (lhs == null || rhs == null) {
604             this.setEquals(false);
605             return this;
606         }
607         final Class<?> lhsClass = lhs.getClass();
608         if (!lhsClass.isArray()) {
609             // The simple case, not an array, just test the element
610             if (testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) {
611                 reflectionAppend(lhs, rhs);
612             } else {
613                 isEquals = lhs.equals(rhs);
614             }
615         } else {
616             // factor out array case in order to keep method small enough
617             // to be inlined
618             appendArray(lhs, rhs);
619         }
620         return this;
621     }
622 
623     /**
624      * <p>Test if an <code>Object</code> is equal to an array.</p>
625      *
626      * @param lhs  the left hand object, an array
627      * @param rhs  the right hand object
628      */
629     private void appendArray(final Object lhs, final Object rhs) {
630         // First we compare different dimensions, for example: a boolean[][] to a boolean[]
631         // then we 'Switch' on type of array, to dispatch to the correct handler
632         // This handles multi dimensional arrays of the same depth
633         if (lhs.getClass() != rhs.getClass()) {
634             this.setEquals(false);
635         } else if (lhs instanceof long[]) {
636             append((long[]) lhs, (long[]) rhs);
637         } else if (lhs instanceof int[]) {
638             append((int[]) lhs, (int[]) rhs);
639         } else if (lhs instanceof short[]) {
640             append((short[]) lhs, (short[]) rhs);
641         } else if (lhs instanceof char[]) {
642             append((char[]) lhs, (char[]) rhs);
643         } else if (lhs instanceof byte[]) {
644             append((byte[]) lhs, (byte[]) rhs);
645         } else if (lhs instanceof double[]) {
646             append((double[]) lhs, (double[]) rhs);
647         } else if (lhs instanceof float[]) {
648             append((float[]) lhs, (float[]) rhs);
649         } else if (lhs instanceof boolean[]) {
650             append((boolean[]) lhs, (boolean[]) rhs);
651         } else {
652             // Not an array of primitives
653             append((Object[]) lhs, (Object[]) rhs);
654         }
655     }
656 
657     /**
658      * <p>
659      * Test if two <code>long</code> s are equal.
660      * </p>
661      *
662      * @param lhs
663      *                  the left hand <code>long</code>
664      * @param rhs
665      *                  the right hand <code>long</code>
666      * @return EqualsBuilder - used to chain calls.
667      */
668     public EqualsBuilder append(final long lhs, final long rhs) {
669         if (!isEquals) {
670             return this;
671         }
672         isEquals = lhs == rhs;
673         return this;
674     }
675 
676     /**
677      * <p>Test if two <code>int</code>s are equal.</p>
678      *
679      * @param lhs  the left hand <code>int</code>
680      * @param rhs  the right hand <code>int</code>
681      * @return EqualsBuilder - used to chain calls.
682      */
683     public EqualsBuilder append(final int lhs, final int rhs) {
684         if (!isEquals) {
685             return this;
686         }
687         isEquals = lhs == rhs;
688         return this;
689     }
690 
691     /**
692      * <p>Test if two <code>short</code>s are equal.</p>
693      *
694      * @param lhs  the left hand <code>short</code>
695      * @param rhs  the right hand <code>short</code>
696      * @return EqualsBuilder - used to chain calls.
697      */
698     public EqualsBuilder append(final short lhs, final short rhs) {
699         if (!isEquals) {
700             return this;
701         }
702         isEquals = lhs == rhs;
703         return this;
704     }
705 
706     /**
707      * <p>Test if two <code>char</code>s are equal.</p>
708      *
709      * @param lhs  the left hand <code>char</code>
710      * @param rhs  the right hand <code>char</code>
711      * @return EqualsBuilder - used to chain calls.
712      */
713     public EqualsBuilder append(final char lhs, final char rhs) {
714         if (!isEquals) {
715             return this;
716         }
717         isEquals = lhs == rhs;
718         return this;
719     }
720 
721     /**
722      * <p>Test if two <code>byte</code>s are equal.</p>
723      *
724      * @param lhs  the left hand <code>byte</code>
725      * @param rhs  the right hand <code>byte</code>
726      * @return EqualsBuilder - used to chain calls.
727      */
728     public EqualsBuilder append(final byte lhs, final byte rhs) {
729         if (!isEquals) {
730             return this;
731         }
732         isEquals = lhs == rhs;
733         return this;
734     }
735 
736     /**
737      * <p>Test if two <code>double</code>s are equal by testing that the
738      * pattern of bits returned by <code>doubleToLong</code> are equal.</p>
739      *
740      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
741      *
742      * <p>It is compatible with the hash code generated by
743      * <code>HashCodeBuilder</code>.</p>
744      *
745      * @param lhs  the left hand <code>double</code>
746      * @param rhs  the right hand <code>double</code>
747      * @return EqualsBuilder - used to chain calls.
748      */
749     public EqualsBuilder append(final double lhs, final double rhs) {
750         if (!isEquals) {
751             return this;
752         }
753         return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
754     }
755 
756     /**
757      * <p>Test if two <code>float</code>s are equal byt testing that the
758      * pattern of bits returned by doubleToLong are equal.</p>
759      *
760      * <p>This handles NaNs, Infinities, and <code>-0.0</code>.</p>
761      *
762      * <p>It is compatible with the hash code generated by
763      * <code>HashCodeBuilder</code>.</p>
764      *
765      * @param lhs  the left hand <code>float</code>
766      * @param rhs  the right hand <code>float</code>
767      * @return EqualsBuilder - used to chain calls.
768      */
769     public EqualsBuilder append(final float lhs, final float rhs) {
770         if (!isEquals) {
771             return this;
772         }
773         return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
774     }
775 
776     /**
777      * <p>Test if two <code>booleans</code>s are equal.</p>
778      *
779      * @param lhs  the left hand <code>boolean</code>
780      * @param rhs  the right hand <code>boolean</code>
781      * @return EqualsBuilder - used to chain calls.
782       */
783     public EqualsBuilder append(final boolean lhs, final boolean rhs) {
784         if (!isEquals) {
785             return this;
786         }
787         isEquals = lhs == rhs;
788         return this;
789     }
790 
791     /**
792      * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
793      *
794      * <p>This also will be called for the top level of
795      * multi-dimensional, ragged, and multi-typed arrays.</p>
796      *
797      * <p>Note that this method does not compare the type of the arrays; it only
798      * compares the contents.</p>
799      *
800      * @param lhs  the left hand <code>Object[]</code>
801      * @param rhs  the right hand <code>Object[]</code>
802      * @return EqualsBuilder - used to chain calls.
803      */
804     public EqualsBuilder append(final Object[] lhs, final Object[] rhs) {
805         if (!isEquals) {
806             return this;
807         }
808         if (lhs == rhs) {
809             return this;
810         }
811         if (lhs == null || rhs == null) {
812             this.setEquals(false);
813             return this;
814         }
815         if (lhs.length != rhs.length) {
816             this.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     }
824 
825     /**
826      * <p>Deep comparison of array of <code>long</code>. Length and all
827      * values are compared.</p>
828      *
829      * <p>The method {@link #append(long, long)} is used.</p>
830      *
831      * @param lhs  the left hand <code>long[]</code>
832      * @param rhs  the right hand <code>long[]</code>
833      * @return EqualsBuilder - used to chain calls.
834      */
835     public EqualsBuilder append(final long[] lhs, final long[] rhs) {
836         if (!isEquals) {
837             return this;
838         }
839         if (lhs == rhs) {
840             return this;
841         }
842         if (lhs == null || rhs == null) {
843             this.setEquals(false);
844             return this;
845         }
846         if (lhs.length != rhs.length) {
847             this.setEquals(false);
848             return this;
849         }
850         for (int i = 0; i < lhs.length && isEquals; ++i) {
851             append(lhs[i], rhs[i]);
852         }
853         return this;
854     }
855 
856     /**
857      * <p>Deep comparison of array of <code>int</code>. Length and all
858      * values are compared.</p>
859      *
860      * <p>The method {@link #append(int, int)} is used.</p>
861      *
862      * @param lhs  the left hand <code>int[]</code>
863      * @param rhs  the right hand <code>int[]</code>
864      * @return EqualsBuilder - used to chain calls.
865      */
866     public EqualsBuilder append(final int[] lhs, final int[] rhs) {
867         if (!isEquals) {
868             return this;
869         }
870         if (lhs == rhs) {
871             return this;
872         }
873         if (lhs == null || rhs == null) {
874             this.setEquals(false);
875             return this;
876         }
877         if (lhs.length != rhs.length) {
878             this.setEquals(false);
879             return this;
880         }
881         for (int i = 0; i < lhs.length && isEquals; ++i) {
882             append(lhs[i], rhs[i]);
883         }
884         return this;
885     }
886 
887     /**
888      * <p>Deep comparison of array of <code>short</code>. Length and all
889      * values are compared.</p>
890      *
891      * <p>The method {@link #append(short, short)} is used.</p>
892      *
893      * @param lhs  the left hand <code>short[]</code>
894      * @param rhs  the right hand <code>short[]</code>
895      * @return EqualsBuilder - used to chain calls.
896      */
897     public EqualsBuilder append(final short[] lhs, final short[] rhs) {
898         if (!isEquals) {
899             return this;
900         }
901         if (lhs == rhs) {
902             return this;
903         }
904         if (lhs == null || rhs == null) {
905             this.setEquals(false);
906             return this;
907         }
908         if (lhs.length != rhs.length) {
909             this.setEquals(false);
910             return this;
911         }
912         for (int i = 0; i < lhs.length && isEquals; ++i) {
913             append(lhs[i], rhs[i]);
914         }
915         return this;
916     }
917 
918     /**
919      * <p>Deep comparison of array of <code>char</code>. Length and all
920      * values are compared.</p>
921      *
922      * <p>The method {@link #append(char, char)} is used.</p>
923      *
924      * @param lhs  the left hand <code>char[]</code>
925      * @param rhs  the right hand <code>char[]</code>
926      * @return EqualsBuilder - used to chain calls.
927      */
928     public EqualsBuilder append(final char[] lhs, final char[] rhs) {
929         if (!isEquals) {
930             return this;
931         }
932         if (lhs == rhs) {
933             return this;
934         }
935         if (lhs == null || rhs == null) {
936             this.setEquals(false);
937             return this;
938         }
939         if (lhs.length != rhs.length) {
940             this.setEquals(false);
941             return this;
942         }
943         for (int i = 0; i < lhs.length && isEquals; ++i) {
944             append(lhs[i], rhs[i]);
945         }
946         return this;
947     }
948 
949     /**
950      * <p>Deep comparison of array of <code>byte</code>. Length and all
951      * values are compared.</p>
952      *
953      * <p>The method {@link #append(byte, byte)} is used.</p>
954      *
955      * @param lhs  the left hand <code>byte[]</code>
956      * @param rhs  the right hand <code>byte[]</code>
957      * @return EqualsBuilder - used to chain calls.
958      */
959     public EqualsBuilder append(final byte[] lhs, final byte[] rhs) {
960         if (!isEquals) {
961             return this;
962         }
963         if (lhs == rhs) {
964             return this;
965         }
966         if (lhs == null || rhs == null) {
967             this.setEquals(false);
968             return this;
969         }
970         if (lhs.length != rhs.length) {
971             this.setEquals(false);
972             return this;
973         }
974         for (int i = 0; i < lhs.length && isEquals; ++i) {
975             append(lhs[i], rhs[i]);
976         }
977         return this;
978     }
979 
980     /**
981      * <p>Deep comparison of array of <code>double</code>. Length and all
982      * values are compared.</p>
983      *
984      * <p>The method {@link #append(double, double)} is used.</p>
985      *
986      * @param lhs  the left hand <code>double[]</code>
987      * @param rhs  the right hand <code>double[]</code>
988      * @return EqualsBuilder - used to chain calls.
989      */
990     public EqualsBuilder append(final double[] lhs, final double[] rhs) {
991         if (!isEquals) {
992             return this;
993         }
994         if (lhs == rhs) {
995             return this;
996         }
997         if (lhs == null || rhs == null) {
998             this.setEquals(false);
999             return this;
1000         }
1001         if (lhs.length != rhs.length) {
1002             this.setEquals(false);
1003             return this;
1004         }
1005         for (int i = 0; i < lhs.length && isEquals; ++i) {
1006             append(lhs[i], rhs[i]);
1007         }
1008         return this;
1009     }
1010 
1011     /**
1012      * <p>Deep comparison of array of <code>float</code>. Length and all
1013      * values are compared.</p>
1014      *
1015      * <p>The method {@link #append(float, float)} is used.</p>
1016      *
1017      * @param lhs  the left hand <code>float[]</code>
1018      * @param rhs  the right hand <code>float[]</code>
1019      * @return EqualsBuilder - used to chain calls.
1020      */
1021     public EqualsBuilder append(final float[] lhs, final float[] rhs) {
1022         if (!isEquals) {
1023             return this;
1024         }
1025         if (lhs == rhs) {
1026             return this;
1027         }
1028         if (lhs == null || rhs == null) {
1029             this.setEquals(false);
1030             return this;
1031         }
1032         if (lhs.length != rhs.length) {
1033             this.setEquals(false);
1034             return this;
1035         }
1036         for (int i = 0; i < lhs.length && isEquals; ++i) {
1037             append(lhs[i], rhs[i]);
1038         }
1039         return this;
1040     }
1041 
1042     /**
1043      * <p>Deep comparison of array of <code>boolean</code>. Length and all
1044      * values are compared.</p>
1045      *
1046      * <p>The method {@link #append(boolean, boolean)} is used.</p>
1047      *
1048      * @param lhs  the left hand <code>boolean[]</code>
1049      * @param rhs  the right hand <code>boolean[]</code>
1050      * @return EqualsBuilder - used to chain calls.
1051      */
1052     public EqualsBuilder append(final boolean[] lhs, final boolean[] rhs) {
1053         if (!isEquals) {
1054             return this;
1055         }
1056         if (lhs == rhs) {
1057             return this;
1058         }
1059         if (lhs == null || rhs == null) {
1060             this.setEquals(false);
1061             return this;
1062         }
1063         if (lhs.length != rhs.length) {
1064             this.setEquals(false);
1065             return this;
1066         }
1067         for (int i = 0; i < lhs.length && isEquals; ++i) {
1068             append(lhs[i], rhs[i]);
1069         }
1070         return this;
1071     }
1072 
1073     /**
1074      * <p>Returns <code>true</code> if the fields that have been checked
1075      * are all equal.</p>
1076      *
1077      * @return boolean
1078      */
1079     public boolean isEquals() {
1080         return this.isEquals;
1081     }
1082 
1083     /**
1084      * <p>Returns <code>true</code> if the fields that have been checked
1085      * are all equal.</p>
1086      *
1087      * @return <code>true</code> if all of the fields that have been checked
1088      *         are equal, <code>false</code> otherwise.
1089      *
1090      * @since 3.0
1091      */
1092     @Override
1093     public Boolean build() {
1094         return Boolean.valueOf(isEquals());
1095     }
1096 
1097     /**
1098      * Sets the <code>isEquals</code> value.
1099      *
1100      * @param isEquals The value to set.
1101      * @since 2.1
1102      */
1103     protected void setEquals(final boolean isEquals) {
1104         this.isEquals = isEquals;
1105     }
1106 
1107     /**
1108      * Reset the EqualsBuilder so you can use the same object again
1109      * @since 2.5
1110      */
1111     public void reset() {
1112         this.isEquals = true;
1113     }
1114 }