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; } }