Martin Peřina has uploaded a new change for review. Change subject: common: Introduce ToStringBuilder ......................................................................
common: Introduce ToStringBuilder Introduces ToStringBuilder: - it eases implementation of toString() method - it makes output of toString() methods in the project consistent - it can be used with GWT (unlike for example commons-lang) Change-Id: I3d4baa2430a45b0281b7891eb19ad2094c1b3408 Signed-off-by: Martin Perina <mper...@redhat.com> --- A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/ToStringBuilder.java A backend/manager/modules/common/src/test/java/org/ovirt/engine/core/common/utils/ToStringBuilderTest.java M frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml 3 files changed, 581 insertions(+), 0 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/40/39240/1 diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/ToStringBuilder.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/ToStringBuilder.java new file mode 100644 index 0000000..f0af401 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/ToStringBuilder.java @@ -0,0 +1,384 @@ +package org.ovirt.engine.core.common.utils; + +import java.util.Arrays; + +/** + * 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 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; + } +} diff --git a/backend/manager/modules/common/src/test/java/org/ovirt/engine/core/common/utils/ToStringBuilderTest.java b/backend/manager/modules/common/src/test/java/org/ovirt/engine/core/common/utils/ToStringBuilderTest.java new file mode 100644 index 0000000..848c80f --- /dev/null +++ b/backend/manager/modules/common/src/test/java/org/ovirt/engine/core/common/utils/ToStringBuilderTest.java @@ -0,0 +1,196 @@ +package org.ovirt.engine.core.common.utils; + +import static org.junit.Assert.assertEquals; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Date; + +import org.junit.Test; + +public class ToStringBuilderTest { + /** + * If no class and attributes were specified, then empty string should be returned + */ + @Test + public void testEmptyForClass() { + assertEquals( + "", + ToStringBuilder.forClass(null).build()); + } + + /** + * If class without attributes was specified, then class name with empty attributes list should be returned + */ + @Test + public void testClassOnlyOutput() { + String expected = getClass().getSimpleName() + + ToStringBuilder.CLASS_NAME_SUFFIX + + ToStringBuilder.ATTRIBUTES_LIST_PREFIX + + ToStringBuilder.ATTRIBUTES_LIST_SUFFIX; + + assertEquals( + expected, + ToStringBuilder.forClass(ToStringBuilderTest.class).build()); + } + + /** + * If no instance and attributes were specified, then empty string should be returned + */ + @Test + public void testEmptyForInstance() { + assertEquals( + "", + ToStringBuilder.forInstance(null).build()); + } + + /** + * If instance without attributes was specified, then class name with empty attributes list should be returned + */ + @Test + public void testInstanceOnlyOutput() { + String expected = getClass().getSimpleName() + + ToStringBuilder.CLASS_NAME_SUFFIX + + ToStringBuilder.ATTRIBUTES_LIST_PREFIX + + ToStringBuilder.ATTRIBUTES_LIST_SUFFIX; + + assertEquals( + expected, + ToStringBuilder.forInstance(this).build()); + } + + /** + * If attributes without class/instance were specified, then attributes list should be returned + */ + @Test + public void testAttributeOnlyOutput() { + String attributeName = "attr1"; + int attributeValue = 100; + String expected = ToStringBuilder.ATTRIBUTES_LIST_PREFIX + + createFirstAttributeOutput(attributeName, String.valueOf(attributeValue)) + + ToStringBuilder.ATTRIBUTES_LIST_SUFFIX; + + assertEquals( + expected, + ToStringBuilder.forInstance(null) + .append(attributeName, attributeValue) + .build()); + } + + + /** + * Tests valid output for all attribute types + */ + @Test + public void testAttributesConversion() { + final String booleanName = "booleanAttr"; + final boolean booleanValue = true; + final String booleanArrayName = "booleanArrayAttr"; + final boolean[] booleanArrayValue = {true, false}; + final String byteName = "byteAttr"; + final byte byteValue = 1; + final String byteArrayName = "byteArrayAttr"; + final byte[] byteArrayValue = {2, 3}; + final String charName = "charAttr"; + final char charValue = 'a'; + final String charArrayName = "charArrayAttr"; + final char[] charArrayValue = {'b', 'c'}; + final String doubleName = "doubleAttr"; + final double doubleValue = 0.1d; + final String doubleArrayName = "doubleArrayAttr"; + final double[] doubleArrayValue = {0.2d, 0.3d}; + final String floatName = "floatAttr"; + final float floatValue = 0.5f; + final String floatArrayName = "floatArrayAttr"; + final float[] floatArrayValue = {0.6f, 0.7f}; + final String intName = "intAttr"; + final int intValue = 100; + final String intArrayName = "intArrayAttr"; + final int[] intArrayValue = {110, 120}; + final String longName = "longAttr"; + final long longValue = 1000L; + final String longArrayName = "longArrayAttr"; + final long[] longArrayValue = {1001L, 1002L}; + final String objectName = "objectAttr"; + final Object objectValue = new BigDecimal("123.45"); + final String objectArrayName = "objectArrayAttr"; + final Object[] objectArrayValue = {new BigDecimal("56.7"), new Date()}; + final String shortName = "shortAttr"; + final short shortValue = 10; + final String shortArrayName = "shortArrayAttr"; + final short[] shortArrayValue = {11, 12}; + final String passwordName = "password"; + final String passwordValue = "qwerty"; + final String nullPasswordName = "nullPassword"; + final String nullPasswordValue = null; + final String nullName = null; + final String nullValue = null; + final String nullArrayName = "nullArray"; + final Object[] nullArrayValue = null; + + String expected = ToStringBuilder.ATTRIBUTES_LIST_PREFIX + + createFirstAttributeOutput(booleanName, String.valueOf(booleanValue)) + + createAttributeOutput(booleanArrayName, Arrays.toString(booleanArrayValue)) + + createAttributeOutput(byteName, String.valueOf(byteValue)) + + createAttributeOutput(byteArrayName, Arrays.toString(byteArrayValue)) + + createAttributeOutput(charName, String.valueOf(charValue)) + + createAttributeOutput(charArrayName, Arrays.toString(charArrayValue)) + + createAttributeOutput(doubleName, String.valueOf(doubleValue)) + + createAttributeOutput(doubleArrayName, Arrays.toString(doubleArrayValue)) + + createAttributeOutput(floatName, String.valueOf(floatValue)) + + createAttributeOutput(floatArrayName, Arrays.toString(floatArrayValue)) + + createAttributeOutput(intName, String.valueOf(intValue)) + + createAttributeOutput(intArrayName, Arrays.toString(intArrayValue)) + + createAttributeOutput(longName, String.valueOf(longValue)) + + createAttributeOutput(longArrayName, Arrays.toString(longArrayValue)) + + createAttributeOutput(objectName, String.valueOf(objectValue)) + + createAttributeOutput(objectArrayName, Arrays.toString(objectArrayValue)) + + createAttributeOutput(shortName, String.valueOf(shortValue)) + + createAttributeOutput(shortArrayName, Arrays.toString(shortArrayValue)) + + createAttributeOutput(nullName, String.valueOf(nullValue)) + + createAttributeOutput(nullArrayName, Arrays.toString(nullArrayValue)) + + createAttributeOutput(passwordName, ToStringBuilder.FILTERED_CONTENT) + + createAttributeOutput(nullPasswordName, null) + + ToStringBuilder.ATTRIBUTES_LIST_SUFFIX; + + System.out.println("ToString: " + expected); + assertEquals( + expected, + ToStringBuilder.forInstance(null) + .append(booleanName, booleanValue) + .append(booleanArrayName, booleanArrayValue) + .append(byteName, byteValue) + .append(byteArrayName, byteArrayValue) + .append(charName, charValue) + .append(charArrayName, charArrayValue) + .append(doubleName, doubleValue) + .append(doubleArrayName, doubleArrayValue) + .append(floatName, floatValue) + .append(floatArrayName, floatArrayValue) + .append(intName, intValue) + .append(intArrayName, intArrayValue) + .append(longName, longValue) + .append(longArrayName, longArrayValue) + .append(objectName, objectValue) + .append(objectArrayName, objectArrayValue) + .append(shortName, shortValue) + .append(shortArrayName, shortArrayValue) + .append(nullName, nullValue) + .append(nullArrayName, nullArrayValue) + .appendFiltered(passwordName, passwordValue) + .appendFiltered(nullPasswordName, nullPasswordValue) + .build()); + } + + private String createAttributeOutput(String name, String value) { + return ToStringBuilder.ATTRIBUTES_SEPARATOR + + createFirstAttributeOutput(name, value); + } + + private String createFirstAttributeOutput(String name, String value) { + return name + + ToStringBuilder.NAME_VALUE_SEPARATOR + + value + + ToStringBuilder.VALUE_SUFFIX; + } +} diff --git a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml index 26dfb12..214e662d 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml +++ b/frontend/webadmin/modules/gwt-common/src/main/resources/org/ovirt/engine/core/Common.gwt.xml @@ -258,6 +258,7 @@ <include name="common/utils/SizeConverter.java"/> <include name="common/utils/CommonConstants.java"/> <include name="common/businessentities/Entities.java"/> + <include name="common/utils/ToStringBuilder.java"/> <!-- Required by frontend --> <include name="common/interfaces/SearchType.java" /> -- To view, visit https://gerrit.ovirt.org/39240 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3d4baa2430a45b0281b7891eb19ad2094c1b3408 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Martin Peřina <mper...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches