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));
+ }
+
+}