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.
Apache Commons Lang, a package of Java utility classes for the
classes that are in java.lang's hierarchy, or are considered to be so
standard as to justify existence in java.lang.
The code is tested using the latest revision of the JDK for supported
LTS releases: 8, 11, 17 and 21 currently.
See https://github.com/apache/commons-lang/blob/master/.github/workflows/maven.yml
Please ensure your build environment is up-to-date and kindly report any build issues.
/*
* 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;
/**
* Constructs a new instance.
*
*
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 = "\"";
/**
* Constructs a new instance.
*
*
* 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;
/**
* Constructs a new instance.
*
*
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;
/**
* Constructs a new instance.
*
*
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;
/**
* Constructs a new instance.
*
*
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;
/**
* Constructs a new instance.
*
*
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;
/**
* Constructs a new instance.
*
*
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 = ThreadLocal.withInitial(WeakHashMap::new);
/*
* 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