Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.builder;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.WeakHashMap;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
/**
* Controls {@link String} formatting for {@link ToStringBuilder}.
* The main public interface is always via {@link ToStringBuilder}.
*
*
These classes are intended to be used as singletons.
* There is no need to instantiate a new style each time. A program
* will generally use one of the predefined constants on this class.
* Alternatively, the {@link StandardToStringStyle} class can be used
* to set the individual settings. Thus most styles can be achieved
* without subclassing.
*
*
If required, a subclass can override as many or as few of the
* methods as it requires. Each object type (from {@code boolean}
* to {@code long} to {@link Object} to {@code int[]}) has
* its own methods to output it. Most have two versions, detail and summary.
*
*
For example, the detail version of the array based methods will
* output the whole array, whereas the summary method will just output
* the array length.
*
*
If you want to format the output of certain objects, such as dates, you
* must create a subclass and override a method.
*
*
* public class MyStyle extends ToStringStyle {
* protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
* if (value instanceof Date) {
* value = new SimpleDateFormat("yyyy-MM-dd").format(value);
* }
* buffer.append(value);
* }
* }
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class DefaultToStringStyle extends ToStringStyle {
/**
* Required for serialization support.
*
* @see java.io.Serializable
*/
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
DefaultToStringStyle() {
}
/**
* Ensure Singleton after serialization.
*
* @return the singleton
*/
private Object readResolve() {
return DEFAULT_STYLE;
}
}
/**
* {@link ToStringStyle} that outputs with JSON format.
*
*
* This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*
*
* @since 3.4
* @see json.org
*/
private static final class JsonToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
private static final String FIELD_NAME_QUOTE = "\"";
/**
* Constructor.
*
*
* Use the static constant rather than instantiating.
*
*/
JsonToStringStyle() {
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
this.setContentStart("{");
this.setContentEnd("}");
this.setArrayStart("[");
this.setArrayEnd("]");
this.setFieldSeparator(",");
this.setFieldNameValueSeparator(":");
this.setNullText("null");
this.setSummaryObjectStartText("\"<");
this.setSummaryObjectEndText(">\"");
this.setSizeStartText("\"\"");
}
@Override
public void append(final StringBuffer buffer, final String fieldName,
final boolean[] array, final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName, final byte[] array,
final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName, final char[] array,
final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName,
final double[] array, final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName,
final float[] array, final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName, final int[] array,
final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName, final long[] array,
final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName, final Object value,
final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, value, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName,
final Object[] array, final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
public void append(final StringBuffer buffer, final String fieldName,
final short[] array, final Boolean fullDetail) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
if (!isFullDetail(fullDetail)) {
throw new UnsupportedOperationException(
"FullDetail must be true when using JsonToStringStyle");
}
super.append(buffer, fieldName, array, fullDetail);
}
@Override
protected void appendDetail(final StringBuffer buffer, final String fieldName, final char value) {
appendValueAsString(buffer, String.valueOf(value));
}
@Override
protected void appendDetail(final StringBuffer buffer, final String fieldName, final Collection> coll) {
if (coll != null && !coll.isEmpty()) {
buffer.append(getArrayStart());
int i = 0;
for (final Object item : coll) {
appendDetail(buffer, fieldName, i++, item);
}
buffer.append(getArrayEnd());
return;
}
buffer.append(coll);
}
@Override
protected void appendDetail(final StringBuffer buffer, final String fieldName, final Map, ?> map) {
if (map != null && !map.isEmpty()) {
buffer.append(getContentStart());
boolean firstItem = true;
for (final Entry, ?> entry : map.entrySet()) {
final String keyStr = Objects.toString(entry.getKey(), null);
if (keyStr != null) {
if (firstItem) {
firstItem = false;
} else {
appendFieldEnd(buffer, keyStr);
}
appendFieldStart(buffer, keyStr);
final Object value = entry.getValue();
if (value == null) {
appendNullText(buffer, keyStr);
} else {
appendInternal(buffer, keyStr, value, true);
}
}
}
buffer.append(getContentEnd());
return;
}
buffer.append(map);
}
@Override
protected void appendDetail(final StringBuffer buffer, final String fieldName, final Object value) {
if (value == null) {
appendNullText(buffer, fieldName);
return;
}
if (value instanceof String || value instanceof Character) {
appendValueAsString(buffer, value.toString());
return;
}
if (value instanceof Number || value instanceof Boolean) {
buffer.append(value);
return;
}
final String valueAsString = value.toString();
if (isJsonObject(valueAsString) || isJsonArray(valueAsString)) {
buffer.append(value);
return;
}
appendDetail(buffer, fieldName, valueAsString);
}
@Override
protected void appendFieldStart(final StringBuffer buffer, final String fieldName) {
if (fieldName == null) {
throw new UnsupportedOperationException(
"Field names are mandatory when using JsonToStringStyle");
}
super.appendFieldStart(buffer, FIELD_NAME_QUOTE + StringEscapeUtils.escapeJson(fieldName)
+ FIELD_NAME_QUOTE);
}
/**
* Appends the given String enclosed in double-quotes to the given StringBuffer.
*
* @param buffer the StringBuffer to append the value to.
* @param value the value to append.
*/
private void appendValueAsString(final StringBuffer buffer, final String value) {
buffer.append('"').append(StringEscapeUtils.escapeJson(value)).append('"');
}
private boolean isJsonArray(final String valueAsString) {
return valueAsString.startsWith(getArrayStart())
&& valueAsString.endsWith(getArrayEnd());
}
private boolean isJsonObject(final String valueAsString) {
return valueAsString.startsWith(getContentStart())
&& valueAsString.endsWith(getContentEnd());
}
/**
* Ensure Singleton after serialization.
*
* @return the singleton
*/
private Object readResolve() {
return JSON_STYLE;
}
}
/**
* {@link ToStringStyle} that outputs on multiple lines.
*
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class MultiLineToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
MultiLineToStringStyle() {
this.setContentStart("[");
this.setFieldSeparator(System.lineSeparator() + " ");
this.setFieldSeparatorAtStart(true);
this.setContentEnd(System.lineSeparator() + "]");
}
/**
* Ensure Singleton after serialization.
*
* @return the singleton
*/
private Object readResolve() {
return MULTI_LINE_STYLE;
}
}
/**
* {@link ToStringStyle} that does not print out the class name
* and identity hash code but prints content start and field names.
*
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class NoClassNameToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
NoClassNameToStringStyle() {
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
}
/**
* Ensure Singleton after serialization.
*
* @return the singleton
*/
private Object readResolve() {
return NO_CLASS_NAME_STYLE;
}
}
/**
* {@link ToStringStyle} that does not print out
* the field names.
*
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class NoFieldNameToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
NoFieldNameToStringStyle() {
this.setUseFieldNames(false);
}
/**
* Ensure Singleton after serialization.
*
* @return the singleton
*/
private Object readResolve() {
return NO_FIELD_NAMES_STYLE;
}
}
/**
* {@link ToStringStyle} that prints out the short
* class name and no identity hash code.
*
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class ShortPrefixToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
ShortPrefixToStringStyle() {
this.setUseShortClassName(true);
this.setUseIdentityHashCode(false);
}
/**
* Ensure Singleton after serialization.
* @return the singleton
*/
private Object readResolve() {
return SHORT_PREFIX_STYLE;
}
}
/**
* {@link ToStringStyle} that does not print out the
* class name, identity hash code, content start or field name.
*
*
This is an inner class rather than using
* {@link StandardToStringStyle} to ensure its immutability.
*/
private static final class SimpleToStringStyle extends ToStringStyle {
private static final long serialVersionUID = 1L;
/**
* Constructor.
*
*
Use the static constant rather than instantiating.
*/
SimpleToStringStyle() {
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
this.setUseFieldNames(false);
this.setContentStart(StringUtils.EMPTY);
this.setContentEnd(StringUtils.EMPTY);
}
/**
* Ensure Singleton after serialization.
* @return the singleton
*/
private Object readResolve() {
return SIMPLE_STYLE;
}
}
/**
* Serialization version ID.
*/
private static final long serialVersionUID = -2587890625525655916L;
/**
* The default toString style. Using the {@code Person}
* example from {@link ToStringBuilder}, the output would look like this:
*
*
*/
public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
/**
* The multi line toString style. Using the {@code Person}
* example from {@link ToStringBuilder}, the output would look like this:
*
*
*/
public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
/**
* The no field names toString style. Using the
* {@code Person} example from {@link ToStringBuilder}, the output
* would look like this:
*
*
* Person@182f0db[John Doe,33,false]
*
*/
public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
/**
* The short prefix toString style. Using the {@code Person} example
* from {@link ToStringBuilder}, the output would look like this:
*
*
* Person[name=John Doe,age=33,smoker=false]
*
*
* @since 2.1
*/
public static final ToStringStyle SHORT_PREFIX_STYLE = new ShortPrefixToStringStyle();
/**
* The simple toString style. Using the {@code Person}
* example from {@link ToStringBuilder}, the output would look like this:
*
*
* John Doe,33,false
*
*/
public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
/**
* The no class name toString style. Using the {@code Person}
* example from {@link ToStringBuilder}, the output would look like this:
*
*
* [name=John Doe,age=33,smoker=false]
*
*
* @since 3.4
*/
public static final ToStringStyle NO_CLASS_NAME_STYLE = new NoClassNameToStringStyle();
/**
* The JSON toString style. Using the {@code Person} example from
* {@link ToStringBuilder}, the output would look like this:
*
*
*
* Note: Since field names are mandatory in JSON, this
* ToStringStyle will throw an {@link UnsupportedOperationException} if no
* field name is passed in while appending. Furthermore This ToStringStyle
* will only generate valid JSON if referenced objects also produce JSON
* when calling {@code toString()} on them.
*
* @since 3.4
* @see json.org
*/
public static final ToStringStyle JSON_STYLE = new JsonToStringStyle();
/**
* A registry of objects used by {@code reflectionToString} methods
* to detect cyclical object references and avoid infinite loops.
*
*/
private static final ThreadLocal> REGISTRY = new ThreadLocal<>();
/*
* Note that objects of this class are generally shared between threads, so
* an instance variable would not be suitable here.
*
* In normal use the registry should always be left empty, because the caller
* should call toString() which will clean up.
*
* See LANG-792
*/
/**
* Returns the registry of objects being traversed by the {@code reflectionToString}
* methods in the current thread.
*
* @return Set the registry of objects being traversed
*/
public static Map