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

com.feilong.lib.lang3.builder.ToStringStyle Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.3.0
Show newest version
/*
 * 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 com.feilong.lib.lang3.builder;

import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.WeakHashMap;

import com.feilong.lib.lang3.ClassUtils;

/**
 * 

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

* *

* These classes are intended to be used as {@code 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. * Alternatively, the {@link StandardToStringStyle} class can be used * to set the individual settings. Thus most styles can be achieved * without subclassing. *

* *

* If required, a subclass can override as many or as few of the * methods as it requires. Each object type (from {@code boolean} * to {@code long} to {@code Object} to {@code 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(StringBuffer buffer,String fieldName,Object value){
 *         if (value instanceof Date){
 *             value = new SimpleDateFormat("yyyy-MM-dd").format(value);
 *         }
 *         buffer.append(value);
 *     }
 * }
 * 
* * @since 1.0 */ // StringEscapeUtils public abstract class ToStringStyle implements Serializable{ private static final String EMPTY = ""; /** * Serialization version ID. */ private static final long serialVersionUID = -2587890625525655916L; /** * The default toString style. Using the {@code 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 {@code 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 * {@code 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 {@code Person} example * from {@link ToStringBuilder}, the output would look like this: * *
     * Person[name=John Doe,age=33,smoker=false]
     * 
