LANG-1034: Add support for recursive comparison to 
EqualsBuilder#reflectionEquals (closes #202)

minimal clean-ups: remove getter methods, improve javadoc, add unit test for 
reflectionAppend


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/0f6a292a
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/0f6a292a
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/0f6a292a

Branch: refs/heads/master
Commit: 0f6a292a29fedd49741310cd517ac4ba907bf8d4
Parents: 0095d8a
Author: pascalschumacher <pascalschumac...@gmx.net>
Authored: Sun Nov 6 19:38:43 2016 +0100
Committer: pascalschumacher <pascalschumac...@gmx.net>
Committed: Sun Nov 13 18:47:41 2016 +0100

----------------------------------------------------------------------
 src/changes/changes.xml                         |  1 +
 .../commons/lang3/builder/EqualsBuilder.java    | 78 ++++++--------------
 .../lang3/builder/EqualsBuilderTest.java        | 18 +++++
 3 files changed, 40 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/0f6a292a/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ecfa481..bed48fb 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -55,6 +55,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action issue="LANG-1070" type="fix" dev="pschumacher" due-to="Paul 
Pogonyshev">ArrayUtils#add confusing example in javadoc</action>
     <action issue="LANG-1271" type="fix" dev="pschumacher" due-to="Pierre 
Templier">StringUtils#isAnyEmpty and #isAnyBlank should return false for an 
empty array</action>
     <action issue="LANG-1155" type="fix" dev="pschumacher" due-to="Saif Asif, 
Thiago Andrade">Add StringUtils#unwrap</action>
+    <action issue="LANG-1034" type="add" dev="pschumacher" due-to="Yathos 
UG">Add support for recursive comparison to 
EqualsBuilder#reflectionEquals</action>
     <action issue="LANG-740" type="add" dev="pschumacher" due-to="James 
Sawle">Implementation of a Memomizer</action>
     <action issue="LANG-1258" type="add" dev="pschumacher" due-to="IG, 
Grzegorz Rożniecki">Add ArrayUtils#toStringArray method</action>
     <action issue="LANG-1160" type="add" dev="kinow">StringUtils#abbreviate 
