📄 tostringstyle.java
字号:
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002-2003 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 acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements 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
* <http://www.apache.org/>.
*/
package org.apache.commons.lang.builder;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.SystemUtils;
/**
* <p>Controls <code>String</code> formatting for {@link ToStringBuilder}.
* The main public interface is always via <code>ToStringBuilder</code>.</p>
*
* <p>These classes are intended to be used as <code>Singletons</code>.
* There is no need to instantiate a new style each time. A program
* will generally use one of the predefined constants on this class.
* Alternatively, the {@link StandardToStringStyle} class can be used
* to set the individual settings. Thus most styles can be achieved
* without subclassing.</p>
*
* <p>If required, a subclass can override as many or as few of the
* methods as it requires. Each object type (from <code>boolean</code>
* to <code>long</code> to <code>Object</code> to <code>int[]</code>) has
* its own methods to output it. Most have two versions, detail and summary.
*
* <p>For example, the detail version of the array based methods will
* output the whole array, whereas the summary method will just output
* the array length.</p>
*
* @author Stephen Colebourne
* @author Gary Gregory
* @author Pete Gieser
* @since 1.0
* @version $Id: ToStringStyle.java,v 1.27 2003/08/23 00:21:49 ggregory 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, the default is <code>true</code>.
*/
private boolean useFieldNames = true;
/**
* Whether to use the class name, the default is <code>true</code>.
*/
private boolean useClassName = true;
/**
* Whether to use short class names, the default is <code>false</code>.
*/
private boolean useShortClassName = false;
/**
* Whether to use the identity hash code, the default is <code>true</code>.
*/
private boolean useIdentityHashCode = true;
/**
* The content start <code>'['</code>.
*/
private String contentStart = "[";
/**
* The content end <code>']'</code>.
*/
private String contentEnd = "]";
/**
* The field name value separator <code>'='</code>.
*/
private String fieldNameValueSeparator = "=";
/**
* Whether the field separator should be added before any other fields.
*/
private boolean fieldSeparatorAtStart = false;
/**
* Whether the field separator should be added after any other fields.
*/
private boolean fieldSeparatorAtEnd = false;
/**
* The field separator <code>','</code>.
*/
private String fieldSeparator = ",";
/**
* The array start <code>'{'</code>.
*/
private String arrayStart = "{";
/**
* The array separator <code>','</code>.
*/
private String arraySeparator = ",";
/**
* The detail for array content.
*/
private boolean arrayContentDetail = true;
/**
* The array end <code>'}'</code>.
*/
private String arrayEnd = "}";
/**
* The value to use when fullDetail is <code>null</code>,
* the default value is <code>true</code>.
*/
private boolean defaultFullDetail = true;
/**
* The <code>null</code> text <code>'<null>'</code>.
*/
private String nullText = "<null>";
/**
* The summary size text start <code>'<size'</code>.
*/
private String sizeStartText = "<size=";
/**
* The summary size text start <code>'>'</code>.
*/
private String sizeEndText = ">";
/**
* The summary object text start <code>'<'</code>.
*/
private String summaryObjectStartText = "<";
/**
* The summary object text start <code>'>'</code>.
*/
private String summaryObjectEndText = ">";
//----------------------------------------------------------------------------
/**
* <p>Constructor.</p>
*/
protected ToStringStyle() {
super();
}
//----------------------------------------------------------------------------
/**
* <p>Append to the <code>toString</code> the superclass toString.</p>
*
* <p>A <code>null</code> <code>superToString</code> is ignored.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param superToString the <code>super.toString()</code>
* @since 2.0
*/
public void appendSuper(StringBuffer buffer, String superToString) {
appendToString(buffer, superToString);
}
/**
* <p>Append to the <code>toString</code> another toString.</p>
*
* <p>A <code>null</code> <code>toString</code> is ignored.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param toString the additional <code>toString</code>
* @since 2.0
*/
public void appendToString(StringBuffer buffer, String toString) {
if (toString != null) {
int pos1 = toString.indexOf(contentStart) + contentStart.length();
int pos2 = toString.lastIndexOf(contentEnd);
if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) {
String data = toString.substring(pos1, pos2);
if (fieldSeparatorAtStart) {
removeLastFieldSeparator(buffer);
}
buffer.append(data);
appendFieldSeparator(buffer);
}
}
}
/**
* <p>Append to the <code>toString</code> the start of data indicator.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param object the <code>Object</code> to build a
* <code>toString</code> for, must not be <code>null</code>
*/
public void appendStart(StringBuffer buffer, Object object) {
appendClassName(buffer, object);
appendIdentityHashCode(buffer, object);
appendContentStart(buffer);
if (fieldSeparatorAtStart) {
appendFieldSeparator(buffer);
}
}
/**
* <p>Append to the <code>toString</code> the end of data indicator.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param object the <code>Object</code> to build a
* <code>toString</code> for, must not be <code>null</code>
*/
public void appendEnd(StringBuffer buffer, Object object) {
if (fieldSeparatorAtEnd == false) {
removeLastFieldSeparator(buffer);
}
appendContentEnd(buffer);
}
/**
* <p>Remove the last field separator from the buffer.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @since 2.0
*/
protected void removeLastFieldSeparator(StringBuffer buffer) {
int len = buffer.length();
int sepLen = fieldSeparator.length();
if (len > 0 && sepLen > 0 && len >= sepLen) {
boolean match = true;
for (int i = 0; i < sepLen; i++) {
if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) {
match = false;
break;
}
}
if (match) {
buffer.setLength(len - sepLen);
}
}
}
//----------------------------------------------------------------------------
/**
* <p>Append to the <code>toString</code> an <code>Object</code>
* value, printing the full <code>toString</code> of the
* <code>Object</code> passed in.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param fieldName the field name
* @param value the value to add to the <code>toString</code>
* @param fullDetail <code>true</code> for detail, <code>false</code>
* for summary info, <code>null</code> for style decides
*/
public void append(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);
}
/**
* <p>Append to the <code>toString</code> an <code>Object</code>,
* correctly interpreting its type.</p>
*
* <p>This method performs the main lookup by Class type to correctly
* route arrays, <code>Collections</code>, <code>Maps</code> and
* <code>Objects</code> to the appropriate method.</p>
*
* <p>Either detail or summary views can be specified.</p>
*
* <p>If a cycle is detected, an object will be appended with the
* <code>Object.toString()</code> format.</p>
*
* @param buffer the <code>StringBuffer</code> to populate
* @param fieldName the field name, typically not used as already appended
* @param value the value to add to the <code>toString</code>,
* not <code>null</code>
* @param detail output detail or not
*/
protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) {
if (ReflectionToStringBuilder.isRegistered(value)
&& !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
ObjectUtils.appendIdentityToString(buffer, value);
} else 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[]) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -