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