diff --git a/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java b/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java index 17b10db08..da2aa1d0c 100644 --- a/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java +++ b/src/java/org/apache/commons/lang/builder/ReflectionToStringBuilder.java @@ -104,7 +104,7 @@ * @author Stephen Colebourne * @author Pete Gieser * @since 2.0 - * @version $Id: ReflectionToStringBuilder.java,v 1.11 2003/09/07 14:32:34 psteitz Exp $ + * @version $Id: ReflectionToStringBuilder.java,v 1.12 2003/10/23 22:25:16 ggregory Exp $ */ public class ReflectionToStringBuilder extends ToStringBuilder { @@ -114,9 +114,9 @@ public class ReflectionToStringBuilder extends ToStringBuilder { */ private static ThreadLocal registry = new ThreadLocal() { protected synchronized Object initialValue() { - // The HashSet implementation is not synchronized, - // which is just what we need here. - return new HashSet(); + // The HashSet implementation is not synchronized, + // which is just what we need here. + return new HashSet(); } }; @@ -150,7 +150,7 @@ static boolean isRegistered(Object value) { static void register(Object value) { getRegistry().add(value); } - + /** *

This method uses reflection to build a suitable * toString using the default ToStringStyle. @@ -168,7 +168,7 @@ static void register(Object value) { * @throws IllegalArgumentException if the Object is null */ public static String toString(Object object) { - return toString(object, null, false, null); + return toString(object, null, false, false, null); } /** @@ -194,7 +194,7 @@ public static String toString(Object object) { * ToStringStyle is null */ public static String toString(Object object, ToStringStyle style) { - return toString(object, style, false, null); + return toString(object, style, false, false, null); } /** @@ -224,7 +224,79 @@ public static String toString(Object object, ToStringStyle style) { * @throws IllegalArgumentException if the Object is null */ public static String toString(Object object, ToStringStyle style, boolean outputTransients) { - return toString(object, style, outputTransients, null); + return toString(object, style, outputTransients, false, null); + } + + /** + *

This method uses reflection to build a suitable + * toString.

+ * + *

It uses AccessibleObject.setAccessible 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.

+ * + *

If the outputTransients is true, + * transient fields will be output, otherwise they are ignored, + * as they are likely derived fields, and not part of the value of the + * Object.

+ * + *

If the outputStatics is true, + * static fields will be output, otherwise they are ignored.

+ * + *

Static fields will not be included. Superclass fields will be appended.

+ * + *

If the style is null, the default + * ToStringStyle is used.

+ * + * @param object the Object to be output + * @param style the style of the toString to create, + * may be null + * @param outputTransients whether to include transient fields + * @param outputStatics whether to include transient fields + * @return the String result + * @throws IllegalArgumentException if the Object is null + */ + public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics) { + return toString(object, style, outputTransients, outputStatics, null); + } + + /** + *

This method uses reflection to build a suitable + * toString.

+ * + *

It uses AccessibleObject.setAccessible 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.

+ * + *

If the outputTransients is true, + * transient fields will be output, otherwise they are ignored, + * as they are likely derived fields, and not part of the value of the + * Object.

+ * + *

If the outputStatics is true, + * static fields will be output, otherwise they are ignored.

+ * + *

Superclass fields will be appended up to and including the + * specified superclass. A null superclass is treated as + * java.lang.Object.

+ * + *

If the style is null, the default + * ToStringStyle is used.

+ * + * @param object the Object to be output + * @param style the style of the toString to create, + * may be null + * @param outputTransients whether to include transient fields + * @param outputStatics whether to include static fields + * @param reflectUpToClass the superclass to reflect up to (inclusive), + * may be null + * @return the String result + * @throws IllegalArgumentException if the Object is null + */ + public static String toString(Object object, ToStringStyle style, boolean outputTransients, boolean outputStatics, Class reflectUpToClass) { + return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients, outputStatics).toString(); } /** @@ -247,6 +319,8 @@ public static String toString(Object object, ToStringStyle style, boolean output * *

If the style is null, the default * ToStringStyle is used.

+ * + * @deprecated Use {@link #toString(Object,ToStringStyle,boolean,boolean,Class)} * * @param object the Object to be output * @param style the style of the toString to create, @@ -257,14 +331,97 @@ public static String toString(Object object, ToStringStyle style, boolean output * @return the String result * @throws IllegalArgumentException if the Object is null */ - public static String toString( - Object object, - ToStringStyle style, - boolean outputTransients, - Class reflectUpToClass) { + public static String toString(Object object, ToStringStyle style, boolean outputTransients, Class reflectUpToClass) { return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString(); } + /** + * TODO: Is this convenience API really needed? + * + *

This method uses reflection to build a suitable + * toString value which includes static fields.

+ * + *

It uses AccessibleObject.setAccessible 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.

+ * + *

Transient fields are not output.

+ * + *

Superclass fields will be appended up to and including + * java.lang.Object.

+ * + *

The default ToStringStyle is used.

+ * + * @param object the Object to be output + * @param reflectUpToClass the superclass to reflect up to (inclusive), + * may be null + * @return the String result + * @throws IllegalArgumentException if the Object is null + */ + public static Object toStringWithStatics(Object object) { + return toString(object, null, false, true, null); + } + + /** + * TODO: Is this convenience API really needed? + * + *

This method uses reflection to build a suitable + * toString value which includes static fields.

+ * + *

It uses AccessibleObject.setAccessible 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.

+ * + *

Transient fields are not output.

+ * + *

Superclass fields will be appended up to and including the specified superclass. + * A null superclass is treated as java.lang.Object.

+ * + *

The default ToStringStyle is used.

+ * + * @param object the Object to be output + * @param reflectUpToClass the superclass to reflect up to (inclusive), + * may be null + * @return the String result + * @throws IllegalArgumentException if the Object is null + */ + public static Object toStringWithStatics(Object object, Class reflectUpToClass) { + return toString(object, null, false, true, reflectUpToClass); + } + + /** + * TODO: Is this convenience API really needed? + * + *

This method uses reflection to build a suitable + * toString value which includes static fields.

+ * + *

It uses AccessibleObject.setAccessible 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.

+ * + *

Transient fields are not output.

+ * + *

Superclass fields will be appended up to and including the specified superclass. + * A null superclass is treated as java.lang.Object.

+ * + *

If the style is null, the default + * ToStringStyle is used.

+ * + * @param object the Object to be output + * @param style the style of the toString to create, + * may be null + * @param reflectUpToClass the superclass to reflect up to (inclusive), + * may be null + * @return the String result + * @throws IllegalArgumentException if the Object is null + */ + public static Object toStringWithStatics(Object object, ToStringStyle toStringStyle, Class reflectUpToClass) { + return toString(object, toStringStyle, false, true, reflectUpToClass); + } + /** *

Unregisters the given object.

* @@ -276,6 +433,11 @@ static void unregister(Object value) { getRegistry().remove(value); } + /** + * Whether or not to append static fields. + */ + private boolean appendStatics = false; + /** * Whether or not to append transient fields. */ @@ -340,6 +502,8 @@ public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffe /** * Constructor. * + * @deprecated Use {@link #ReflectionToStringBuilder(Object,ToStringStyle,StringBuffer,Class,boolean,boolean)}. + * * @param object the Object to build a toString for, * must not be null * @param style the style of the toString to create, @@ -361,21 +525,57 @@ public ReflectionToStringBuilder( this.setAppendTransients(outputTransients); } + /** + * Constructor. + * + * @param object the Object to build a toString for, + * must not be null + * @param style the style of the toString to create, + * may be null + * @param buffer the StringBuffer to populate, may be + * null + * @param reflectUpToClass the superclass to reflect up to (inclusive), + * may be null + * @param outputTransients whether to include transient fields + * @param outputStatics whether to include static fields + */ + public ReflectionToStringBuilder( + Object object, + ToStringStyle style, + StringBuffer buffer, + Class reflectUpToClass, + boolean outputTransients, + boolean outputStatics) { + super(object, style, buffer); + this.setUpToClass(reflectUpToClass); + this.setAppendTransients(outputTransients); + this.setAppendStatics(outputStatics); + } + /** * Returns whether or not to append the given Field. * * @param field The Field to test. * @return Whether or not to append the given Field. */ protected boolean accept(Field field) { - String fieldName = field.getName(); - return (fieldName.indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) == -1) - && (this.isAppendTransients() || !Modifier.isTransient(field.getModifiers())) - && (!Modifier.isStatic(field.getModifiers())); + if (field.getName().indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) != -1) { + // Reject field from inner class. + return false; + } + if (Modifier.isTransient(field.getModifiers()) && !this.isAppendTransients()) { + // transients. + return false; + } + if (Modifier.isStatic(field.getModifiers()) && !this.isAppendStatics()) { + // transients. + return false; + } + return true; } /** @@ -438,7 +638,7 @@ protected void appendFieldsIn(Class clazz) { this.unregisterObject(); } } - + /** *

Gets the last super class to stop appending fields for.

* @@ -459,6 +659,15 @@ protected Object getValue(Field field) throws IllegalArgumentException, IllegalA return field.get(this.getObject()); } + /** + *

Gets whether or not to append static fields.

+ * + * @return Whether or not to append static fields. + */ + public boolean isAppendStatics() { + return this.appendStatics; + } + /** *

Gets whether or not to append transient fields.

* @@ -467,7 +676,7 @@ protected Object getValue(Field field) throws IllegalArgumentException, IllegalA public boolean isAppendTransients() { return this.appendTransients; } - + /** *

Append to the toString an Object * array.

@@ -488,6 +697,15 @@ void registerObject() { register(this.getObject()); } + /** + *

Sets whether or not to append static fields.

+ * + * @param appendStatics Whether or not to append static fields. + */ + public void setAppendStatics(boolean appendStatics) { + this.appendStatics = appendStatics; + } + /** *

Sets whether or not to append transient fields.

* diff --git a/src/java/org/apache/commons/lang/builder/ToStringBuilder.java b/src/java/org/apache/commons/lang/builder/ToStringBuilder.java index 2d7de946e..d94a6e7f9 100644 --- a/src/java/org/apache/commons/lang/builder/ToStringBuilder.java +++ b/src/java/org/apache/commons/lang/builder/ToStringBuilder.java @@ -125,7 +125,7 @@ * @author Gary Gregory * @author Pete Gieser * @since 1.0 - * @version $Id: ToStringBuilder.java,v 1.29 2003/08/23 00:21:49 ggregory Exp $ + * @version $Id: ToStringBuilder.java,v 1.30 2003/10/23 22:25:16 ggregory Exp $ */ public class ToStringBuilder { @@ -176,7 +176,7 @@ public static String reflectionToString(Object object, ToStringStyle style) { * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean) */ public static String reflectionToString(Object object, ToStringStyle style, boolean outputTransients) { - return ReflectionToStringBuilder.toString(object, style, outputTransients, null); + return ReflectionToStringBuilder.toString(object, style, outputTransients, false, null); } /** @@ -190,7 +190,7 @@ public static String reflectionToString( ToStringStyle style, boolean outputTransients, Class reflectUpToClass) { - return ReflectionToStringBuilder.toString(object, style, outputTransients, reflectUpToClass); + return ReflectionToStringBuilder.toString(object, style, outputTransients, false, reflectUpToClass); } /** @@ -1035,6 +1035,16 @@ public ToStringBuilder appendToString(String toString) { return this; } + /** + *

Returns the Object being output.

+ * + * @return The object being output. + * @since 2.0 + */ + public Object getObject() { + return object; + } + /** *

Gets the StringBuffer being populated.

* @@ -1069,14 +1079,4 @@ public String toString() { return buffer.toString(); } - /** - *

Returns the Object being output.

- * - * @return The object being output. - * @since 2.0 - */ - public Object getObject() { - return object; - } - } diff --git a/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java b/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java index 81b6661be..673784051 100644 --- a/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java +++ b/src/test/org/apache/commons/lang/builder/ToStringBuilderTest.java @@ -68,7 +68,7 @@ * @author Stephen Colebourne * @author Gary Gregory * @author Alex Chaffee - * @version $Id: ToStringBuilderTest.java,v 1.10 2003/08/18 02:22:26 bayard Exp $ + * @version $Id: ToStringBuilderTest.java,v 1.11 2003/10/23 22:26:00 ggregory Exp $ */ public class ToStringBuilderTest extends TestCase { @@ -840,4 +840,88 @@ public void testBooleanArrayArray() { assertEquals(baseStr + "[]", new ToStringBuilder(base).append((Object) array).toString()); } + public void testSimpleReflectionStatics() { + SimpleReflectionStaticFieldsFixture instance1 = new SimpleReflectionStaticFieldsFixture(); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toString(instance1, null, false, true, SimpleReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toString(instance1, null, true, true, SimpleReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toStringWithStatics(instance1, SimpleReflectionStaticFieldsFixture.class)); + } + + /** + * Tests ReflectionToStringBuilder.toString() for statics. + */ + public void testReflectionStatics() { + ReflectionStaticFieldsFixture instance1 = new ReflectionStaticFieldsFixture(); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345,instanceString=instanceString,instanceInt=67890]", + ReflectionToStringBuilder.toString(instance1, null, false, true, ReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345,staticTransientString=staticTransientString,staticTransientInt=54321,instanceString=instanceString,instanceInt=67890,transientString=transientString,transientInt=98765]", + ReflectionToStringBuilder.toString(instance1, null, true, true, ReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345,instanceString=instanceString,instanceInt=67890]", + ReflectionToStringBuilder.toStringWithStatics(instance1, null, ReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString=staticString,staticInt=12345,instanceString=instanceString,instanceInt=67890]", + ReflectionToStringBuilder.toStringWithStatics(instance1, ReflectionStaticFieldsFixture.class)); + } + + /** + * Tests ReflectionToStringBuilder.toString() for statics. + */ + public void testInheritedReflectionStatics() { + InheritedReflectionStaticFieldsFixture instance1 = new InheritedReflectionStaticFieldsFixture(); + assertEquals( + this.toBaseString(instance1) + "[staticString2=staticString2,staticInt2=67890]", + ReflectionToStringBuilder.toString(instance1, null, false, true, InheritedReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString2=staticString2,staticInt2=67890,staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toString(instance1, null, false, true, SimpleReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString2=staticString2,staticInt2=67890,staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toStringWithStatics(instance1, null, SimpleReflectionStaticFieldsFixture.class)); + assertEquals( + this.toBaseString(instance1) + "[staticString2=staticString2,staticInt2=67890,staticString=staticString,staticInt=12345]", + ReflectionToStringBuilder.toStringWithStatics(instance1, SimpleReflectionStaticFieldsFixture.class)); + } + + /** + * Tests ReflectionToStringBuilder.toString() for statics. + */ + class ReflectionStaticFieldsFixture { + static final String staticString = "staticString"; + static final int staticInt = 12345; + static final transient String staticTransientString = "staticTransientString"; + static final transient int staticTransientInt = 54321; + String instanceString = "instanceString"; + int instanceInt = 67890; + transient String transientString = "transientString"; + transient int transientInt = 98765; + } + + /** + * Test fixture for ReflectionToStringBuilder.toString() for statics. + */ + class SimpleReflectionStaticFieldsFixture { + static final String staticString = "staticString"; + static final int staticInt = 12345; + } + + /** + * Test fixture for ReflectionToStringBuilder.toString() for statics. + */ + class InheritedReflectionStaticFieldsFixture extends SimpleReflectionStaticFieldsFixture { + static final String staticString2 = "staticString2"; + static final int staticInt2 = 67890; + } + }