You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ch...@apache.org on 2017/04/20 15:08:19 UTC

[3/6] [lang] LANG-1167: Added isExcludeNullValues to ReflectionToStringBuilder and test

LANG-1167: Added isExcludeNullValues to ReflectionToStringBuilder and test


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

Branch: refs/heads/master
Commit: 661d16d190708a1a396d8b75ba10738e4574c11d
Parents: 40b8ecd
Author: MarkDacek <ma...@richmond.edu>
Authored: Sat Mar 18 15:47:09 2017 -0400
Committer: MarkDacek <ma...@richmond.edu>
Committed: Sat Mar 18 15:47:09 2017 -0400

----------------------------------------------------------------------
 .../builder/ReflectionToStringBuilder.java      | 122 ++++++++++++++++++-
 ...ionToStringBuilderExcludeNullValuesTest.java |  99 +++++++++++++++
 2 files changed, 220 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/661d16d1/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
index d40a838..0b4d7e5 100644
--- a/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
+++ b/src/main/java/org/apache/commons/lang3/builder/ReflectionToStringBuilder.java
@@ -300,6 +300,64 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
         return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics)
                 .toString();
     }
+    
+    /**
+     * <p>
+     * Builds a <code>toString</code> value through reflection.
+     * </p>
+     *
+     * <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.
+     * </p>
+     *
+     * <p>
+     * If the <code>outputTransients</code> is <code>true</code>, transient fields will be output, otherwise they
+     * are ignored, as they are likely derived fields, and not part of the value of the Object.
+     * </p>
+     *
+     * <p>
+     * If the <code>outputStatics</code> is <code>true</code>, static fields will be output, otherwise they are
+     * ignored.
+     * </p>
+     *
+     * <p>
+     * Superclass fields will be appended up to and including the specified superclass. A null superclass is treated as
+     * <code>java.lang.Object</code>.
+     * </p>
+     *
+     * <p>
+     * If the style is <code>null</code>, the default <code>ToStringStyle</code> is used.
+     * </p>
+     *
+     * @param <T>
+     *            the type of the object
+     * @param object
+     *            the Object to be output
+     * @param style
+     *            the style of the <code>toString</code> to create, may be <code>null</code>
+     * @param outputTransients
+     *            whether to include transient fields
+     * @param outputStatics
+     *            whether to include static fields
+     * @param excludeNulls
+     *            whether to exclude fields whose values are null
+     * @param reflectUpToClass
+     *            the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @return the String result
+     * @throws IllegalArgumentException
+     *             if the Object is <code>null</code>
+     * 
+     * @see ToStringExclude
+     * @since 2.1
+     */
+    public static <T> String toString(
+            final T object, final ToStringStyle style, final boolean outputTransients,
+            final boolean outputStatics, boolean excludeNulls, final Class<? super T> reflectUpToClass) {
+        return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics, excludeNulls)
+                .toString();
+    }
 
     /**
      * Builds a String for a toString method excluding the given field names.
@@ -379,6 +437,11 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
      * Whether or not to append transient fields.
      */
     private boolean appendTransients = false;
