package org.ovirt.engine.core.common.utils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
/**
* Eases implementation of {@code toString()} methods.
*
* TODO: When our business entities won't be compiled with GWT compiler this class could be replaced/refactored using
* TODO: commons-lang {@code ToStringBuilder} or guava {@code MoreObjects.ToStringHelper}
*/
public class ToStringBuilder {
static final char CLASS_NAME_SUFFIX = ':';
static final char ATTRIBUTES_LIST_PREFIX = '{';
static final char ATTRIBUTES_LIST_SUFFIX = '}';
static final String ATTRIBUTES_SEPARATOR = ", ";
static final String NAME_VALUE_SEPARATOR = "='";
static final char VALUE_SUFFIX = '\'';
static final String FILTERED_CONTENT = "***";
/**
* Buffer to store class name and its attributes
*/
private final StringBuilder buffer;
/**
* Indicates if at least one attribute was already appended {@code false} or not {@code true}
*/
private boolean noAttributes;
private ToStringBuilder() {
this(null);
}
private ToStringBuilder(Class<?> clazz) {
buffer = new StringBuilder();
noAttributes = true;
appendClassName(clazz);
}
/**
* Creates builder instance for specified class
*/
public static ToStringBuilder forClass(Class<?> clazz) {
return new ToStringBuilder(clazz);
}
/**
* Creates builder instance for specified instance
*/
public static ToStringBuilder forInstance(Object instance) {
return new ToStringBuilder(instance == null ? null : instance.getClass());
}
/**
* Appends {@code boolean} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final boolean value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code boolean[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final boolean[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code byte} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final byte value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code byte[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final byte[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code char} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final char value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code char[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final char[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code double} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final double value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code double[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final double[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code float} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final float value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code float[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final float[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code int} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final int value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code int[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final int[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code long} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final long value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code long[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final long[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code Object} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final Object value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code Object[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final Object[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code short} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final short value) {
appendAttribute(name, String.valueOf(value));
return this;
}
/**
* Appends {@code short[]} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder append(final String name, final short[] value) {
appendAttribute(name, Arrays.toString(value));
return this;
}
/**
* Appends {@code Collection} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public <T> ToStringBuilder append(final String name, final Collection<T> value) {
appendAttribute(name, value == null ? null : Arrays.toString(value.toArray()));
return this;
}
/**
* Appends {@code Map} attribute with specified {@code name} and {@code value}
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public <K, V> ToStringBuilder append(final String name, final Map<K, V> value) {
append(name, value == null ? null : value.entrySet());
return this;
}
/**
* Appends {@code String} attribute with specified {@code name} and its filtered {@code value}:
* <ul>
* <li>If value is not {@code null}, then {@code getFilteredContent()} is appended as value</li>
* <li>Otherwise {@code null} is appended as value</li>
* </ul>
*
* @param name
* attribute name
* @param value
* attribute value
* @return this
*/
public ToStringBuilder appendFiltered(final String name, final String value) {
appendAttribute(name, filterValue(value));
return this;
}
/**
* Saves specified class and its attributes into {@code String}
*/
public String build() {
final int bufferLength = buffer.length();
if (bufferLength > 0) {
final char lastChar = buffer.charAt(bufferLength - 1);
if (lastChar == VALUE_SUFFIX) {
// at least one attribute was added to list
buffer.append(ATTRIBUTES_LIST_SUFFIX);
} else if (lastChar == CLASS_NAME_SUFFIX) {
// only class name was added to buffer
buffer.append(ATTRIBUTES_LIST_PREFIX);
buffer.append(ATTRIBUTES_LIST_SUFFIX);
}
}
return buffer.toString();
}
/**
* Appends attribute with specified name and value to buffer
*/
private void appendAttribute(String name, String value) {
appendSeparatorOrPrefix();
buffer.append(name);
buffer.append(NAME_VALUE_SEPARATOR);
buffer.append(value);
buffer.append(VALUE_SUFFIX);
}
/**
* Appends attributes separator or attributes list prefix when needed
*/
private void appendSeparatorOrPrefix() {
if (noAttributes) {
// append prefix of attributes list
buffer.append(ATTRIBUTES_LIST_PREFIX);
noAttributes = false;
} else {
// except for 1st attribute we need to append separator
buffer.append(ATTRIBUTES_SEPARATOR);
}
}
/**
* Appends name of specified class to buffer
*/
private void appendClassName(Class<?> clazz) {
if (clazz != null) {
buffer.append(clazz.getSimpleName());
buffer.append(CLASS_NAME_SUFFIX);
}
}
/**
* Filters specified value
*/
private String filterValue(String value) {
return value == null ? null : FILTERED_CONTENT;
}
}