/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.caudexorigo.builder; import java.io.Serializable; import java.lang.reflect.Array; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.caudexorigo.lang.ClassUtils; import org.caudexorigo.lang.ObjectUtils; import org.caudexorigo.lang.SystemUtils; /** * <p> * Controls <code>String</code> formatting for {@link ToStringBuilder}. The main public interface is always via <code>ToStringBuilder</code>. * </p> * * <p> * These classes are intended to be used as <code>Singletons</code>. There is no need to instantiate a new style each time. A program will generally use one of the predefined constants on this class. Alternatively, the {@link StandardToStringStyle} class can be used to set the individual settings. Thus most styles can be achieved without subclassing. * </p> * * <p> * If required, a subclass can override as many or as few of the methods as it requires. Each object type (from <code>boolean</code> to <code>long</code> to <code>Object</code> to <code>int[]</code>) has its own methods to output it. Most have two versions, detail and summary. * * <p> * 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. * </p> * * <p> * If you want to format the output of certain objects, such as dates, you must create a subclass and override a method. * * <pre> * public class MyStyle extends ToStringStyle * { * protected void appendDetail(StringBuilder buffer, String fieldName, Object value) * { * if (value instanceof Date) * { * value = new SimpleDateFormat("yyyy-MM-dd").format(value); * } * buffer.append(value); * } * } * </pre> * * </p> * * @author Stephen Colebourne * @author Gary Gregory * @author Pete Gieser * @author Masato Tezuka * @since 1.0 * @version $Id: ToStringStyle.java 594386 2007-11-13 01:22:21Z bayard $ */ public abstract class ToStringStyle implements Serializable { /** * The default toString style. Using the Using the <code>Person</code> example from {@link ToStringBuilder}, the output would look like this: * * <pre> * Person@182f0db[name=John Doe,age=33,smoker=false] * </pre> */ public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle(); /** * The multi line toString style. Using the Using the <code>Person</code> example from {@link ToStringBuilder}, the output would look like this: * * <pre> * Person@182f0db[ * name=John Doe * age=33 * smoker=false * ] * </pre> */ public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle(); /** * The no field names toString style. Using the Using the <code>Person</code> example from {@link ToStringBuilder}, the output would look like this: * * <pre> * Person@182f0db[John Doe,33,false] * </pre> */ public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle(); /** * The short prefix toString style. Using the <code>Person</code> example from {@link ToStringBuilder}, the output would look like this: * * <pre> * Person[name=John Doe,age=33,smoker=false] * </pre> * * @since 2.1 */ public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle(); /** * The simple toString style. Using the Using the <code>Person</code> example from {@link ToStringBuilder}, the output would look like this: * * <pre> * John Doe,33,false * </pre> */ public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle(); /** * <p> * A registry of objects used by <code>reflectionToString</code> methods to detect cyclical object references and avoid infinite loops. * </p> */ private static ThreadLocal registry = new ThreadLocal() { protected Object initialValue() { // The HashSet implementation is not synchronized, // which is just what we need here. return new HashSet(); } }; /** * <p> * Returns the registry of objects being traversed by the <code>reflectionToString</code> methods in the current thread. * </p> * * @return Set the registry of objects being traversed */ static Set getRegistry() { return (Set) registry.get(); } /** * <p> * Returns <code>true</code> if the registry contains the given object. Used by the reflection methods to avoid infinite loops. * </p> * * @param value * The object to lookup in the registry. * @return boolean <code>true</code> if the registry contains the given object. */ static boolean isRegistered(Object value) { return getRegistry().contains(value); } /** * <p> * Registers the given object. Used by the reflection methods to avoid infinite loops. * </p> * * @param value * The object to register. */ static void register(Object value) { if (value != null) { getRegistry().add(value); } } /** * <p> * Unregisters the given object. * </p> * * <p> * Used by the reflection methods to avoid infinite loops. * </p> * * @param value * The object to unregister. */ static void unregister(Object value) { getRegistry().remove(value); } /** * Whether to use the field names, the default is <code>true</code>. */ private boolean useFieldNames = true; /** * Whether to use the class name, the default is <code>true</code>. */ private boolean useClassName = true; /** * Whether to use short class names, the default is <code>false</code>. */ private boolean useShortClassName = false; /** * Whether to use the identity hash code, the default is <code>true</code>. */ private boolean useIdentityHashCode = true; /** * The content start <code>'['</code>. */ private String contentStart = "["; /** * The content end <code>']'</code>. */ private String contentEnd = "]"; /** * The field name value separator <code>'='</code>. */ 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 <code>','</code>. */ private String fieldSeparator = ","; /** * The array start <code>'{'</code>. */ private String arrayStart = "{"; /** * The array separator <code>','</code>. */ private String arraySeparator = ","; /** * The detail for array content. */ private boolean arrayContentDetail = true; /** * The array end <code>'}'</code>. */ private String arrayEnd = "}"; /** * The value to use when fullDetail is <code>null</code>, the default value is <code>true</code>. */ private boolean defaultFullDetail = true; /** * The <code>null</code> text <code>'<null>'</code>. */ private String nullText = "<null>"; /** * The summary size text start <code>'<size'</code>. */ private String sizeStartText = "<size="; /** * The summary size text start <code>'>'</code>. */ private String sizeEndText = ">"; /** * The summary object text start <code>'<'</code>. */ private String summaryObjectStartText = "<"; /** * The summary object text start <code>'>'</code>. */ private String summaryObjectEndText = ">"; // ---------------------------------------------------------------------------- /** * <p> * Constructor. * </p> */ protected ToStringStyle() { super(); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> the superclass toString. * </p> * <p> * NOTE: It assumes that the toString has been created from the same ToStringStyle. * </p> * * <p> * A <code>null</code> <code>superToString</code> is ignored. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param superToString * the <code>super.toString()</code> * @since 2.0 */ public void appendSuper(StringBuilder buffer, String superToString) { appendToString(buffer, superToString); } /** * <p> * Append to the <code>toString</code> another toString. * </p> * <p> * NOTE: It assumes that the toString has been created from the same ToStringStyle. * </p> * * <p> * A <code>null</code> <code>toString</code> is ignored. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param toString * the additional <code>toString</code> * @since 2.0 */ 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); } } } /** * <p> * Append to the <code>toString</code> the start of data indicator. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param object * the <code>Object</code> to build a <code>toString</code> for */ public void appendStart(StringBuilder buffer, Object object) { if (object != null) { appendClassName(buffer, object); appendIdentityHashCode(buffer, object); appendContentStart(buffer); if (fieldSeparatorAtStart) { appendFieldSeparator(buffer); } } } /** * <p> * Append to the <code>toString</code> the end of data indicator. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param object * the <code>Object</code> to build a <code>toString</code> for. */ public void appendEnd(StringBuilder buffer, Object object) { if (this.fieldSeparatorAtEnd == false) { removeLastFieldSeparator(buffer); } appendContentEnd(buffer); unregister(object); } /** * <p> * Remove the last field separator from the buffer. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @since 2.0 */ 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); } } } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> an <code>Object</code> value, printing the full <code>toString</code> of the <code>Object</code> passed in. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> an <code>Object</code>, correctly interpreting its type. * </p> * * <p> * This method performs the main lookup by Class type to correctly route arrays, <code>Collections</code>, <code>Maps</code> and <code>Objects</code> to the appropriate method. * </p> * * <p> * Either detail or summary views can be specified. * </p> * * <p> * If a cycle is detected, an object will be appended with the <code>Object.toString()</code> format. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code>, not <code>null</code> * @param detail * output detail or not */ protected void appendInternal(StringBuilder buffer, String fieldName, Object value, boolean detail) { if (isRegistered(value) && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) { appendCyclicObject(buffer, fieldName, value); return; } register(value); try { if (value instanceof Collection) { if (detail) { appendDetail(buffer, fieldName, (Collection) value); } else { appendSummarySize(buffer, fieldName, ((Collection) value).size()); } } else if (value instanceof Map) { if (detail) { appendDetail(buffer, fieldName, (Map) value); } else { appendSummarySize(buffer, fieldName, ((Map) value).size()); } } else if (value instanceof long[]) { if (detail) { appendDetail(buffer, fieldName, (long[]) value); } else { appendSummary(buffer, fieldName, (long[]) value); } } else if (value instanceof int[]) { if (detail) { appendDetail(buffer, fieldName, (int[]) value); } else { appendSummary(buffer, fieldName, (int[]) value); } } else if (value instanceof short[]) { if (detail) { appendDetail(buffer, fieldName, (short[]) value); } else { appendSummary(buffer, fieldName, (short[]) value); } } else if (value instanceof byte[]) { if (detail) { appendDetail(buffer, fieldName, (byte[]) value); } else { appendSummary(buffer, fieldName, (byte[]) value); } } else if (value instanceof char[]) { if (detail) { appendDetail(buffer, fieldName, (char[]) value); } else { appendSummary(buffer, fieldName, (char[]) value); } } else if (value instanceof double[]) { if (detail) { appendDetail(buffer, fieldName, (double[]) value); } else { appendSummary(buffer, fieldName, (double[]) value); } } else if (value instanceof float[]) { if (detail) { appendDetail(buffer, fieldName, (float[]) value); } else { appendSummary(buffer, fieldName, (float[]) value); } } else if (value instanceof boolean[]) { if (detail) { appendDetail(buffer, fieldName, (boolean[]) value); } else { appendSummary(buffer, fieldName, (boolean[]) value); } } else if (value.getClass().isArray()) { if (detail) { appendDetail(buffer, fieldName, (Object[]) value); } else { appendSummary(buffer, fieldName, (Object[]) value); } } else { if (detail) { appendDetail(buffer, fieldName, value); } else { appendSummary(buffer, fieldName, value); } } } finally { unregister(value); } } /** * <p> * Append to the <code>toString</code> an <code>Object</code> value that has been detected to participate in a cycle. This implementation will print the standard string value of the value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code>, not <code>null</code> * * @since 2.2 */ protected void appendCyclicObject(StringBuilder buffer, String fieldName, Object value) { ObjectUtils.appendIdentityToString(buffer, value); } /** * <p> * Append to the <code>toString</code> an <code>Object</code> value, printing the full detail of the <code>Object</code>. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, Object value) { buffer.append(value); } /** * <p> * Append to the <code>toString</code> a <code>Collection</code>. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param coll * the <code>Collection</code> to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, Collection coll) { buffer.append(coll); } /** * <p> * Append to the <code>toString</code> a <code>Map<code>. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param map * the <code>Map</code> to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, Map map) { buffer.append(map); } /** * <p> * Append to the <code>toString</code> an <code>Object</code> value, printing a summary of the <code>Object</code>. * </P> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, Object value) { buffer.append(summaryObjectStartText); buffer.append(getShortClassName(value.getClass())); buffer.append(summaryObjectEndText); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>long</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, long value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>long</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, long value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> an <code>int</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, int value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> an <code>int</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, int value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>short</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, short value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>short</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, short value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>byte</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, byte value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>byte</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, byte value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>char</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, char value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>char</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, char value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>double</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, double value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>double</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, double value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>float</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, float value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>float</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, float value) { buffer.append(value); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>boolean</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param value * the value to add to the <code>toString</code> */ public void append(StringBuilder buffer, String fieldName, boolean value) { appendFieldStart(buffer, fieldName); appendDetail(buffer, fieldName, value); appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> a <code>boolean</code> value. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the <code>toString</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, boolean value) { buffer.append(value); } /** * <p> * Append to the <code>toString</code> an <code>Object</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> the detail of an <code>Object</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, Object[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { Object item = array[i]; if (i > 0) { buffer.append(arraySeparator); } if (item == null) { appendNullText(buffer, fieldName); } else { appendInternal(buffer, fieldName, item, arrayContentDetail); } } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> the detail of an array type. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> * @since 2.0 */ protected void reflectionAppendArrayDetail(StringBuilder buffer, String fieldName, Object array) { buffer.append(arrayStart); int length = Array.getLength(array); for (int i = 0; i < length; i++) { Object item = Array.get(array, i); if (i > 0) { buffer.append(arraySeparator); } if (item == null) { appendNullText(buffer, fieldName); } else { appendInternal(buffer, fieldName, item, arrayContentDetail); } } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of an <code>Object</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, Object[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>long</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>long</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, long[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>long</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, long[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> an <code>int</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of an <code>int</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, int[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of an <code>int</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, int[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>short</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>short</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, short[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>short</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, short[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>byte</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>byte</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, byte[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>byte</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, byte[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>char</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the <code>toString</code> * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>char</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, char[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>char</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, char[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>double</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>double</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, double[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>double</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, double[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>float</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>float</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, float[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>float</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, float[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> a <code>boolean</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * <code>true</code> for detail, <code>false</code> for summary info, <code>null</code> 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)) { appendDetail(buffer, fieldName, array); } else { appendSummary(buffer, fieldName, array); } appendFieldEnd(buffer, fieldName); } /** * <p> * Append to the <code>toString</code> the detail of a <code>boolean</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendDetail(StringBuilder buffer, String fieldName, boolean[] array) { buffer.append(arrayStart); for (int i = 0; i < array.length; i++) { if (i > 0) { buffer.append(arraySeparator); } appendDetail(buffer, fieldName, array[i]); } buffer.append(arrayEnd); } /** * <p> * Append to the <code>toString</code> a summary of a <code>boolean</code> array. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the <code>toString</code>, not <code>null</code> */ protected void appendSummary(StringBuilder buffer, String fieldName, boolean[] array) { appendSummarySize(buffer, fieldName, array.length); } // ---------------------------------------------------------------------------- /** * <p> * Append to the <code>toString</code> the class name. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param object * the <code>Object</code> 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()); } } } /** * <p> * Append the {@link System#identityHashCode(java.lang.Object)}. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param object * the <code>Object</code> 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))); } } /** * <p> * Append to the <code>toString</code> the content start. * </p> * * @param buffer * the <code>StringBuilder</code> to populate */ protected void appendContentStart(StringBuilder buffer) { buffer.append(contentStart); } /** * <p> * Append to the <code>toString</code> the content end. * </p> * * @param buffer * the <code>StringBuilder</code> to populate */ protected void appendContentEnd(StringBuilder buffer) { buffer.append(contentEnd); } /** * <p> * Append to the <code>toString</code> an indicator for <code>null</code>. * </p> * * <p> * The default indicator is <code>'<null>'</code>. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended */ protected void appendNullText(StringBuilder buffer, String fieldName) { buffer.append(nullText); } /** * <p> * Append to the <code>toString</code> the field separator. * </p> * * @param buffer * the <code>StringBuilder</code> to populate */ protected void appendFieldSeparator(StringBuilder buffer) { buffer.append(fieldSeparator); } /** * <p> * Append to the <code>toString</code> the field start. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name */ protected void appendFieldStart(StringBuilder buffer, String fieldName) { if (useFieldNames && fieldName != null) { buffer.append(fieldName); buffer.append(fieldNameValueSeparator); } } /** * <p> * Append to the <code>toString<code> the field end. * </p> * * @param buffer * the <code>StringBuilder</code> to populate * @param fieldName * the field name, typically not used as already appended */ protected void appendFieldEnd(StringBuilder buffer, String fieldName) { appendFieldSeparator(buffer); } /** * <p> * Append to the <code>toString</code> a size summary. * </p> * * <p> * The size summary is used to summarize the contents of <code>Collections</code>, <code>Maps</code> and arrays. * </p> * * <p> * The output consists of a prefix, the passed in size and a suffix. * </p> * * <p> * The default format is <code>'<size=n>'<code>. * </p> * * @param buffer * the <code>StringBuilder</code> 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); } /** * <p> * Is this field to be output in full detail. * </p> * * <p> * This method converts a detail request into a detail level. The calling code may request full detail (<code>true</code>), but a subclass might ignore that and always return <code>false</code>. The calling code may pass in <code>null</code> indicating that it doesn't care about the detail level. In this case the default detail level is used. * </p> * * @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(); } /** * <p> * Gets the short class name for a class. * </p> * * <p> * The short class name is the classname excluding the package name. * </p> * * @param cls * the <code>Class</code> to get the short name of * @return the short name */ protected String getShortClassName(Class cls) { return ClassUtils.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) // --------------------------------------------------------------------- /** * <p> * Gets whether to use the class name. * </p> * * @return the current useClassName flag */ protected boolean isUseClassName() { return useClassName; } /** * <p> * Sets whether to use the class name. * </p> * * @param useClassName * the new useClassName flag */ protected void setUseClassName(boolean useClassName) { this.useClassName = useClassName; } // --------------------------------------------------------------------- /** * <p> * Gets whether to output short or long class names. * </p> * * @return the current useShortClassName flag * @since 2.0 */ protected boolean isUseShortClassName() { return useShortClassName; } /** * <p> * Gets whether to output short or long class names. * </p> * * @return the current shortClassName flag * @deprecated Use {@link #isUseShortClassName()} Method will be removed in Commons Lang 3.0. */ protected boolean isShortClassName() { return useShortClassName; } /** * <p> * Sets whether to output short or long class names. * </p> * * @param useShortClassName * the new useShortClassName flag * @since 2.0 */ protected void setUseShortClassName(boolean useShortClassName) { this.useShortClassName = useShortClassName; } /** * <p> * Sets whether to output short or long class names. * </p> * * @param shortClassName * the new shortClassName flag * @deprecated Use {@link #setUseShortClassName(boolean)} Method will be removed in Commons Lang 3.0. */ protected void setShortClassName(boolean shortClassName) { this.useShortClassName = shortClassName; } // --------------------------------------------------------------------- /** * <p> * Gets whether to use the identity hash code. * </p> * * @return the current useIdentityHashCode flag */ protected boolean isUseIdentityHashCode() { return useIdentityHashCode; } /** * <p> * Sets whether to use the identity hash code. * </p> * * @param useIdentityHashCode * the new useIdentityHashCode flag */ protected void setUseIdentityHashCode(boolean useIdentityHashCode) { this.useIdentityHashCode = useIdentityHashCode; } // --------------------------------------------------------------------- /** * <p> * Gets whether to use the field names passed in. * </p> * * @return the current useFieldNames flag */ protected boolean isUseFieldNames() { return useFieldNames; } /** * <p> * Sets whether to use the field names passed in. * </p> * * @param useFieldNames * the new useFieldNames flag */ protected void setUseFieldNames(boolean useFieldNames) { this.useFieldNames = useFieldNames; } // --------------------------------------------------------------------- /** * <p> * Gets whether to use full detail when the caller doesn't specify. * </p> * * @return the current defaultFullDetail flag */ protected boolean isDefaultFullDetail() { return defaultFullDetail; } /** * <p> * Sets whether to use full detail when the caller doesn't specify. * </p> * * @param defaultFullDetail * the new defaultFullDetail flag */ protected void setDefaultFullDetail(boolean defaultFullDetail) { this.defaultFullDetail = defaultFullDetail; } // --------------------------------------------------------------------- /** * <p> * Gets whether to output array content detail. * </p> * * @return the current array content detail setting */ protected boolean isArrayContentDetail() { return arrayContentDetail; } /** * <p> * Sets whether to output array content detail. * </p> * * @param arrayContentDetail * the new arrayContentDetail flag */ protected void setArrayContentDetail(boolean arrayContentDetail) { this.arrayContentDetail = arrayContentDetail; } // --------------------------------------------------------------------- /** * <p> * Gets the array start text. * </p> * * @return the current array start text */ protected String getArrayStart() { return arrayStart; } /** * <p> * Sets the array start text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param arrayStart * the new array start text */ protected void setArrayStart(String arrayStart) { if (arrayStart == null) { arrayStart = ""; } this.arrayStart = arrayStart; } // --------------------------------------------------------------------- /** * <p> * Gets the array end text. * </p> * * @return the current array end text */ protected String getArrayEnd() { return arrayEnd; } /** * <p> * Sets the array end text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param arrayEnd * the new array end text */ protected void setArrayEnd(String arrayEnd) { if (arrayEnd == null) { arrayEnd = ""; } this.arrayEnd = arrayEnd; } // --------------------------------------------------------------------- /** * <p> * Gets the array separator text. * </p> * * @return the current array separator text */ protected String getArraySeparator() { return arraySeparator; } /** * <p> * Sets the array separator text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param arraySeparator * the new array separator text */ protected void setArraySeparator(String arraySeparator) { if (arraySeparator == null) { arraySeparator = ""; } this.arraySeparator = arraySeparator; } // --------------------------------------------------------------------- /** * <p> * Gets the content start text. * </p> * * @return the current content start text */ protected String getContentStart() { return contentStart; } /** * <p> * Sets the content start text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param contentStart * the new content start text */ protected void setContentStart(String contentStart) { if (contentStart == null) { contentStart = ""; } this.contentStart = contentStart; } // --------------------------------------------------------------------- /** * <p> * Gets the content end text. * </p> * * @return the current content end text */ protected String getContentEnd() { return contentEnd; } /** * <p> * Sets the content end text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param contentEnd * the new content end text */ protected void setContentEnd(String contentEnd) { if (contentEnd == null) { contentEnd = ""; } this.contentEnd = contentEnd; } // --------------------------------------------------------------------- /** * <p> * Gets the field name value separator text. * </p> * * @return the current field name value separator text */ protected String getFieldNameValueSeparator() { return fieldNameValueSeparator; } /** * <p> * Sets the field name value separator text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param fieldNameValueSeparator * the new field name value separator text */ protected void setFieldNameValueSeparator(String fieldNameValueSeparator) { if (fieldNameValueSeparator == null) { fieldNameValueSeparator = ""; } this.fieldNameValueSeparator = fieldNameValueSeparator; } // --------------------------------------------------------------------- /** * <p> * Gets the field separator text. * </p> * * @return the current field separator text */ protected String getFieldSeparator() { return fieldSeparator; } /** * <p> * Sets the field separator text. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param fieldSeparator * the new field separator text */ protected void setFieldSeparator(String fieldSeparator) { if (fieldSeparator == null) { fieldSeparator = ""; } this.fieldSeparator = fieldSeparator; } // --------------------------------------------------------------------- /** * <p> * Gets whether the field separator should be added at the start of each buffer. * </p> * * @return the fieldSeparatorAtStart flag * @since 2.0 */ protected boolean isFieldSeparatorAtStart() { return fieldSeparatorAtStart; } /** * <p> * Sets whether the field separator should be added at the start of each buffer. * </p> * * @param fieldSeparatorAtStart * the fieldSeparatorAtStart flag * @since 2.0 */ protected void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) { this.fieldSeparatorAtStart = fieldSeparatorAtStart; } // --------------------------------------------------------------------- /** * <p> * Gets whether the field separator should be added at the end of each buffer. * </p> * * @return fieldSeparatorAtEnd flag * @since 2.0 */ protected boolean isFieldSeparatorAtEnd() { return fieldSeparatorAtEnd; } /** * <p> * Sets whether the field separator should be added at the end of each buffer. * </p> * * @param fieldSeparatorAtEnd * the fieldSeparatorAtEnd flag * @since 2.0 */ protected void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) { this.fieldSeparatorAtEnd = fieldSeparatorAtEnd; } // --------------------------------------------------------------------- /** * <p> * Gets the text to output when <code>null</code> found. * </p> * * @return the current text to output when null found */ protected String getNullText() { return nullText; } /** * <p> * Sets the text to output when <code>null</code> found. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param nullText * the new text to output when null found */ protected void setNullText(String nullText) { if (nullText == null) { nullText = ""; } this.nullText = nullText; } // --------------------------------------------------------------------- /** * <p> * Gets the start text to output when a <code>Collection</code>, <code>Map</code> or array size is output. * </p> * * <p> * This is output before the size value. * </p> * * @return the current start of size text */ protected String getSizeStartText() { return sizeStartText; } /** * <p> * Sets the start text to output when a <code>Collection</code>, <code>Map</code> or array size is output. * </p> * * <p> * This is output before the size value. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param sizeStartText * the new start of size text */ protected void setSizeStartText(String sizeStartText) { if (sizeStartText == null) { sizeStartText = ""; } this.sizeStartText = sizeStartText; } // --------------------------------------------------------------------- /** * <p> * Gets the end text to output when a <code>Collection</code>, <code>Map</code> or array size is output. * </p> * * <p> * This is output after the size value. * </p> * * @return the current end of size text */ protected String getSizeEndText() { return sizeEndText; } /** * <p> * Sets the end text to output when a <code>Collection</code>, <code>Map</code> or array size is output. * </p> * * <p> * This is output after the size value. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param sizeEndText * the new end of size text */ protected void setSizeEndText(String sizeEndText) { if (sizeEndText == null) { sizeEndText = ""; } this.sizeEndText = sizeEndText; } // --------------------------------------------------------------------- /** * <p> * Gets the start text to output when an <code>Object</code> is output in summary mode. * </p> * * <p> * This is output before the size value. * </p> * * @return the current start of summary text */ protected String getSummaryObjectStartText() { return summaryObjectStartText; } /** * <p> * Sets the start text to output when an <code>Object</code> is output in summary mode. * </p> * * <p> * This is output before the size value. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param summaryObjectStartText * the new start of summary text */ protected void setSummaryObjectStartText(String summaryObjectStartText) { if (summaryObjectStartText == null) { summaryObjectStartText = ""; } this.summaryObjectStartText = summaryObjectStartText; } // --------------------------------------------------------------------- /** * <p> * Gets the end text to output when an <code>Object</code> is output in summary mode. * </p> * * <p> * This is output after the size value. * </p> * * @return the current end of summary text */ protected String getSummaryObjectEndText() { return summaryObjectEndText; } /** * <p> * Sets the end text to output when an <code>Object</code> is output in summary mode. * </p> * * <p> * This is output after the size value. * </p> * * <p> * <code>null</code> is accepted, but will be converted to an empty String. * </p> * * @param summaryObjectEndText * the new end of summary text */ protected void setSummaryObjectEndText(String summaryObjectEndText) { if (summaryObjectEndText == null) { summaryObjectEndText = ""; } this.summaryObjectEndText = summaryObjectEndText; } // ---------------------------------------------------------------------------- /** * <p> * Default <code>ToStringStyle</code>. * </p> * * <p> * This is an inner class rather than using <code>StandardToStringStyle</code> to ensure its immutability. * </p> */ private static final class DefaultToStringStyle extends ToStringStyle { /** * Required for serialization support. * * @see java.io.Serializable */ private static final long serialVersionUID = 1L; /** * <p> * Constructor. * </p> * * <p> * Use the static constant rather than instantiating. * </p> */ DefaultToStringStyle() { super(); } /** * <p> * Ensure <code>Singleton</code> after serialization. * </p> * * @return the singleton */ private Object readResolve() { return ToStringStyle.DEFAULT_STYLE; } } // ---------------------------------------------------------------------------- /** * <p> * <code>ToStringStyle</code> that does not print out the field names. * </p> * * <p> * This is an inner class rather than using <code>StandardToStringStyle</code> to ensure its immutability. */ private static final class NoFieldNameToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** * <p> * Constructor. * </p> * * <p> * Use the static constant rather than instantiating. * </p> */ NoFieldNameToStringStyle() { super(); this.setUseFieldNames(false); } /** * <p> * Ensure <code>Singleton</code> after serialization. * </p> * * @return the singleton */ private Object readResolve() { return ToStringStyle.NO_FIELD_NAMES_STYLE; } } // ---------------------------------------------------------------------------- /** * <p> * <code>ToStringStyle</code> that prints out the short class name and no identity hashcode. * </p> * * <p> * This is an inner class rather than using <code>StandardToStringStyle</code> to ensure its immutability. * </p> */ private static final class ShortPrefixToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** * <p> * Constructor. * </p> * * <p> * Use the static constant rather than instantiating. * </p> */ ShortPrefixToStringStyle() { super(); this.setUseShortClassName(true); this.setUseIdentityHashCode(false); } /** * <p> * Ensure <code>Singleton</ode> after serialization. * </p> * * @return the singleton */ private Object readResolve() { return ToStringStyle.SHORT_PREFIX_STYLE; } } /** * <p> * <code>ToStringStyle</code> that does not print out the classname, identity hashcode, content start or field name. * </p> * * <p> * This is an inner class rather than using <code>StandardToStringStyle</code> to ensure its immutability. * </p> */ private static final class SimpleToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** * <p> * Constructor. * </p> * * <p> * Use the static constant rather than instantiating. * </p> */ SimpleToStringStyle() { super(); this.setUseClassName(false); this.setUseIdentityHashCode(false); this.setUseFieldNames(false); this.setContentStart(""); this.setContentEnd(""); } /** * <p> * Ensure <code>Singleton</ode> after serialization. * </p> * * @return the singleton */ private Object readResolve() { return ToStringStyle.SIMPLE_STYLE; } } // ---------------------------------------------------------------------------- /** * <p> * <code>ToStringStyle</code> that outputs on multiple lines. * </p> * * <p> * This is an inner class rather than using <code>StandardToStringStyle</code> to ensure its immutability. * </p> */ private static final class MultiLineToStringStyle extends ToStringStyle { private static final long serialVersionUID = 1L; /** * <p> * Constructor. * </p> * * <p> * Use the static constant rather than instantiating. * </p> */ MultiLineToStringStyle() { super(); this.setContentStart("["); this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + " "); this.setFieldSeparatorAtStart(true); this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]"); } /** * <p> * Ensure <code>Singleton</code> after serialization. * </p> * * @return the singleton */ private Object readResolve() { return ToStringStyle.MULTI_LINE_STYLE; } } }