panda.lang.builder.ToStringBuilder Maven / Gradle / Ivy
Show all versions of panda-core Show documentation
package panda.lang.builder;
import panda.lang.Objects;
/**
*
* Assists in implementing {@link Object#toString()} methods.
*
*
* This class enables a good and consistent toString()
to be built for any class or
* object. This class aims to simplify the process by:
*
*
* - allowing field names
* - handling all types consistently
* - handling nulls consistently
* - outputting arrays and multi-dimensional arrays
* - enabling the detail level to be controlled for Objects and Collections
* - handling class hierarchies
*
*
* To use this class write code as follows:
*
*
*
* public class Person {
* String name;
* int age;
* boolean smoker;
*
* ...
*
* public String toString() {
* return new ToStringBuilder(this).
* append("name", name).
* append("age", age).
* append("smoker", smoker).
* toString();
* }
* }
*
*
* This will produce a toString of the format:
* Person@7f54[name=Stephen,age=29,smoker=false]
*
*
* To add the superclass toString
, use {@link #appendSuper}. To append the
* toString
from an object that is delegated to (or any other object), use
* {@link #appendToString}.
*
*
* Alternatively, there is a method that uses reflection to determine the fields to test. Because
* these fields are usually private, the method, reflectionToString
, uses
* AccessibleObject.setAccessible
to change the visibility of the fields. This will
* fail under a security manager, unless the appropriate permissions are set up correctly. It is
* also slower than testing explicitly.
*
*
* The exact format of the toString
is determined by the {@link ToStringStyle} passed
* into the constructor.
*
*
*/
public class ToStringBuilder implements Builder {
/**
* The default style of output to use, not null.
*/
private static volatile ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
// ----------------------------------------------------------------------------
/**
*
* Gets the default ToStringStyle
to use.
*
*
* This method gets a singleton default value, typically for the whole JVM. Changing this
* default should generally only be done during application startup. It is recommended to pass a
* ToStringStyle
to the constructor instead of using this global default.
*
*
* This method can be used from multiple threads. Internally, a volatile
variable
* is used to provide the guarantee that the latest value set using {@link #setDefaultStyle} is
* the value returned. It is strongly recommended that the default style is only changed during
* application startup.
*
*
* One reason for changing the default could be to have a verbose style during development and a
* compact style in production.
*
*
* @return the default ToStringStyle
, never null
*/
public static ToStringStyle getDefaultStyle() {
return defaultStyle;
}
/**
*
* Sets the default ToStringStyle
to use.
*
*
* This method sets a singleton default value, typically for the whole JVM. Changing this
* default should generally only be done during application startup. It is recommended to pass a
* ToStringStyle
to the constructor instead of changing this global default.
*
*
* This method is not intended for use from multiple threads. Internally, a
* volatile
variable is used to provide the guarantee that the latest value set is
* the value returned from {@link #getDefaultStyle}.
*
*
* @param style the default ToStringStyle
* @throws IllegalArgumentException if the style is null
*/
public static void setDefaultStyle(ToStringStyle style) {
if (style == null) {
throw new IllegalArgumentException("The style must not be null");
}
defaultStyle = style;
}
// ----------------------------------------------------------------------------
/**
* Current toString buffer, not null.
*/
private final StringBuilder buffer;
/**
* The object being output, may be null.
*/
private final Object object;
/**
* The style of output to use, not null.
*/
private final ToStringStyle style;
/**
*
* Constructs a builder for the specified object using the default output style.
*
*
* This default style is obtained from {@link #getDefaultStyle()}.
*
*/
public ToStringBuilder() {
this(null, null, null);
}
/**
*
* Constructs a builder for the specified object using the default output style.
*
*
* This default style is obtained from {@link #getDefaultStyle()}.
*
*
* @param object the Object to build a toString
for, not recommended to be null
*/
public ToStringBuilder(Object object) {
this(object, null, null);
}
/**
*
* Constructs a builder for the specified object using the a defined output style.
*
*
* If the style is null
, the default style is used.
*
*
* @param object the Object to build a toString
for, not recommended to be null
* @param style the style of the toString
to create, null uses the default style
*/
public ToStringBuilder(Object object, ToStringStyle style) {
this(object, style, null);
}
/**
*
* Constructs a builder for the specified object.
*
*
* If the style is null
, the default style is used.
*
*
* If the buffer is null
, a new one is created.
*
*
* @param object the Object to build a toString
for, not recommended to be null
* @param style the style of the toString
to create, null uses the default style
* @param buffer the StringBuilder
to populate, may be null
*/
public ToStringBuilder(Object object, ToStringStyle style, StringBuilder buffer) {
if (style == null) {
style = getDefaultStyle();
}
if (buffer == null) {
buffer = new StringBuilder(512);
}
this.buffer = buffer;
this.style = style;
this.object = object;
style.appendStart(buffer, object);
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a boolean
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(boolean value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a boolean
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(boolean[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a byte
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(byte value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a byte
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(byte[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a char
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(char value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a char
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(char[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a double
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(double value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a double
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(double[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a float
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(float value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a float
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(float[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
an int
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(int value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
an int
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(int[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a long
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(long value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a long
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(long[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
an Object
value.
*
*
* @param obj the value to add to the toString
* @return this
*/
public ToStringBuilder append(Object obj) {
style.append(buffer, null, obj, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
an Object
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(Object[] array) {
style.append(buffer, null, array, null);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a short
value.
*
*
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(short value) {
style.append(buffer, null, value);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append to the toString
a short
array.
*
*
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(short[] array) {
style.append(buffer, null, array, null);
return this;
}
/**
*
* Append to the toString
a boolean
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, boolean value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a boolean
array.
*
*
* @param fieldName the field name
* @param array the array to add to the hashCode
* @return this
*/
public ToStringBuilder append(String fieldName, boolean[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a boolean
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, boolean[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an byte
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, byte value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a byte
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, byte[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a byte
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, byte[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
a char
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, char value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a char
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, char[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a char
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, char[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
a double
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, double value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a double
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, double[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a double
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, double[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an float
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, float value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a float
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, float[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a float
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, float[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an int
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, int value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
an int
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, int[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
an int
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, int[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
a long
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, long value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a long
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, long[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a long
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, long[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an Object
value.
*
*
* @param fieldName the field name
* @param obj the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, Object obj) {
style.append(buffer, fieldName, obj, null);
return this;
}
/**
*
* Append to the toString
an Object
value.
*
*
* @param fieldName the field name
* @param obj the value to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, Object obj, boolean fullDetail) {
style.append(buffer, fieldName, obj, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an Object
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, Object[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
an Object
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, Object[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Append to the toString
an short
value.
*
*
* @param fieldName the field name
* @param value the value to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, short value) {
style.append(buffer, fieldName, value);
return this;
}
/**
*
* Append to the toString
a short
array.
*
*
* @param fieldName the field name
* @param array the array to add to the toString
* @return this
*/
public ToStringBuilder append(String fieldName, short[] array) {
style.append(buffer, fieldName, array, null);
return this;
}
/**
*
* Append to the toString
a short
array.
*
*
* A boolean parameter controls the level of detail to show. Setting true
will
* output the array in full. Setting false
will output a summary, typically the
* size of the array.
*
* @param fieldName the field name
* @param array the array to add to the toString
* @param fullDetail true
for detail, false
for summary info
* @return this
*/
public ToStringBuilder append(String fieldName, short[] array, boolean fullDetail) {
style.append(buffer, fieldName, array, Boolean.valueOf(fullDetail));
return this;
}
/**
*
* Appends with the same format as the default Object toString()
*
method. Appends the class name followed by
* {@link System#identityHashCode(java.lang.Object)}.
*
*
* @param object the Object
whose class name and id to output
* @return this
*/
public ToStringBuilder appendAsObjectToString(Object object) {
Objects.identityToString(this.getStringBuilder(), object);
return this;
}
// ----------------------------------------------------------------------------
/**
*
* Append the toString
from the superclass.
*
*
* This method assumes that the superclass uses the same ToStringStyle
as this one.
*
*
* If superToString
is null
, no change is made.
*
*
* @param superToString the result of super.toString()
* @return this
*/
public ToStringBuilder appendSuper(String superToString) {
if (superToString != null) {
style.appendSuper(buffer, superToString);
}
return this;
}
/**
*
* Append the toString
from another object.
*
*
* This method is useful where a class delegates most of the implementation of its properties to
* another class. You can then call toString()
on the other class and pass the
* result into this method.
*
*
*
* private AnotherObject delegate;
* private String fieldInThisClass;
*
* public String toString() {
* return new ToStringBuilder(this).appendToString(delegate.toString()).append(fieldInThisClass)
* .toString();
* }
*
*
* This method assumes that the other object uses the same ToStringStyle
as this
* one.
*
*
* If the toString
is null
, no change is made.
*
*
* @param toString the result of toString()
on another object
* @return this
*/
public ToStringBuilder appendToString(String toString) {
if (toString != null) {
style.appendToString(buffer, toString);
}
return this;
}
/**
*
* Returns the Object
being output.
*
*
* @return The object being output.
*/
public Object getObject() {
return object;
}
/**
*
* Gets the StringBuilder
being populated.
*
*
* @return the StringBuilder
being populated
*/
public StringBuilder getStringBuilder() {
return buffer;
}
// ----------------------------------------------------------------------------
/**
*
* Gets the ToStringStyle
being used.
*
*
* @return the ToStringStyle
being used
*/
public ToStringStyle getStyle() {
return style;
}
/**
*
* Returns the built toString
.
*
*
* This method appends the end of data indicator, and can only be called once. Use
* {@link #getStringBuilder} to get the current string state.
*
*
* If the object is null
, return the style's nullText
*
*
* @return the String toString
*/
@Override
public String toString() {
if (this.getObject() != null) {
style.appendEnd(this.getStringBuilder(), this.getObject());
}
return this.getStringBuilder().toString();
}
/**
* Returns the String that was build as an object representation. The default implementation
* utilizes the {@link #toString()} implementation.
*
* @return the String toString
* @see #toString()
*/
public String build() {
return toString();
}
}