+    
+    /**
+     * Whether or not to append fields that are null.
+     */
+    private boolean excludeNullValues;
 
     /**
      * Which field names to exclude from output. Intended for fields like <code>"password"</code>.
@@ -483,6 +546,38 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
         this.setAppendTransients(outputTransients);
         this.setAppendStatics(outputStatics);
     }
+    
+    /**
+     * Constructor.
+     *
+     * @param <T>
+     *            the type of the object
+     * @param object
+     *            the Object to build a <code>toString</code> for
+     * @param style
+     *            the style of the <code>toString</code> to create, may be <code>null</code>
+     * @param buffer
+     *            the <code>StringBuffer</code> to populate, may be <code>null</code>
+     * @param reflectUpToClass
+     *            the superclass to reflect up to (inclusive), may be <code>null</code>
+     * @param outputTransients
+     *            whether to include transient fields
+     * @param outputStatics
+     *            whether to include static fields
+     * @param excludeNullValues
+     *            whether to exclude fields who value is null
+     * @since 2.1
+     */
+    public <T> ReflectionToStringBuilder(
+            final T object, final ToStringStyle style, final StringBuffer buffer,
+            final Class<? super T> reflectUpToClass, final boolean outputTransients, final boolean outputStatics,
+            final boolean excludeNullValues) {
+        super(checkNotNull(object), style, buffer);
+        this.setUpToClass(reflectUpToClass);
+        this.setAppendTransients(outputTransients);
+        this.setAppendStatics(outputStatics);
+        this.setExcludeNullValues(excludeNullValues);
+    }
 
     /**
      * Returns whether or not to append the given <code>Field</code>.
@@ -547,7 +642,9 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
                     // Warning: Field.get(Object) creates wrappers objects
                     // for primitive types.
                     final Object fieldValue = this.getValue(field);
-                    this.append(fieldName, fieldValue);
+                    if(!excludeNullValues || fieldValue != null){
+                        this.append(fieldName, fieldValue);
+                    }
                 } catch (final IllegalAccessException ex) {
                     //this can't happen. Would get a Security exception
                     // instead
@@ -619,6 +716,17 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
     public boolean isAppendTransients() {
         return this.appendTransients;
     }
+    
+    /**
+     * <p>
+     * Gets whether or not to append fields whose values are null.
+     * </p>
+     *
+     * @return Whether or not to append fields whose values are null.
+     */
+    public boolean isExcludeNullValues() {
+        return this.excludeNullValues;
+    }
 
     /**
      * <p>
@@ -658,6 +766,18 @@ public class ReflectionToStringBuilder extends ToStringBuilder {
     public void setAppendTransients(final boolean appendTransients) {
         this.appendTransients = appendTransients;
     }
+    
+    /**
+     * <p>
+     * Sets whether or not to append fields whose values are null.
+     * </p>
+     *
+     * @param excludeNullValues
+     *            Whether or not to append fields whose values are null.
+     */
+    public void setExcludeNullValues(final boolean excludeNullValues) {
+        this.excludeNullValues = excludeNullValues;
+    }
 
     /**
      * Sets the field names to exclude.

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/661d16d1/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java
new file mode 100644
index 0000000..be368d6
--- /dev/null
+++ b/src/test/java/org/apache/commons/lang3/builder/ReflectionToStringBuilderExcludeNullValuesTest.java
@@ -0,0 +1,99 @@
+package org.apache.commons.lang3.builder;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ReflectionToStringBuilderExcludeNullValuesTest {
+
+    class TestFixture{
+        private Integer testIntegerField;
+        private String testStringField;
+        
+        public TestFixture(Integer a, String b){
+            this.testIntegerField = a;
+            this.testStringField = b;
+        }
+    }
+    
+    private static final String INTEGER_FIELD_NAME = "testIntegerField";
+    private static final String STRING_FIELD_NAME = "testStringField";
+    private final TestFixture BOTH_NON_NULL = new TestFixture(0, "str");
+    private final TestFixture FIRST_NULL = new TestFixture(null, "str");
+    private final TestFixture SECOND_NULL = new TestFixture(0, null);
+    private final TestFixture BOTH_NULL = new TestFixture(null, null);
+    
+    @Test
+    public void test_NonExclude(){
+        //normal case=
+        String toString = ReflectionToStringBuilder.toString(BOTH_NON_NULL, null, false, false, false, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        //make one null
+        toString = ReflectionToStringBuilder.toString(FIRST_NULL, null, false, false, false, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        //other one null
+        toString = ReflectionToStringBuilder.toString(SECOND_NULL, null, false, false, false, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+
+        //make the both null
+        toString = ReflectionToStringBuilder.toString(BOTH_NULL, null, false, false, false, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+    }
+    
+    @Test
+    public void test_excludeNull(){
+        
+        //test normal case
+        String toString = ReflectionToStringBuilder.toString(BOTH_NON_NULL, null, false, false, true, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        //make one null
+        toString = ReflectionToStringBuilder.toString(FIRST_NULL, null, false, false, true, null);
+        assertFalse(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        //other one null
+        toString = ReflectionToStringBuilder.toString(SECOND_NULL, null, false, false, true, null);
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertFalse(toString.contains(STRING_FIELD_NAME));
+        
+        //both null
+        toString = ReflectionToStringBuilder.toString(BOTH_NULL, null, false, false, true, null);
+        assertFalse(toString.contains(INTEGER_FIELD_NAME));
+        assertFalse(toString.contains(STRING_FIELD_NAME));
+    }
+    
+    @Test
+    public void test_ConstructorOption(){
+        ReflectionToStringBuilder builder = new ReflectionToStringBuilder(BOTH_NON_NULL, null, null, null, false, false, false);
+        builder.setExcludeNullValues(true);
+        assertTrue(builder.isExcludeNullValues());
+        
+        String toString = builder.toString();
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        builder = new ReflectionToStringBuilder(FIRST_NULL, null, null, null, false, false, true);
+        toString = builder.toString();
+        assertFalse(toString.contains(INTEGER_FIELD_NAME));
+        assertTrue(toString.contains(STRING_FIELD_NAME));
+        
+        builder = new ReflectionToStringBuilder(SECOND_NULL, null, null, null, false, false, true);
+        toString = builder.toString();
+        assertTrue(toString.contains(INTEGER_FIELD_NAME));
+        assertFalse(toString.contains(STRING_FIELD_NAME));
+        
+        builder = new ReflectionToStringBuilder(BOTH_NULL, null, null, null, false, false, true);
+        toString = builder.toString();
+        assertFalse(toString.contains(INTEGER_FIELD_NAME));
+        assertFalse(toString.contains(STRING_FIELD_NAME));
+    }
+
+}