should support 'custom ellipses' parameter</action>

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/0f6a292a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java 
b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
index 5f1c8e0..a58e799 100644
--- a/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
+++ b/src/main/java/org/apache/commons/lang3/builder/EqualsBuilder.java
@@ -229,19 +229,10 @@ public class EqualsBuilder implements Builder<Boolean> {
     //-------------------------------------------------------------------------
 
     /**
-     * Whether calls of {@link #reflectionAppend(Object, Object)}
-     * will test transient fields, too.
-     * @return boolean
-     */
-    public boolean isTestTransients() {
-        return testTransients;
-    }
-
-    /**
-     * Set testing transients behavior for calls 
-     * of {@link #reflectionAppend(Object, Object)}.
+     * Set whether to include transient fields when reflectively comparing 
objects.
      * @param testTransients whether to test transient fields
      * @return EqualsBuilder - used to chain calls.
+     * @since 3.6
      */
     public EqualsBuilder setTestTransients(boolean testTransients) {
         this.testTransients = testTransients;
@@ -249,21 +240,10 @@ public class EqualsBuilder implements Builder<Boolean> {
     }
 
     /**
-     * Whether calls of {@link #append(Object, Object)}
-     * will recursively test non primitive fields by
-     * using this <code>EqualsBuilder</code> or b<
-     * using <code>equals()</code>.
-     * @return boolean
-     */
-    public boolean isTestRecursive() {
-        return testRecursive;
-    }
-
-    /**
-     * Set recursive test behavior 
-     * of {@link #reflectionAppend(Object, Object)}.
+     * Set whether to include transient fields when reflectively comparing 
objects.
      * @param testRecursive  whether to do a recursive test
      * @return EqualsBuilder - used to chain calls.
+     * @since 3.6
      */
     public EqualsBuilder setTestRecursive(boolean testRecursive) {
         this.testRecursive = testRecursive;
@@ -271,19 +251,10 @@ public class EqualsBuilder implements Builder<Boolean> {
     }
 
     /**
-     * The superclass to reflect up to (maybe <code>null</code>)
-     * at reflective tests.
-     * @return Class  <code>null</code> is same as 
-     *  <code>java.lang.Object</code>
-     */
-    public Class<?> getReflectUpToClass() {
-        return reflectUpToClass;
-    }
-
-    /**
-     * Set the superclass to reflect up to
-     * at reflective tests.
+     * Set the superclass to reflect up to at reflective tests.
+     * @param reflectUpToClass the super class to reflect up to
      * @return EqualsBuilder - used to chain calls.
+     * @since 3.6
      */
     public EqualsBuilder setReflectUpToClass(Class<?> reflectUpToClass) {
         this.reflectUpToClass = reflectUpToClass;
@@ -291,18 +262,10 @@ public class EqualsBuilder implements Builder<Boolean> {
     }
 
     /**
-     * Fields names which will be ignored in any class
-     * by reflection tests.
-     * @return String[]  maybe null.
-     */
-    public String[] getExcludeFields() {
-        return excludeFields;
-    }
-
-    /**
      * Set field names to be excluded by reflection tests.
-     * @param excludeFields
+     * @param excludeFields the fields to exclude
      * @return EqualsBuilder - used to chain calls.
+     * @since 3.6
      */
     public EqualsBuilder setExcludeFields(String... excludeFields) {
         this.excludeFields = excludeFields;
@@ -430,7 +393,7 @@ public class EqualsBuilder implements Builder<Boolean> {
      * <p>It uses <code>AccessibleObject.setAccessible</code> to gain access 
to private
      * fields. This means that it will throw a security exception if run under
      * a security manager, if the permissions are not set up correctly. It is 
also
-     * not as efficient as testing explicitly. Non-primitive fields are 
compared using 
+     * not as efficient as testing explicitly. Non-primitive fields are 
compared using
      * <code>equals()</code>.</p>
      *
      * <p>If the testTransients parameter is set to <code>true</code>, 
transient
@@ -457,6 +420,7 @@ public class EqualsBuilder implements Builder<Boolean> {
      * @return <code>true</code> if the two Objects have tested equals.
      * 
      * @see EqualsExclude
+     * @since 3.6
      */
     public static boolean reflectionEquals(final Object lhs, final Object rhs, 
final boolean testTransients, final Class<?> reflectUpToClass,
             boolean testRecursive, final String... excludeFields) {
@@ -466,14 +430,13 @@ public class EqualsBuilder implements Builder<Boolean> {
         if (lhs == null || rhs == null) {
             return false;
         }
-        final EqualsBuilder equalsBuilder = new EqualsBuilder();
-        equalsBuilder.setExcludeFields(excludeFields)
+        return new EqualsBuilder()
+                    .setExcludeFields(excludeFields)
                     .setReflectUpToClass(reflectUpToClass)
                     .setTestTransients(testTransients)
-                    .setTestRecursive(testRecursive);
-        
-        equalsBuilder.reflectionAppend(lhs, rhs);
-        return equalsBuilder.isEquals();
+                    .setTestRecursive(testRecursive)
+                    .reflectionAppend(lhs, rhs)
+                    .isEquals();
     }
     
     /**
@@ -500,9 +463,9 @@ public class EqualsBuilder implements Builder<Boolean> {
      * @return EqualsBuilder - used to chain calls.
      */
     public EqualsBuilder reflectionAppend(final Object lhs, final Object rhs) {
-        if(!isEquals)
+        if (!isEquals) {
             return this;
-        
+        }
         if (lhs == rhs) {
             return this;
         }
@@ -510,6 +473,7 @@ public class EqualsBuilder implements Builder<Boolean> {
             isEquals = false;
             return this;
         }
+
         // Find the leaf class since there may be transients in the leaf
         // class or in classes between the leaf and root.
         // If we are not testing transients or a subclass has no ivars,
@@ -534,7 +498,7 @@ public class EqualsBuilder implements Builder<Boolean> {
             isEquals = false;
             return this;
         }
-        
+
         try {
             if (testClass.isArray()) {
                 append(lhs, rhs);
@@ -643,7 +607,7 @@ public class EqualsBuilder implements Builder<Boolean> {
         final Class<?> lhsClass = lhs.getClass();
         if (!lhsClass.isArray()) {
             // The simple case, not an array, just test the element
-            if(testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) {
+            if (testRecursive && !ClassUtils.isPrimitiveOrWrapper(lhsClass)) {
                 reflectionAppend(lhs, rhs);
             } else {
                 isEquals = lhs.equals(rhs);

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/0f6a292a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java 
b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
index c2551af..ccdd16f 100644
--- a/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
+++ b/src/test/java/org/apache/commons/lang3/builder/EqualsBuilderTest.java
@@ -1298,5 +1298,23 @@ public class EqualsBuilderTest {
         assertTrue(EqualsBuilder.reflectionEquals(one, two));
     }
 
+    @Test
+    public void testReflectionAppend() {
+        assertTrue(EqualsBuilder.reflectionEquals(null, null));
+
+        final TestObject o1 = new TestObject(4);
+        final TestObject o2 = new TestObject(5);
+        assertTrue(new EqualsBuilder().reflectionAppend(o1, o1).build());
+        assertFalse(new EqualsBuilder().reflectionAppend(o1, o2).build());
+
+        o2.setA(4);
+        assertTrue(new EqualsBuilder().reflectionAppend(o1, o2).build());
+
+        assertFalse(new EqualsBuilder().reflectionAppend(o1, this).build());
+
+        assertFalse(new EqualsBuilder().reflectionAppend(o1, null).build());
+        assertFalse(new EqualsBuilder().reflectionAppend(null, o2).build());
+    }
+
 }
 

Reply via email to