All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.lang.builder.ToStringStyle Maven / Gradle / Ivy

package panda.lang.builder;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.WeakHashMap;

import panda.lang.Classes;
import panda.lang.Objects;
import panda.lang.Strings;
import panda.lang.Systems;


/**
 * 

Controls String formatting for {@link ToStringBuilder}. * The main public interface is always via ToStringBuilder.

* *

These classes are intended to be used as Singletons. * There is no need to instantiate a new style each time. A program * will generally use one of the predefined constants on this class. * *

If required, a subclass can override as many or as few of the * methods as it requires. Each object type (from boolean * to long to Object to int[]) has * its own methods to output it. Most have two versions, detail and summary. * *

For example, the detail version of the array based methods will * output the whole array, whereas the summary method will just output * the array length.

* *

If you want to format the output of certain objects, such as dates, you * must create a subclass and override a method. *

 * public class MyStyle extends ToStringStyle {
 *   protected void appendDetail(StringBuilder buffer, String fieldName, Object value) {
 *     if (value instanceof Date) {
 *       value = FastDateFormat.getInstance("yyyy-MM-dd").format(value);
 *     }
 *     buffer.append(value);
 *   }
 * }
 * 
*

* */ public abstract class ToStringStyle implements Serializable { /** * Serialization version ID. */ private static final long serialVersionUID = -2587890625525655916L; /** * The default toString style. Using the Using the Person example from * {@link ToStringBuilder}, the output would look like this: * *
	 * Person@182f0db(name=John Doe,age=33,smoker=false)
	 * 
*/ public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle(); /** * The multi line toString style. Using the Using the Person example from * {@link ToStringBuilder}, the output would look like this: * *
	 * Person@182f0db(
	 *   name=John Doe
	 *   age=33
	 *   smoker=false
	 * )
	 * 
*/ public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle(); /** * The no field names toString style. Using the Using the Person example from * {@link ToStringBuilder}, the output would look like this: * *
	 * Person@182f0db(John Doe,33,false)
	 * 
*/ public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle(); /** * The short prefix toString style. Using the Person example from * {@link ToStringBuilder}, the output would look like this: * *
	 * Person(name=John Doe,age=33,smoker=false)
	 * 
* */ public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle(); /** * The simple toString style. Using the Using the Person example from * {@link ToStringBuilder}, the output would look like this: * *
	 * John Doe,33,false
	 * 
*/ public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle(); /** *

* A registry of objects used by reflectionToString methods to detect cyclical * object references and avoid infinite loops. *

*/ private static final ThreadLocal> REGISTRY = new ThreadLocal>(); /** *

* Returns the registry of objects being traversed by the reflectionToString * methods in the current thread. *

* * @return Set the registry of objects being traversed */ static Map getRegistry() { return REGISTRY.get(); } /** *

* Returns true if the registry contains the given object. Used by the reflection * methods to avoid infinite loops. *

* * @param value The object to lookup in the registry. * @return boolean true if the registry contains the given object. */ static boolean isRegistered(Object value) { Map m = getRegistry(); return m != null && m.containsKey(value); } /** *

* Registers the given object. Used by the reflection methods to avoid infinite loops. *

* * @param value The object to register. */ static void register(Object value) { if (value != null) { Map m = getRegistry(); if (m == null) { REGISTRY.set(new WeakHashMap()); } getRegistry().put(value, null); } } /** *

* Unregisters the given object. *

*

* Used by the reflection methods to avoid infinite loops. *

* * @param value The object to unregister. */ static void unregister(Object value) { if (value != null) { Map m = getRegistry(); if (m != null) { m.remove(value); if (m.isEmpty()) { REGISTRY.remove(); } } } } /** * Whether to use the field names, the default is true. */ private boolean useFieldNames = true; /** * Whether to use the class name, the default is true. */ private boolean useClassName = true; /** * Whether to use short class names, the default is false. */ private boolean useShortClassName = false; /** * Whether to use the identity hash code, the default is true. */ private boolean useIdentityHashCode = true; /** * The content start '{'. */ private String contentStart = "{"; /** * The content end '}'. */ private String contentEnd = "}"; /** * The field name value separator '='. */ private String fieldNameValueSeparator = "="; /** * Whether the field separator should be added before any other fields. */ private boolean fieldSeparatorAtStart = false; /** * Whether the field separator should be added after any other fields. */ private boolean fieldSeparatorAtEnd = false; /** * The field separator ','. */ private String fieldSeparator = ","; /** * The array start '['. */ private String arrayStart = "["; /** * The array separator ','. */ private String arraySeparator = ","; /** * The array end ']'. */ private String arrayEnd = "]"; /** * The value to use when fullDetail is null, the default value is true * . */ private boolean defaultFullDetail = false; /** * The default detail size * . */ private int defaultDetailSize = 10; /** * The null text '<null>'. */ private String nullText = ""; /** * The summary size text start '. */ private String sizeStartText = "'>'. */ private String sizeEndText = ">"; /** * The summary object text start '<'. */ private String summaryObjectStartText = "<"; /** * The summary object text start '>'. */ private String summaryObjectEndText = ">"; // ---------------------------------------------------------------------------- /** *

* Constructor. *

*/ protected ToStringStyle() { super(); } // ---------------------------------------------------------------------------- /** *

* Append to the toString the superclass toString. *

*

* NOTE: It assumes that the toString has been created from the same ToStringStyle. *

*

* A null superToString is ignored. *

* * @param buffer the StringBuilder to populate * @param superToString the super.toString() */ public void appendSuper(StringBuilder buffer, String superToString) { appendToString(buffer, superToString); } /** *

* Append to the toString another toString. *

*

* NOTE: It assumes that the toString has been created from the same ToStringStyle. *

*

* A null toString is ignored. *

* * @param buffer the StringBuilder to populate * @param toString the additional toString */ public void appendToString(StringBuilder buffer, String toString) { if (toString != null) { int pos1 = toString.indexOf(contentStart) + contentStart.length(); int pos2 = toString.lastIndexOf(contentEnd); if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) { String data = toString.substring(pos1, pos2); if (fieldSeparatorAtStart) { removeLastFieldSeparator(buffer); } buffer.append(data); appendFieldSeparator(buffer); } } } /** *

* Append to the toString the start of data indicator. *

* * @param buffer the StringBuilder to populate * @param object the Object to build a toString for */ public void appendStart(StringBuilder buffer, Object object) { if (object != null) { appendClassName(buffer, object); appendIdentityHashCode(buffer, object); appendContentStart(buffer); if (fieldSeparatorAtStart) { appendFieldSeparator(buffer); } } } /** *

* Append to the toString the end of data indicator. *

* * @param buffer the StringBuilder to populate * @param object the Object to build a toString for. */ public void appendEnd(StringBuilder buffer, Object object) { if (this.fieldSeparatorAtEnd == false) { removeLastFieldSeparator(buffer); } appendContentEnd(buffer); unregister(object); } /** *

* Remove the last field separator from the buffer. *

* * @param buffer the StringBuilder to populate */ protected void removeLastFieldSeparator(StringBuilder buffer) { int len = buffer.length(); int sepLen = fieldSeparator.length(); if (len > 0 && sepLen > 0 && len >= sepLen) { boolean match = true; for (int i = 0; i < sepLen; i++) { if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) { match = false; break; } } if (match) { buffer.setLength(len - sepLen); } } } // ---------------------------------------------------------------------------- /** *