* * @since 2.1 */ public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle(); /** * The simple toString style. Using the {@code Person} * example from {@link ToStringBuilder}, the output would look like this: * *
     * John Doe,33,false
     * 
*/ public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle(); /** * The no class name toString style. Using the {@code Person} * example from {@link ToStringBuilder}, the output would look like this: * *
     * [name=John Doe,age=33,smoker=false]
     * 
* * @since 3.4 */ public static final ToStringStyle NO_CLASS_NAME_STYLE = new NoClassNameToStringStyle(); /** *

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

*/ private static final ThreadLocal> REGISTRY = new ThreadLocal<>(); /* * Note that objects of this class are generally shared between threads, so * an instance variable would not be suitable here. * * In normal use the registry should always be left empty, because the caller * should call toString() which will clean up. * * See LANG-792 */ /** *

* Returns the registry of objects being traversed by the {@code reflectionToString} * methods in the current thread. *

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

* Returns {@code 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 {@code true} if the registry contains the given * object. */ static boolean isRegistered(final Object value){ final 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(final Object value){ if (value != null){ final 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(final Object value){ if (value != null){ final Map m = getRegistry(); if (m != null){ m.remove(value); if (m.isEmpty()){ REGISTRY.remove(); } } } } /** * Whether to use the field names, the default is {@code true}. */ private boolean useFieldNames = true; /** * Whether to use the class name, the default is {@code true}. */ private boolean useClassName = true; /** * Whether to use short class names, the default is {@code false}. */ private boolean useShortClassName = false; /** * Whether to use the identity hash code, the default is {@code true}. */ private boolean useIdentityHashCode = true; /** * The content start {@code '['}. */ private String contentStart = "["; /** * The content end {@code ']'}. */ private String contentEnd = "]"; /** * The field name value separator {@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 ','}. */ private String fieldSeparator = ","; /** * The array start '{'. */ private String arrayStart = "{"; /** * The array separator {@code ','}. */ private String arraySeparator = ","; /** * The detail for array content. */ private boolean arrayContentDetail = true; /** * The array end {@code '}'}. */ private String arrayEnd = "}"; /** * The value to use when fullDetail is {@code null}, * the default value is {@code true}. */ private boolean defaultFullDetail = true; /** * The {@code null} text {@code '<null>'}. */ private String nullText = ""; /** * The summary size text start {@code '<size'}. */ private String sizeStartText = " * Constructor. *

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

* Append to the {@code toString} the superclass toString. *

*

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

* *

* A {@code null} {@code superToString} is ignored. *

* * @param buffer * the {@code StringBuffer} to populate * @param superToString * the {@code super.toString()} * @since 2.0 */ public void appendSuper(final StringBuffer buffer,final String superToString){ appendToString(buffer, superToString); } /** *

* Append to the {@code toString} another toString. *

*

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

* *

* A {@code null} {@code toString} is ignored. *

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

* Append to the {@code toString} the start of data indicator. *

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

* Append to the {@code toString} the end of data indicator. *

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

* Remove the last field separator from the buffer. *

* * @param buffer * the {@code StringBuffer} to populate * @since 2.0 */ protected void removeLastFieldSeparator(final StringBuffer buffer){ final int len = buffer.length(); final 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 {@code toString} an {@code Object} * value, printing the full {@code toString} of the * {@code Object} passed in. *

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

* Append to the {@code toString} an {@code Object}, * correctly interpreting its type. *

* *

* This method performs the main lookup by Class type to correctly * route arrays, {@code Collections}, {@code Maps} and * {@code 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 * {@code Object.toString()} format. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the {@code toString}, * not {@code null} * @param detail * output detail or not */ protected void appendInternal(final StringBuffer buffer,final String fieldName,final Object value,final 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); } } /** *

* Append to the {@code toString} an {@code 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 {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the {@code toString}, * not {@code null} * * @since 2.2 */ protected void appendCyclicObject(final StringBuffer buffer,final String fieldName,final Object value){ buffer.append(Objects.toString(value)); } /** *

* Append to the {@code toString} an {@code Object} * value, printing the full detail of the {@code Object}. *

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

* Append to the {@code toString} a {@code Collection}. *

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

* Append to the {@code toString} a {@code Map}. *

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

* Append to the {@code toString} an {@code Object} * value, printing a summary of the {@code Object}. *

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

* Append to the {@code toString} a {@code long} * value. *

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

* Append to the {@code toString} a {@code long} * value. *

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

* Append to the {@code toString} an {@code int} * value. *

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

* Append to the {@code toString} an {@code int} * value. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param value * the value to add to the {@code toString} */ protected void appendDetail(final StringBuffer buffer,@SuppressWarnings("unused") final String fieldName,final int value){ buffer.append(value); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code short} * value. *

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

* Append to the {@code toString} a {@code short} * value. *

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

* Append to the {@code toString} a {@code byte} * value. *

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

* Append to the {@code toString} a {@code byte} * value. *

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

* Append to the {@code toString} a {@code char} * value. *

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

* Append to the {@code toString} a {@code char} * value. *

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

* Append to the {@code toString} a {@code double} * value. *

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

* Append to the {@code toString} a {@code double} * value. *

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

* Append to the {@code toString} a {@code float} * value. *

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

* Append to the {@code toString} a {@code float} * value. *

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

* Append to the {@code toString} a {@code boolean} * value. *

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

* Append to the {@code toString} a {@code boolean} * value. *

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

* Append to the {@code toString} an {@code Object} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final Object[] array,final 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); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} the detail of an * {@code Object} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final Object[] array){ buffer.append(arrayStart); for (int i = 0; i < array.length; i++){ final 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); } /** *

* Append to the {@code toString} the detail of an array type. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} * @since 2.0 */ protected void reflectionAppendArrayDetail(final StringBuffer buffer,final String fieldName,final Object array){ buffer.append(arrayStart); final int length = Array.getLength(array); for (int i = 0; i < length; i++){ final 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); } /** *

* Append to the {@code toString} a summary of an * {@code Object} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final Object[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code long} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the {@code toString} * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final long[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code long} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code long} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final long[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} an {@code int} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the {@code toString} * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final int[] array,final 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); } /** *

* Append to the {@code toString} the detail of an * {@code int} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of an * {@code int} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final int[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code short} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the {@code toString} * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final short[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code short} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code short} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final short[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code byte} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the {@code toString} * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final byte[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code byte} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code byte} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final byte[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code char} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the {@code toString} * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final char[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code char} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code char} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final char[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code double} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final double[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code double} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code double} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final double[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code float} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final float[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code float} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code float} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final float[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} a {@code boolean} * array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name * @param array * the array to add to the toString * @param fullDetail * {@code true} for detail, {@code false} * for summary info, {@code null} for style decides */ public void append(final StringBuffer buffer,final String fieldName,final boolean[] array,final 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); } /** *

* Append to the {@code toString} the detail of a * {@code boolean} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendDetail(final StringBuffer buffer,final String fieldName,final 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); } /** *

* Append to the {@code toString} a summary of a * {@code boolean} array. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param array * the array to add to the {@code toString}, * not {@code null} */ protected void appendSummary(final StringBuffer buffer,final String fieldName,final boolean[] array){ appendSummarySize(buffer, fieldName, array.length); } //---------------------------------------------------------------------------- /** *

* Append to the {@code toString} the class name. *

