From 12c32597453bd6e855d96dd9de1cecec90ff8ea2 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Tue, 17 Sep 2002 22:07:20 +0000 Subject: [PATCH] Initial checkin of ToStringBuilder and assistants git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk@137032 13f79535-47bb-0310-9956-ffa450edef68 --- .../lang/builder/StandardToStringStyle.java | 460 ++++++ .../commons/lang/builder/ToStringBuilder.java | 929 +++++++++++ .../commons/lang/builder/ToStringStyle.java | 1393 +++++++++++++++++ 3 files changed, 2782 insertions(+) create mode 100644 src/java/org/apache/commons/lang/builder/StandardToStringStyle.java create mode 100644 src/java/org/apache/commons/lang/builder/ToStringBuilder.java create mode 100644 src/java/org/apache/commons/lang/builder/ToStringStyle.java diff --git a/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java b/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java new file mode 100644 index 000000000..0effd1106 --- /dev/null +++ b/src/java/org/apache/commons/lang/builder/StandardToStringStyle.java @@ -0,0 +1,460 @@ +package org.apache.commons.lang.builder; +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +// package org.apache.commons.lang.builder + +/** + * StandardToStringStyle works with ToStringBuilder to create a + * toString. + *

+ * This class is intended to be used as a singleton. There is no need + * to instantiate a new style each time. Your code should instantiate the class + * once, customize the values as required, and then store the result in a + * public static final variable for the rest of the program to access. + * + * @author Stephen Colebourne + * @version $Id: StandardToStringStyle.java,v 1.1 2002/09/17 22:07:20 scolebourne Exp $ + */ +public class StandardToStringStyle extends ToStringStyle { + + /** + * Constructor. + */ + public StandardToStringStyle() { + super(); + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to use the class name. + * @return the current useClassName flag + */ + public boolean isUseClassName() { + return useClassName; + } + + /** + * Sets whether to use the class name. + * @param useClassName the new useClassName flag + */ + public void setUseClassName(boolean useClassName) { + this.useClassName = useClassName; + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to output short or long class names. + * @return the current shortClassName flag + */ + public boolean isShortClassName() { + return useShortClassName; + } + + /** + * Sets whether to output short or long class names. + * @param shortClassName the new shortClassName flag + */ + public void setShortClassName(boolean shortClassName) { + this.useShortClassName = shortClassName; + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to use the identity hash code. + * @return the current useIdentityHashCode flag + */ + public boolean isUseIdentityHashCode() { + return useIdentityHashCode; + } + + /** + * Sets whether to use the identity hash code. + * @param useFieldNames the new useIdentityHashCode flag + */ + public void setUseIdentityHashCode(boolean useIdentityHashCode) { + this.useIdentityHashCode = useIdentityHashCode; + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to use the field names passed in. + * @return the current useFieldNames flag + */ + public boolean isUseFieldNames() { + return useFieldNames; + } + + /** + * Sets whether to use the field names passed in. + * @param useFieldNames the new useFieldNames flag + */ + public void setUseFieldNames(boolean useFieldNames) { + this.useFieldNames = useFieldNames; + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to use full detail when the caller doesn't specify. + * @return the current defaultFullDetail flag + */ + public boolean isDefaultFullDetail() { + return defaultFullDetail; + } + + /** + * Sets whether to use full detail when the caller doesn't specify. + * @param defaultFullDetail the new defaultFullDetail flag + */ + public void setDefaultFullDetail(boolean defaultFullDetail) { + this.defaultFullDetail = defaultFullDetail; + } + + //--------------------------------------------------------------------- + + /** + * Gets whether to output array content detail. + * @return the current array content detail setting + */ + public boolean isArrayContentDetail() { + return arrayContentDetail; + } + + /** + * Sets whether to output array content detail. + * @param arrayContentDetail the new arrayContentDetail flag + */ + public void setArrayContentDetail(boolean arrayContentDetail) { + this.arrayContentDetail = arrayContentDetail; + } + + //--------------------------------------------------------------------- + + /** + * Gets the array start text. + * @return the current array start text + */ + public String getArrayStart() { + return arrayStart; + } + + /** + * Sets the array start text. + * Null is accepted, but will be converted to a blank string. + * @param arrayStart the new array start text + */ + public void setArrayStart(String arrayStart) { + if (arrayStart == null) { + arrayStart = ""; + } + this.arrayStart = arrayStart; + } + + //--------------------------------------------------------------------- + + /** + * Gets the array end text. + * @return the current array end text + */ + public String getArrayEnd() { + return arrayEnd; + } + + /** + * Sets the array end text. + * Null is accepted, but will be converted to a blank string. + * @param arrayEnd the new array end text + */ + public void setArrayEnd(String arrayEnd) { + if (arrayStart == null) { + arrayStart = ""; + } + this.arrayEnd = arrayEnd; + } + + //--------------------------------------------------------------------- + + /** + * Gets the array separator text. + * @return the current array separator text + */ + public String getArraySeparator() { + return arraySeparator; + } + + /** + * Sets the array separator text. + * Null is accepted, but will be converted to a blank string. + * @param arraySeparator the new array separator text + */ + public void setArraySeparator(String arraySeparator) { + if (arraySeparator == null) { + arraySeparator = ""; + } + this.arraySeparator = arraySeparator; + } + + //--------------------------------------------------------------------- + + /** + * Gets the content start text. + * @return the current content start text + */ + public String getContentStart() { + return contentStart; + } + + /** + * Sets the content start text. + * Null is accepted, but will be converted to a blank string. + * @param contentStart the new content start text + */ + public void setContentStart(String contentStart) { + if (contentStart == null) { + contentStart = ""; + } + this.contentStart = contentStart; + } + + //--------------------------------------------------------------------- + + /** + * Gets the content end text. + * @return the current content end text + */ + public String getContentEnd() { + return contentEnd; + } + + /** + * Sets the content end text. + * Null is accepted, but will be converted to a blank string. + * @param contentEnd the new content end text + */ + public void setContentEnd(String contentEnd) { + if (contentEnd == null) { + contentEnd = ""; + } + this.contentEnd = contentEnd; + } + + //--------------------------------------------------------------------- + + /** + * Gets the field name value separator text. + * @return the current field name value separator text + */ + public String getFieldNameValueSeparator() { + return fieldNameValueSeparator; + } + + /** + * Sets the field name value separator text. + * Null is accepted, but will be converted to a blank string. + * @param fieldNameValueSeparator the new field name value separator text + */ + public void setFieldNameValueSeparator(String fieldNameValueSeparator) { + if (fieldNameValueSeparator == null) { + fieldNameValueSeparator = ""; + } + this.fieldNameValueSeparator = fieldNameValueSeparator; + } + + //--------------------------------------------------------------------- + + /** + * Gets the field separator text. + * @return the current field separator text + */ + public String getFieldSeparator() { + return fieldSeparator; + } + + /** + * Sets the field separator text. + * Null is accepted, but will be converted to a blank string. + * @param fieldSeparator the new field separator text + */ + public void setFieldSeparator(String fieldSeparator) { + if (fieldSeparator == null) { + fieldSeparator = ""; + } + this.fieldSeparator = fieldSeparator; + } + + //--------------------------------------------------------------------- + + /** + * Gets the text to output when null found. + * @return the current text to output when null found + */ + public String getNullText() { + return nullText; + } + + /** + * Sets the text to output when null found. + * Null is accepted, but will be converted to a blank string. + * @param nullText the new text to output when null found + */ + public void setNullText(String nullText) { + if (nullText == null) { + nullText = ""; + } + this.nullText = nullText; + } + + //--------------------------------------------------------------------- + + /** + * Gets the text to output when a Collection, Map or Array size is output. + * This is output before the size value. + * @return the current start of size text + */ + public String getSizeStartText() { + return sizeStartText; + } + + /** + * Sets the text to output when a Collection, Map or Array size is output. + * This is output before the size value. + * Null is accepted, but will be converted to a blank string. + * @param sizeStartText the new start of size text + */ + public void setSizeStartText(String sizeStartText) { + if (sizeStartText == null) { + sizeStartText = ""; + } + this.sizeStartText = sizeStartText; + } + + //--------------------------------------------------------------------- + + /** + * Gets the text to output when a Collection, Map or Array size is output. + * This is output after the size value. + * @return the current end of size text + */ + public String getSizeEndText() { + return sizeEndText; + } + + /** + * Sets the text to output when a Collection, Map or Array size is output. + * This is output after the size value. + * Null is accepted, but will be converted to a blank string. + * @param sizeEndText the new end of size text + */ + public void setSizeEndText(String sizeEndText) { + if (sizeEndText == null) { + sizeEndText = ""; + } + this.sizeEndText = sizeEndText; + } + + //--------------------------------------------------------------------- + + /** + * Gets the text to output when an Object is output in summary mode. + * This is output before the size value. + * @return the current start of summary text + */ + public String getSummaryObjectStartText() { + return summaryObjectStartText; + } + + /** + * Sets the text to output when an Object is output in summary mode. + * This is output before the size value. + * Null is accepted, but will be converted to a blank string. + * @param summaryObjectStartText the new start of summary text + */ + public void setSummaryObjectStartText(String summaryObjectStartText) { + if (summaryObjectStartText == null) { + summaryObjectStartText = ""; + } + this.summaryObjectStartText = summaryObjectStartText; + } + + //--------------------------------------------------------------------- + + /** + * Gets the text to output when an Object is output in summary mode. + * This is output after the size value. + * @return the current end of summary text + */ + public String getSummaryObjectEndText() { + return summaryObjectEndText; + } + + /** + * Sets the text to output when an Object is output in summary mode. + * This is output after the size value. + * Null is accepted, but will be converted to a blank string. + * @param summaryObjectEndText the new end of summary text + */ + public void setSummaryObjectEndText(String summaryObjectEndText) { + if (summaryObjectEndText == null) { + summaryObjectEndText = ""; + } + this.summaryObjectEndText = summaryObjectEndText; + } + + //--------------------------------------------------------------------- + +} diff --git a/src/java/org/apache/commons/lang/builder/ToStringBuilder.java b/src/java/org/apache/commons/lang/builder/ToStringBuilder.java new file mode 100644 index 000000000..bd3c411f2 --- /dev/null +++ b/src/java/org/apache/commons/lang/builder/ToStringBuilder.java @@ -0,0 +1,929 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +package org.apache.commons.lang.builder; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +/** + * ToString generation routine. + *

+ * This class enables a good toString to be built for any class. This class aims + * to simplify the process by: + *

+ *

+ * To use this class write code as follows: + * + * public class Person { + * String name; + * int age; + * boolean isSmoker; + * + * ... + * + * public String toString() { + * return new ToStringBuilder(this). + * append(name, "name"). + * append(age, "age"). + * append(smoker, "smoker"). + * toString(); + * } + * } + * + * This will produce a toString of the format: + * Person@7f54[name=Stephen,age=29,smoker=false] + * + * @author Stephen Colebourne + * @version $Id: ToStringBuilder.java,v 1.1 2002/09/17 22:07:20 scolebourne Exp $ + */ +public class ToStringBuilder { + + /** + * The default style of output to use + */ + private static ToStringStyle defaultStyle; + /** + * Current toString buffer + */ + private final StringBuffer buffer; + /** + * The style of output to use + */ + private final ToStringStyle style; + /** + * The object being output + */ + private final Object object; + + /** + * Constructor for ToStringBuilder. + * This constructor outputs using the default style set with + * setDefaultStyle. + * + * @param object the object to build a toString for, must not be null + * @throws IllegalArgumentException if the object passed in is null + */ + public ToStringBuilder(Object object) { + this(object, getDefaultStyle(), null); + } + + /** + * Constructor for ToStringBuilder specifying the output style. + *

+ * If the style is null, the default style is used. + * + * @param object the object to build a toString for, must not be null + * @param style the style of the toString to create, may be null + * @throws IllegalArgumentException if the object passed in is null + */ + public ToStringBuilder(Object object, ToStringStyle style) { + this(object, style, null); + } + + /** + * Constructor for ToStringBuilder. + *

+ * If the style is null, the default style is used. + * If the buffer is null, a new one is created. + * + * @param object the object to build a toString for, must not be null + * @param style the style of the toString to create, may be null + * @param buffer the string buffer to populate, may be null + * @throws IllegalArgumentException if the object passed in is null + */ + public ToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) { + super(); + if (object == null) { + throw new IllegalArgumentException("The object to create a toString for must not be null"); + } + if (style == null) { + style = ToStringStyle.DEFAULT_STYLE; + } + if (buffer == null) { + buffer = new StringBuffer(512); + } + this.buffer = buffer; + this.style = style; + this.object = object; + + style.appendStart(buffer, object); + } + + //---------------------------------------------------------------------------- + + /** + * Gets the default style to use. + *

+ * This could allow the toString style to be controlled for an entire + * application with one call. This might be used to have a verbose toString + * during development and a compact toString in production. + * + * @return the default toString style + */ + public static ToStringStyle getDefaultStyle() { + return defaultStyle; + } + + /** + * Sets the default style to use. + * + * @param style the default toString style + * @throws IllegalArgumentException if the style is null + */ + public static void setDefaultStyle(ToStringStyle style) { + if (style == null) { + throw new IllegalArgumentException("The style must not be null"); + } + defaultStyle = style; + } + + //------------------------------------------------------------------------- + + /** + * This method uses reflection to build a suitable toString using the default style. + *

+ * It uses Field.setAccessible to gain access to private fields. This means + * that it will throw a security exception if run under a security manger, if + * the permissions are not set up. + * It is also not as efficient as testing explicitly. + * Transient members will be not be included, as they are likely derived. + * Static fields will be not be included. + * fields, and not part of the value of the object. + * + * @param object the object to be output + * @return the String result + * @throws IllegalArgumentException if the object is null + */ + public static String reflectionToString(Object object) { + return reflectionToString(object, null, false); + } + + /** + * This method uses reflection to build a suitable toString. + *

+ * It uses Field.setAccessible to gain access to private fields. This means + * that it will throw a security exception if run under a security manger, if + * the permissions are not set up. + * It is also not as efficient as testing explicitly. + * Transient members will be not be included, as they are likely derived. + * Static fields will be not be included. + * fields, and not part of the value of the object. + *

+ * If the style is null, the default style is used. + * + * @param object the object to be output + * @param style the style of the toString to create, may be null + * @return the String result + * @throws IllegalArgumentException if the object or style is null + */ + public static String reflectionToString(Object object, ToStringStyle style) { + return reflectionToString(object, style, false); + } + + /** + * This method uses reflection to build a suitable toString. + *

+ * It uses Field.setAccessible to gain access to private fields. This means + * that it will throw a security exception if run under a security manger, if + * the permissions are not set up. + * It is also not as efficient as testing explicitly. + * If the outputTransients parameter is set to true, transient members will be + * output, otherwise they are ignored, as they are likely derived fields, and + * not part of the value of the object. + * Static fields will not be tested. + *

+ * If the style is null, the default style is used. + * + * @param object the object to be output + * @param style the style of the toString to create, may be null + * @param outputTransients whether to include transient fields + * @return the String result + * @throws IllegalArgumentException if the object or style is null + */ + public static String reflectionToString(Object object, ToStringStyle style, + boolean outputTransients) { + if (object == null) { + throw new IllegalArgumentException("The object must not be null"); + } + if (style == null) { + style = getDefaultStyle(); + } + Field[] fields = object.getClass().getDeclaredFields(); + Field.setAccessible(fields, true); + ToStringBuilder builder = new ToStringBuilder(object, style); + for (int i = 0; i < fields.length; ++i) { + Field f = fields[i]; + if (outputTransients || !Modifier.isTransient(f.getModifiers())) { + if (!Modifier.isStatic(f.getModifiers())) { + try { + builder.append(f.getName(), f.get(object)); + + } catch (IllegalAccessException ex) { + //this can't happen. Would get a Security exception instead + //throw a runtime exception in case the impossible happens. + throw new InternalError("Unexpected IllegalAccessException"); + } + } + } + } + return builder.toString(); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an Object value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(Object object) { + style.append(buffer, null, object, null); + return this; + } + + /** + * Append to the toString an Object value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, Object object) { + style.append(buffer, fieldName, object, null); + return this; + } + + /** + * Append to the toString an Object value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, Object object, boolean fullDetail) { + style.append(buffer, fieldName, object, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a long value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(long value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a long value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, long value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an int value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(int value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString an int value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, int value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a short value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(short value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a short value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, short value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a char value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(char value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a char value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, char value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a byte value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(byte value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a byte value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, byte value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a double value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(double value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a double value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, double value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a float value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(float value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a float value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, float value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a boolean value. + * + * @param value the value to add to the toString + * @return this + */ + public ToStringBuilder append(boolean value) { + style.append(buffer, null, value); + return this; + } + + /** + * Append to the toString a boolean value. + * + * @param value the value to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, boolean value) { + style.append(buffer, fieldName, value); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an Object array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(Object[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append to the toString an Object array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(String fieldName, Object[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString an Object array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, Object[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a long array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(long[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a long array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, long[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a long array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, long[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a int array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(int[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for an int array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, int[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString an int array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, int[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a short array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(short[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a short array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, short[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a short array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, short[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a char array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(char[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a char array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, char[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a char array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, char[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a byte array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(byte[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a byte array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, byte[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a byte array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, byte[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a double array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(double[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a double array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, double[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a double array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, double[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a float array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(float[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a float array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, float[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a float array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, float[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a boolean array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @return this + */ + public ToStringBuilder append(boolean[] array) { + style.append(buffer, null, array, null); + return this; + } + + /** + * Append a hashCode for a boolean array. + * + * @param array the array to add to the hashCode + * @return this + */ + public ToStringBuilder append(String fieldName, boolean[] array) { + style.append(buffer, fieldName, array, null); + return this; + } + + /** + * Append to the toString a boolean array. + *

+ * A boolean parameter controls the level of detail to show. Setting true + * will output the array in full. Setting false will output a summary, + * typically the size of the array. + * + * @param array the array to add to the toString + * @param fieldName the field name + * @param fullDetail true for detail, false for summary info + * @return this + */ + public ToStringBuilder append(String fieldName, boolean[] array, boolean fullDetail) { + style.append(buffer, fieldName, array, new Boolean(fullDetail)); + return this; + } + + //---------------------------------------------------------------------------- + + /** + * Gets the buffer being populated + * + * @return the StringBuffer being populated + */ + public StringBuffer getStringBuffer() { + return buffer; + } + + /** + * Returns the built toString + * + * @return the String toString + */ + public String toString() { + style.appendEnd(buffer, object); + return buffer.toString(); + } + +} diff --git a/src/java/org/apache/commons/lang/builder/ToStringStyle.java b/src/java/org/apache/commons/lang/builder/ToStringStyle.java new file mode 100644 index 000000000..402327fec --- /dev/null +++ b/src/java/org/apache/commons/lang/builder/ToStringStyle.java @@ -0,0 +1,1393 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ +// package org.apache.commons.lang.builder + +package org.apache.commons.lang.builder; +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; + +import org.apache.commons.lang.SystemUtils; +/** + * ToStringStyle works with ToStringBuilder to create a + * toString. + *

+ * These classes are intended to be used as singletons. There is no need + * to instantiate a new style each time. A prohram will generally use one + * of the predefined constants on this class. Alternatively, the + * {@link StandardToStringStyle} class can be used to set the individual + * settings. + *

+ * If necessary, this class can be subclassed to provide specific toString + * designs. The main public interface is always via ToStringBuilder however. + * + * @author Stephen Colebourne + * @version $Id: ToStringStyle.java,v 1.1 2002/09/17 22:07:20 scolebourne Exp $ + */ +public abstract class ToStringStyle implements Serializable { + + /** + * The default toString style. + */ + public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle(); + /** + * The multi line toString style. + */ + public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle(); + /** + * The no field names toString style. + */ + public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle(); + /** + * The simple toString style. + */ + public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle(); + + /** + * Whether to use the field names 'true' + */ + protected boolean useFieldNames = true; + /** + * Whether to use the class name 'true' + */ + protected boolean useClassName = true; + /** + * Whether to use short class names 'false' + */ + protected boolean useShortClassName = false; + /** + * Whether to use the identity hash code 'true' + */ + protected boolean useIdentityHashCode = true; + + /** + * The content start '[' + */ + protected String contentStart = "["; + /** + * The content end ']' + */ + protected String contentEnd = "]"; + /** + * The field name value separator '=' + */ + protected String fieldNameValueSeparator = "="; + /** + * The field separator ',' + */ + protected String fieldSeparator = ","; + /** + * The array start '{' + */ + protected String arrayStart = "{"; + /** + * The array separator ',' + */ + protected String arraySeparator = ","; + /** + * The detail for array content + */ + protected boolean arrayContentDetail = true; + /** + * The array end '}' + */ + protected String arrayEnd = "}"; + /** + * The value to use when fullDetail is null 'true' + */ + protected boolean defaultFullDetail = true; + /** + * The null text '' + */ + protected String nullText = ""; + /** + * The summary size text start '' + */ + protected String sizeEndText = ">"; + /** + * The summary object text start '<' + */ + protected String summaryObjectStartText = "<"; + /** + * The summary object text start '>' + */ + protected String summaryObjectEndText = ">"; + + //---------------------------------------------------------------------------- + + /** + * Constructor. + */ + protected ToStringStyle() { + super(); + } + + //---------------------------------------------------------------------------- + + /** + * Append the start of data indicator. + * + * @param buffer the StringBuffer to populate + * @param object the object to build a toString for, must not be null + */ + public void appendStart(StringBuffer buffer, Object object) { + appendClassName(buffer, object); + appendIdentityHashCode(buffer, object); + appendContentStart(buffer); + } + + /** + * Append the end of data indicator. + * + * @param buffer the StringBuffer to populate + * @param object the object to build a toString for, must not be null + */ + public void appendEnd(StringBuffer buffer, Object object) { + appendContentEnd(buffer); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an Object value, printing the full + * toString of the object passed in. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString an Object, correctly interpretting its type. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString, not null + * @param detail output detail or not + */ + protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) { + 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, (Object) value); + } else { + appendSummary(buffer, fieldName, (Object) value); + } + } + } + + /** + * Append to the toString an Object value, printing the full detail of the object. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString, not null + */ + protected void appendDetail(StringBuffer buffer, String fieldName, Object value) { + buffer.append(value); + } + + /** + * Append to the toString a Collection. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param coll the collection to add to the toString, not null + */ + protected void appendDetail(StringBuffer buffer, String fieldName, Collection coll) { + buffer.append(coll); + } + + /** + * Append to the toString a Map. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param map the maps to add to the toString, not null + */ + protected void appendDetail(StringBuffer buffer, String fieldName, Map map) { + buffer.append(map); + } + + /** + * Append to the toString an Object value, printing a summary of the object. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, Object value) { + buffer.append(summaryObjectStartText); + buffer.append(getShortClassName(value.getClass())); + buffer.append(summaryObjectEndText); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a long value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, long value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a long value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, long value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an int value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, int value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString an int value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, int value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a short value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, short value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a short value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, short value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a byte value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, byte value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a byte value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, byte value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a char value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, char value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a char value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, char value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a double value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, double value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a double value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, double value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a float value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, float value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a float value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, float value) { + buffer.append(value); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a boolean value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param value the value to add to the toString + */ + public void append(StringBuffer buffer, String fieldName, boolean value) { + appendFieldStart(buffer, fieldName); + appendDetail(buffer, fieldName, value); + appendFieldEnd(buffer, fieldName); + } + + /** + * Append to the toString a boolean value. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param value the value to add to the toString + */ + protected void appendDetail(StringBuffer buffer, String fieldName, boolean value) { + buffer.append(value); + } + + /** + * Append to the toString an Object array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString the detail of an Object array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of an Object array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, Object[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a long array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a long array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a long array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, long[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString an int array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of an int array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of an int array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, int[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a short array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a short array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a short array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, short[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a byte array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a byte array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a byte array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, byte[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a char array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a char array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a char array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, char[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a double array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a double array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a double array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, double[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a float array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a float array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a float array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, float[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append to the toString a boolean array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + * @param array the array to add to the toString + * @param fullDetail true for detail, false for summary info, null for style decides + */ + public void append(StringBuffer 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); + } + + /** + * Append to the toString the detail of a boolean array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendDetail(StringBuffer 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); + } + + /** + * Append to the toString a summary of a boolean array. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param array the array to add to the toString, not null + */ + protected void appendSummary(StringBuffer buffer, String fieldName, boolean[] array) { + appendSummarySize(buffer, fieldName, array.length); + } + + //---------------------------------------------------------------------------- + + /** + * Append the class name. + * + * @param object the object whose name to output + */ + protected void appendClassName(StringBuffer buffer, Object object) { + if (useClassName) { + if (useShortClassName) { + buffer.append(getShortClassName(object.getClass())); + } else { + buffer.append(object.getClass().getName()); + } + } + } + + /** + * Append the IdentityHashCode. + * + * @param object the object whose id to output + */ + protected void appendIdentityHashCode(StringBuffer buffer, Object object) { + if (useIdentityHashCode) { + buffer.append('@'); + buffer.append(Integer.toHexString(System.identityHashCode(object))); + } + } + + /** + * Append the content start to the buffer. + * + * @param buffer the StringBuffer to populate + */ + protected void appendContentStart(StringBuffer buffer) { + buffer.append(contentStart); + } + + /** + * Append the content end to the buffer. + * + * @param buffer the StringBuffer to populate + */ + protected void appendContentEnd(StringBuffer buffer) { + int len = buffer.length(); + int sepLen = fieldSeparator.length(); + if (len > 0 && sepLen > 0 && len >= sepLen && buffer.charAt(len - 1) == fieldSeparator.charAt(sepLen - 1)) { + buffer.setLength(len - sepLen); + } + buffer.append(contentEnd); + } + + /** + * Append an indicator for null to the buffer. + * Default output is ''. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + */ + protected void appendNullText(StringBuffer buffer, String fieldName) { + buffer.append(nullText); + } + + /** + * Append the field separator to the buffer. + * + * @param buffer the StringBuffer to populate + */ + protected void appendFieldSeparator(StringBuffer buffer) { + buffer.append(fieldSeparator); + } + + /** + * Append the field start to the buffer. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name + */ + protected void appendFieldStart(StringBuffer buffer, String fieldName) { + if (useFieldNames && fieldName != null) { + buffer.append(fieldName); + buffer.append(fieldNameValueSeparator); + } + } + + /** + * Append the field end to the buffer. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + */ + protected void appendFieldEnd(StringBuffer buffer, String fieldName) { + appendFieldSeparator(buffer); + } + + /** + * Append to the toString a size summary. + * + * @param buffer the StringBuffer to populate + * @param fieldName the field name, typically not used as already appended + * @param size the size to append + */ + protected void appendSummarySize(StringBuffer buffer, String fieldName, int size) { + buffer.append(sizeStartText); + buffer.append(size); + buffer.append(sizeEndText); + } + + /** + * Is this field to be output in full detail. + * + * @param fullDetail the detail level requested + * @return whether full detail is to be shown + */ + protected boolean isFullDetail(Boolean fullDetailRequest) { + if (fullDetailRequest == null) { + return defaultFullDetail; + } + return fullDetailRequest.booleanValue(); + } + + /** + * Gets the short class name for a class. + * + * @param cls the class to get the short name of + * @return the short name + */ + protected String getShortClassName(Class cls) { + String name = cls.getName(); + int pos = name.lastIndexOf('.'); + if (pos == -1) { + return name; + } + return name.substring(pos + 1); + } + + //---------------------------------------------------------------------------- + + /** + * Default ToStringStyle. + * This is an inner class rather than using StandardToStringStyle to + * ensure its immutability. + */ + private static class DefaultToStringStyle extends ToStringStyle { + + /** + * Constructor - use the static constant rather than instantiating. + */ + private DefaultToStringStyle() { + super(); + } + + /** + * Ensure singleton after serialization. + */ + private Object readResolve() { + return ToStringStyle.DEFAULT_STYLE; + } + + } + + //---------------------------------------------------------------------------- + + /** + * ToStringStyle that does not print out the field names. + * This is an inner class rather than using StandardToStringStyle to + * ensure its immutability. + */ + private static class NoFieldNameToStringStyle extends ToStringStyle { + + /** + * Constructor - use the static constant rather than instantiating. + */ + private NoFieldNameToStringStyle() { + super(); + useFieldNames = false; + } + + /** + * Ensure singleton after serialization. + */ + private Object readResolve() { + return ToStringStyle.NO_FIELD_NAMES_STYLE; + } + + } + + //---------------------------------------------------------------------------- + + /** + * ToStringStyle that does not print out the classname, identity hashcode, + * content start or field name. + * This is an inner class rather than using StandardToStringStyle to + * ensure its immutability. + */ + private static class SimpleToStringStyle extends ToStringStyle { + + /** + * Constructor - use the static constant rather than instantiating. + */ + private SimpleToStringStyle() { + super(); + useClassName = false; + useIdentityHashCode = false; + useFieldNames = false; + contentStart = ""; + contentEnd = ""; + } + + /** + * Ensure singleton after serialization. + */ + private Object readResolve() { + return ToStringStyle.SIMPLE_STYLE; + } + + } + + //---------------------------------------------------------------------------- + + /** + * ToStringStyle that outputs on multiple lines. + * This is an inner class rather than using StandardToStringStyle to + * ensure its immutability. + */ + private static class MultiLineToStringStyle extends ToStringStyle { + + /** + * Constructor - use the static constant rather than instantiating. + */ + private MultiLineToStringStyle() { + super(); + contentStart = "[" + SystemUtils.LINE_SEPARATOR + " "; + fieldSeparator = SystemUtils.LINE_SEPARATOR + " "; + contentEnd = SystemUtils.LINE_SEPARATOR + "]"; + } + + /** + * Ensure singleton after serialization. + */ + private Object readResolve() { + return ToStringStyle.MULTI_LINE_STYLE; + } + + } + + //---------------------------------------------------------------------------- + + // Removed, as the XML style needs more work for escaping characters, arrays, + // collections, maps and embedded beans. +// /** +// * ToStringStyle that outputs in XML style +// */ +// private static class XMLToStringStyle extends ToStringStyle { +// +// /** +// * Constructor - use the static constant rather than instantiating. +// */ +// private XMLToStringStyle() { +// super(); +// nullText = "null"; +// sizeStartText = "size="; +// sizeEndText = ""; +// } +// +// /** +// * @see ToStringStyle#appendStart(StringBuffer, Object) +// */ +// public void appendStart(StringBuffer buffer, Object object) { +// buffer.append('<'); +// buffer.append(getShortClassName(object.getClass())); +// buffer.append(" class=\""); +// appendClassName(buffer, object); +// buffer.append("\" hashCode=\""); +// appendIdentityHashCode(buffer, object); +// buffer.append("\">"); +// buffer.append(SystemUtils.LINE_SEPARATOR); +// buffer.append(" "); +// } +// +// /** +// * @see ToStringStyle#appendFieldStart(StringBuffer, String) +// */ +// protected void appendFieldStart(StringBuffer buffer, String fieldName) { +// buffer.append('<'); +// buffer.append(fieldName); +// buffer.append('>'); +// } +// +// /** +// * @see ToStringStyle#appendFieldEnd(StringBuffer, String) +// */ +// protected void appendFieldEnd(StringBuffer buffer, String fieldName) { +// buffer.append("'); +// buffer.append(SystemUtils.LINE_SEPARATOR); +// buffer.append(" "); +// } +// +// /** +// * @see ToStringStyle#appendEnd(StringBuffer, Object) +// */ +// public void appendEnd(StringBuffer buffer, Object object) { +// int len = buffer.length(); +// if (len > 2 && buffer.charAt(len - 1) == ' ' && buffer.charAt(len - 2) == ' ') { +// buffer.setLength(len - 2); +// } +// buffer.append(""); +// } +// +// } + +}