* Append to the toString an Object value, printing the full * toString of the Object passed in. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, Object value, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (value == null) { appendNullText(buffer, fieldName); } else { appendInternal(buffer, fieldName, value, isFullDetail(fullDetail) ? Integer.MAX_VALUE : defaultDetailSize); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString an Object, correctly interpreting its type. *

*

* This method performs the main lookup by Class type to correctly route arrays, * Collections, Maps and Objects to the appropriate * method. *

*

* Either detail or summary views can be specified. *

*

* If a cycle is detected, an object will be appended with the Object.toString() * format. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString, not null * @param detailSize the size of detail item to output */ protected void appendInternal(StringBuilder buffer, String fieldName, Object value, int detailSize) { if (isRegistered(value) && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) { appendCyclicObject(buffer, fieldName, value); return; } register(value); try { if (value instanceof Collection) { appendCollection(buffer, fieldName, (Collection)value); } else if (value instanceof Map) { appendMap(buffer, fieldName, (Map)value); } else if (value instanceof long[]) { appendArray(buffer, fieldName, (long[])value, detailSize); } else if (value instanceof int[]) { appendArray(buffer, fieldName, (int[])value, detailSize); } else if (value instanceof short[]) { appendArray(buffer, fieldName, (short[])value, detailSize); } else if (value instanceof byte[]) { appendArray(buffer, fieldName, (byte[])value, detailSize); } else if (value instanceof char[]) { appendArray(buffer, fieldName, (char[])value, detailSize); } else if (value instanceof double[]) { appendArray(buffer, fieldName, (double[])value, detailSize); } else if (value instanceof float[]) { appendArray(buffer, fieldName, (float[])value, detailSize); } else if (value instanceof boolean[]) { appendArray(buffer, fieldName, (boolean[])value, detailSize); } else if (value.getClass().isArray()) { appendArray(buffer, fieldName, (Object[])value, detailSize); } else if (Classes.isImmutable(value.getClass())) { appendElement(buffer, fieldName, value); } else { appendObject(buffer, fieldName, value); } } finally { unregister(value); } } /** *

* Append to the toString an Object value that has been detected to * participate in a cycle. This implementation will print the standard string value of the * value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString, not null */ protected void appendCyclicObject(StringBuilder buffer, String fieldName, Object value) { Objects.identityToString(buffer, value); } /** *

* Append to the toString an Object value, printing the full detail of * the Object. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString, not null */ protected void appendElement(StringBuilder buffer, String fieldName, Object value) { buffer.append(value); } /** *

* Append to the toString an Object value, printing the full detail of * the Object. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString, not null */ protected void appendObject(StringBuilder buffer, String fieldName, Object value) { buffer.append(contentStart); buffer.append(value); buffer.append(contentEnd); } /** *

* Append to the toString a Collection. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param coll the Collection to add to the toString, not * null */ protected void appendCollection(StringBuilder buffer, String fieldName, Collection coll) { buffer.append(coll); } /** *

* Append to the toString a Map. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param map the Map to add to the toString, not null */ protected void appendMap(StringBuilder buffer, String fieldName, Map map) { buffer.append(map); } /** *

* Append to the toString an Object value, printing a summary of the * Object. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, Object value) { buffer.append(summaryObjectStartText); buffer.append(getShortClassName(value.getClass())); buffer.append(summaryObjectEndText); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a long value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, long value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a long value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, long value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString an int value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, int value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString an int value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, int value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a short value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, short value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a short value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, short value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a byte value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, byte value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a byte value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, byte value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a char value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, char value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a char value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, char value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a double value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, double value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a double value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, double value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a float value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, float value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a float value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, float value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a boolean value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param value the value to add to the toString */ public void append(StringBuilder buffer, String fieldName, boolean value) { appendFieldStart(buffer, fieldName); appendElement(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString a boolean value. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param value the value to add to the toString */ protected void appendElement(StringBuilder buffer, String fieldName, boolean value) { buffer.append(value); } /** *

* Append to the toString an Object array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, Object[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } // ---------------------------------------------------------------------------- /** *

* Append to the toString the detail of a Object array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, Object[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } Object item = array[i]; if (item == null) { appendNullText(buffer, fieldName); } else { appendInternal(buffer, fieldName, item, detailSize); } } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of an Object array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, Object[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of an Object array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, Object[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a long array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, long[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a long array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, long[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a long array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, long[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a long array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, long[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString an int array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, int[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a int array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, int[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of an int array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, int[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of an int array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, int[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a short array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, short[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a short array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, short[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a short array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, short[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a short array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, short[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a byte array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, byte[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a byte array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, byte[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a byte array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, byte[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a byte array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, byte[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a char array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, char[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a char array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, char[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a char array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, char[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a char array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, char[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a double array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, double[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a double array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, double[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a double array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, double[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a double array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, double[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a float array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, float[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a float array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, float[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a float array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, float[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a float array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, float[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString a boolean array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name * @param array the array to add to the toString * @param fullDetail true for detail, false for summary info, * null for style decides */ public void append(StringBuilder buffer, String fieldName, boolean[] array, Boolean fullDetail) { appendFieldStart(buffer, fieldName); if (array == null) { appendNullText(buffer, fieldName); } else if (isFullDetail(fullDetail)) { appendArray(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** *

* Append to the toString the detail of a boolean array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null * @param detailSize the detail size */ protected void appendArray(StringBuilder buffer, String fieldName, boolean[] array, int detailSize) { buffer.append(arrayStart); for (int i = 0; i < array.length && i < detailSize; i++) { if (i > 0) { buffer.append(arraySeparator); } appendElement(buffer, fieldName, array[i]); } if (detailSize < array.length) { appendSummarySize(buffer, fieldName, array.length); } buffer.append(arrayEnd); } /** *

* Append to the toString the detail of a boolean array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendArray(StringBuilder buffer, String fieldName, boolean[] array) { appendArray(buffer, fieldName, array, Integer.MAX_VALUE); } /** *

* Append to the toString a summary of a boolean array. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param array the array to add to the toString, not null */ protected void appendSummary(StringBuilder buffer, String fieldName, boolean[] array) { appendArray(buffer, fieldName, array, defaultDetailSize); } // ---------------------------------------------------------------------------- /** *

* Append to the toString the class name. *

* * @param buffer the StringBuilder to populate * @param object the Object whose name to output */ protected void appendClassName(StringBuilder buffer, Object object) { if (useClassName && object != null) { register(object); if (useShortClassName) { buffer.append(getShortClassName(object.getClass())); } else { buffer.append(object.getClass().getName()); } } } /** *

* Append the {@link System#identityHashCode(java.lang.Object)}. *

* * @param buffer the StringBuilder to populate * @param object the Object whose id to output */ protected void appendIdentityHashCode(StringBuilder buffer, Object object) { if (this.isUseIdentityHashCode() && object != null) { register(object); buffer.append('@'); buffer.append(Integer.toHexString(System.identityHashCode(object))); } } /** *

* Append to the toString the content start. *

* * @param buffer the StringBuilder to populate */ protected void appendContentStart(StringBuilder buffer) { buffer.append(contentStart); } /** *

* Append to the toString the content end. *

* * @param buffer the StringBuilder to populate */ protected void appendContentEnd(StringBuilder buffer) { buffer.append(contentEnd); } /** *

* Append to the toString an indicator for null. *

*

* The default indicator is '<null>'. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended */ protected void appendNullText(StringBuilder buffer, String fieldName) { buffer.append(nullText); } /** *

* Append to the toString the field separator. *

* * @param buffer the StringBuilder to populate */ protected void appendFieldSeparator(StringBuilder buffer) { buffer.append(fieldSeparator); } /** *

* Append to the toString the field start. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name */ protected void appendFieldStart(StringBuilder buffer, String fieldName) { if (useFieldNames && fieldName != null) { buffer.append(fieldName); buffer.append(fieldNameValueSeparator); } } /** *

* Append to the toString the field end. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended */ protected void appendFieldEnd(StringBuilder buffer, String fieldName) { appendFieldSeparator(buffer); } /** *

* Append to the toString a size summary. *

*

* The size summary is used to summarize the contents of Collections, * Maps and arrays. *

*

* The output consists of a prefix, the passed in size and a suffix. *

*

* The default format is '<size=n>'. *

* * @param buffer the StringBuilder to populate * @param fieldName the field name, typically not used as already appended * @param size the size to append */ protected void appendSummarySize(StringBuilder buffer, String fieldName, int size) { buffer.append(sizeStartText); buffer.append(size); buffer.append(sizeEndText); } /** *

* Is this field to be output in full detail. *

*

* This method converts a detail request into a detail level. The calling code may request full * detail (true), but a subclass might ignore that and always return * false. The calling code may pass in null indicating that it doesn't * care about the detail level. In this case the default detail level is used. *

* * @param fullDetailRequest the detail level requested * @return whether full detail is to be shown */ protected boolean isFullDetail(Boolean fullDetailRequest) { if (fullDetailRequest == null) { return defaultFullDetail; } return fullDetailRequest.booleanValue(); } /** *

* Gets the short class name for a class. *

*

* The short class name is the classname excluding the package name. *

* * @param cls the Class to get the short name of * @return the short name */ protected String getShortClassName(Class cls) { return Classes.getShortClassName(cls); } // Setters and getters for the customizable parts of the style // These methods are not expected to be overridden, except to make public // (They are not public so that immutable subclasses can be written) // --------------------------------------------------------------------- /** *

* Gets whether to use the class name. *

* * @return the current useClassName flag */ protected boolean isUseClassName() { return useClassName; } /** *

* Sets whether to use the class name. *

* * @param useClassName the new useClassName flag */ protected void setUseClassName(boolean useClassName) { this.useClassName = useClassName; } // --------------------------------------------------------------------- /** *

* Gets whether to output short or long class names. *

* * @return the current useShortClassName flag */ protected boolean isUseShortClassName() { return useShortClassName; } /** *

* Sets whether to output short or long class names. *

* * @param useShortClassName the new useShortClassName flag */ protected void setUseShortClassName(boolean useShortClassName) { this.useShortClassName = useShortClassName; } // --------------------------------------------------------------------- /** *

* Gets whether to use the identity hash code. *

* * @return the current useIdentityHashCode flag */ protected boolean isUseIdentityHashCode() { return useIdentityHashCode; } /** *

* Sets whether to use the identity hash code. *

* * @param useIdentityHashCode the new useIdentityHashCode flag */ protected void setUseIdentityHashCode(boolean useIdentityHashCode) { this.useIdentityHashCode = useIdentityHashCode; } // --------------------------------------------------------------------- /** *

* Gets whether to use the field names passed in. *

* * @return the current useFieldNames flag */ protected boolean isUseFieldNames() { return useFieldNames; } /** *

* Sets whether to use the field names passed in. *

* * @param useFieldNames the new useFieldNames flag */ protected void setUseFieldNames(boolean useFieldNames) { this.useFieldNames = useFieldNames; } // --------------------------------------------------------------------- /** *

* Gets whether to use full detail when the caller doesn't specify. *

* * @return the current defaultFullDetail flag */ protected boolean isDefaultFullDetail() { return defaultFullDetail; } /** *

* Sets whether to use full detail when the caller doesn't specify. *

* * @param defaultFullDetail the new defaultFullDetail flag */ protected void setDefaultFullDetail(boolean defaultFullDetail) { this.defaultFullDetail = defaultFullDetail; } // --------------------------------------------------------------------- /** *

* Gets the array start text. *

* * @return the current array start text */ protected String getArrayStart() { return arrayStart; } /** *

* Sets the array start text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param arrayStart the new array start text */ protected void setArrayStart(String arrayStart) { if (arrayStart == null) { arrayStart = Strings.EMPTY; } this.arrayStart = arrayStart; } // --------------------------------------------------------------------- /** *

* Gets the array end text. *

* * @return the current array end text */ protected String getArrayEnd() { return arrayEnd; } /** *

* Sets the array end text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param arrayEnd the new array end text */ protected void setArrayEnd(String arrayEnd) { if (arrayEnd == null) { arrayEnd = Strings.EMPTY; } this.arrayEnd = arrayEnd; } // --------------------------------------------------------------------- /** *

* Gets the array separator text. *

* * @return the current array separator text */ protected String getArraySeparator() { return arraySeparator; } /** *

* Sets the array separator text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param arraySeparator the new array separator text */ protected void setArraySeparator(String arraySeparator) { if (arraySeparator == null) { arraySeparator = Strings.EMPTY; } this.arraySeparator = arraySeparator; } // --------------------------------------------------------------------- /** *

* Gets the content start text. *

* * @return the current content start text */ protected String getContentStart() { return contentStart; } /** *

* Sets the content start text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param contentStart the new content start text */ protected void setContentStart(String contentStart) { if (contentStart == null) { contentStart = Strings.EMPTY; } this.contentStart = contentStart; } // --------------------------------------------------------------------- /** *

* Gets the content end text. *

* * @return the current content end text */ protected String getContentEnd() { return contentEnd; } /** *

* Sets the content end text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param contentEnd the new content end text */ protected void setContentEnd(String contentEnd) { if (contentEnd == null) { contentEnd = Strings.EMPTY; } this.contentEnd = contentEnd; } // --------------------------------------------------------------------- /** *

* Gets the field name value separator text. *

* * @return the current field name value separator text */ protected String getFieldNameValueSeparator() { return fieldNameValueSeparator; } /** *

* Sets the field name value separator text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param fieldNameValueSeparator the new field name value separator text */ protected void setFieldNameValueSeparator(String fieldNameValueSeparator) { if (fieldNameValueSeparator == null) { fieldNameValueSeparator = Strings.EMPTY; } this.fieldNameValueSeparator = fieldNameValueSeparator; } // --------------------------------------------------------------------- /** *

* Gets the field separator text. *

* * @return the current field separator text */ protected String getFieldSeparator() { return fieldSeparator; } /** *

* Sets the field separator text. *

*

* null is accepted, but will be converted to an empty String. *

* * @param fieldSeparator the new field separator text */ protected void setFieldSeparator(String fieldSeparator) { if (fieldSeparator == null) { fieldSeparator = Strings.EMPTY; } this.fieldSeparator = fieldSeparator; } // --------------------------------------------------------------------- /** *

* Gets whether the field separator should be added at the start of each buffer. *

* * @return the fieldSeparatorAtStart flag */ protected boolean isFieldSeparatorAtStart() { return fieldSeparatorAtStart; } /** *

* Sets whether the field separator should be added at the start of each buffer. *

* * @param fieldSeparatorAtStart the fieldSeparatorAtStart flag */ protected void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) { this.fieldSeparatorAtStart = fieldSeparatorAtStart; } // --------------------------------------------------------------------- /** *

* Gets whether the field separator should be added at the end of each buffer. *

* * @return fieldSeparatorAtEnd flag */ protected boolean isFieldSeparatorAtEnd() { return fieldSeparatorAtEnd; } /** *

* Sets whether the field separator should be added at the end of each buffer. *

* * @param fieldSeparatorAtEnd the fieldSeparatorAtEnd flag */ protected void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) { this.fieldSeparatorAtEnd = fieldSeparatorAtEnd; } // --------------------------------------------------------------------- /** *

* Gets the text to output when null found. *

* * @return the current text to output when null found */ protected String getNullText() { return nullText; } /** *

* Sets the text to output when null found. *

*

* null is accepted, but will be converted to an empty String. *

* * @param nullText the new text to output when null found */ protected void setNullText(String nullText) { if (nullText == null) { nullText = Strings.EMPTY; } this.nullText = nullText; } // --------------------------------------------------------------------- /** *

* Gets the start text to output when a Collection, Map or array size * is output. *

*

* This is output before the size value. *

* * @return the current start of size text */ protected String getSizeStartText() { return sizeStartText; } /** *

* Sets the start text to output when a Collection, Map or array size * is output. *

*

* This is output before the size value. *

*

* null is accepted, but will be converted to an empty String. *

* * @param sizeStartText the new start of size text */ protected void setSizeStartText(String sizeStartText) { if (sizeStartText == null) { sizeStartText = Strings.EMPTY; } this.sizeStartText = sizeStartText; } // --------------------------------------------------------------------- /** *

* Gets the end text to output when a Collection, Map or array size is * output. *

*

* This is output after the size value. *

* * @return the current end of size text */ protected String getSizeEndText() { return sizeEndText; } /** *

* Sets the end text to output when a Collection, Map or array size is * output. *

*

* This is output after the size value. *

*

* null is accepted, but will be converted to an empty String. *

* * @param sizeEndText the new end of size text */ protected void setSizeEndText(String sizeEndText) { if (sizeEndText == null) { sizeEndText = Strings.EMPTY; } this.sizeEndText = sizeEndText; } // --------------------------------------------------------------------- /** *

* Gets the start text to output when an Object is output in summary mode. *

*

* This is output before the size value. *

* * @return the current start of summary text */ protected String getSummaryObjectStartText() { return summaryObjectStartText; } /** *

* Sets the start text to output when an Object is output in summary mode. *

*

* This is output before the size value. *

*

* null is accepted, but will be converted to an empty String. *

* * @param summaryObjectStartText the new start of summary text */ protected void setSummaryObjectStartText(String summaryObjectStartText) { if (summaryObjectStartText == null) { summaryObjectStartText = Strings.EMPTY; } this.summaryObjectStartText = summaryObjectStartText; } // --------------------------------------------------------------------- /** *

* Gets the end text to output when an Object is output in summary mode. *

*

* This is output after the size value. *

* * @return the current end of summary text */ protected String getSummaryObjectEndText() { return summaryObjectEndText; } /** *

* Sets the end text to output when an Object is output in summary mode. *

*

* This is output after the size value. *

*

* null is accepted, but will be converted to an empty String. *

* * @param summaryObjectEndText the new end of summary text */ protected void setSummaryObjectEndText(String summaryObjectEndText) { if (summaryObjectEndText == null) { summaryObjectEndText = Strings.EMPTY; } this.summaryObjectEndText = summaryObjectEndText; } // ---------------------------------------------------------------------------- /** *

* Default ToStringStyle. *

*/ private static final class DefaultToStringStyle extends ToStringStyle { /** * Required for serialization support. * * @see java.io.Serializable */ private static final long serialVersionUID = 1L; /** *

* Constructor. *

*

* Use the static constant rather than instantiating. *

*/ DefaultToStringStyle() { super(); } } // ---------------------------------------------------------------------------- /** *

* ToStringStyle that does not print out the field names. *

*/ private static final class NoFieldNameToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** *

* Constructor. *

*

* Use the static constant rather than instantiating. *

*/ NoFieldNameToStringStyle() { super(); this.setUseFieldNames(false); } } // ---------------------------------------------------------------------------- /** *

* ToStringStyle that prints out the short class name and no identity hashcode. *

*/ private static final class ShortPrefixToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** *

* Constructor. *

*

* Use the static constant rather than instantiating. *

*/ ShortPrefixToStringStyle() { super(); this.setUseShortClassName(true); this.setUseIdentityHashCode(false); } } /** *

* ToStringStyle that does not print out the classname, identity hashcode, content * start or field name. *

*/ private static final class SimpleToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** *

* Constructor. *

*

* Use the static constant rather than instantiating. *

*/ SimpleToStringStyle() { super(); this.setUseClassName(false); this.setUseIdentityHashCode(false); this.setUseFieldNames(false); this.setContentStart(Strings.EMPTY); this.setContentEnd(Strings.EMPTY); } } // ---------------------------------------------------------------------------- /** *

* ToStringStyle that outputs on multiple lines. *

*/ private static final class MultiLineToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** *

* Constructor. *

*

* Use the static constant rather than instantiating. *

*/ MultiLineToStringStyle() { super(); this.setFieldSeparator(Systems.LINE_SEPARATOR + " "); this.setFieldSeparatorAtStart(true); this.setContentEnd(Systems.LINE_SEPARATOR + getContentEnd()); } } }