* * @param buffer * the {@code StringBuffer} to populate * @param object * the {@code Object} whose name to output */ protected void appendClassName(final StringBuffer buffer,final 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 {@code StringBuffer} to populate * @param object * the {@code Object} whose id to output */ protected void appendIdentityHashCode(final StringBuffer buffer,final Object object){ if (this.isUseIdentityHashCode() && object != null){ register(object); buffer.append('@'); buffer.append(Integer.toHexString(System.identityHashCode(object))); } } /** *

* Append to the {@code toString} the content start. *

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

* Append to the {@code toString} the content end. *

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

* Append to the {@code toString} an indicator for {@code null}. *

* *

* The default indicator is {@code '<null>'}. *

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

* Append to the {@code toString} the field separator. *

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

* Append to the {@code toString} the field start. *

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

* Append to the {@code toString} the field end. *

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

* Append to the {@code toString} a size summary. *

* *

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

* *

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

* *

* The default format is {@code '<size=n>'}. *

* * @param buffer * the {@code StringBuffer} to populate * @param fieldName * the field name, typically not used as already appended * @param size * the size to append */ protected void appendSummarySize(final StringBuffer buffer,final String fieldName,final 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 ({@code true}), * but a subclass might ignore that and always return * {@code false}. The calling code may pass in * {@code 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(final 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 {@code Class} to get the short name of * @return the short name */ protected String getShortClassName(final 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) //--------------------------------------------------------------------- /** *

* 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(final boolean useClassName){ this.useClassName = useClassName; } //--------------------------------------------------------------------- /** *

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

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

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

* * @param useShortClassName * the new useShortClassName flag * @since 2.0 */ protected void setUseShortClassName(final 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(final 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(final 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(final boolean defaultFullDetail){ this.defaultFullDetail = defaultFullDetail; } //--------------------------------------------------------------------- /** *

* Gets whether to output array content detail. *

* * @return the current array content detail setting */ protected boolean isArrayContentDetail(){ return arrayContentDetail; } /** *

* Sets whether to output array content detail. *

* * @param arrayContentDetail * the new arrayContentDetail flag */ protected void setArrayContentDetail(final boolean arrayContentDetail){ this.arrayContentDetail = arrayContentDetail; } //--------------------------------------------------------------------- /** *

* Gets the array start text. *

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

* Sets the array start text. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = 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. *

* *

* {@code 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 = EMPTY; } this.fieldSeparator = fieldSeparator; } //--------------------------------------------------------------------- /** *

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

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

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

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

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

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

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

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

* Gets the text to output when {@code null} found. *

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

* Sets the text to output when {@code null} found. *

* *

* {@code 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 = EMPTY; } this.nullText = nullText; } //--------------------------------------------------------------------- /** *

* Gets the start text to output when a {@code Collection}, * {@code 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 {@code Collection}, * {@code Map} or array size is output. *

* *

* This is output before the size value. *

* *

* {@code 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 = EMPTY; } this.sizeStartText = sizeStartText; } //--------------------------------------------------------------------- /** *

* Gets the end text to output when a {@code Collection}, * {@code 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 {@code Collection}, * {@code Map} or array size is output. *

* *

* This is output after the size value. *

* *

* {@code 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 = EMPTY; } this.sizeEndText = sizeEndText; } //--------------------------------------------------------------------- /** *

* Gets the start text to output when an {@code 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 {@code Object} is * output in summary mode. *

* *

* This is output before the size value. *

* *

* {@code 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 = EMPTY; } this.summaryObjectStartText = summaryObjectStartText; } //--------------------------------------------------------------------- /** *

* Gets the end text to output when an {@code 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 {@code Object} is * output in summary mode. *

* *

* This is output after the size value. *

* *

* {@code 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 = EMPTY; } this.summaryObjectEndText = summaryObjectEndText; } //---------------------------------------------------------------------------- /** *

* Default {@code ToStringStyle}. *

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. *

*/ 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(); } /** *

* Ensure {@code Singleton} after serialization. *

* * @return the singleton */ private Object readResolve(){ return DEFAULT_STYLE; } } //---------------------------------------------------------------------------- /** *

* {@code ToStringStyle} that does not print out * the field names. *

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. */ 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); } /** *

* Ensure {@code Singleton} after serialization. *

* * @return the singleton */ private Object readResolve(){ return NO_FIELD_NAMES_STYLE; } } //---------------------------------------------------------------------------- /** *

* {@code ToStringStyle} that prints out the short * class name and no identity hashcode. *

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. *

*/ 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); } /** *

* Ensure Singleton after serialization. *

* * @return the singleton */ private Object readResolve(){ return SHORT_PREFIX_STYLE; } } //---------------------------------------------------------------------------- /** *

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

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. *

*/ 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(EMPTY); this.setContentEnd(EMPTY); } /** *

* Ensure Singleton after serialization. *

* * @return the singleton */ private Object readResolve(){ return SIMPLE_STYLE; } } //---------------------------------------------------------------------------- /** *

* {@code ToStringStyle} that outputs on multiple lines. *

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. *

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

* Constructor. *

* *

* Use the static constant rather than instantiating. *

*/ MultiLineToStringStyle(){ super(); this.setContentStart("["); this.setFieldSeparator(System.lineSeparator() + " "); this.setFieldSeparatorAtStart(true); this.setContentEnd(System.lineSeparator() + "]"); } /** *

* Ensure {@code Singleton} after serialization. *

* * @return the singleton */ private Object readResolve(){ return MULTI_LINE_STYLE; } } //---------------------------------------------------------------------------- /** *

* {@code ToStringStyle} that does not print out the classname * and identity hash code but prints content start and field names. *

* *

* This is an inner class rather than using * {@code StandardToStringStyle} to ensure its immutability. *

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

* Constructor. *

* *

* Use the static constant rather than instantiating. *

*/ NoClassNameToStringStyle(){ super(); this.setUseClassName(false); this.setUseIdentityHashCode(false); } /** *

* Ensure {@code Singleton} after serialization. *

* * @return the singleton */ private Object readResolve(){ return NO_CLASS_NAME_STYLE; } } // ---------------------------------------------------------------------------- }