Modified toString() such that the no-box-arguments versions do not
automatically traverse collections, but instead simply call toString on them. The versions that take box arguments (where the developer is clearly expressing a desire for custom formatted collections) still do the traversal. Moved the warning that Enumeration and Iterator are consumed into said methods. Switched LogBuilder to use StringUtil.toString, since it now subsumes the behavior of ArrayUtil.toString without the undesirable collection munging that motivated its original creation. Nixed ArrayUtil.toString/safeToString because they haven't been in the wild long enough to be likely to have been discovered and used by third parties.
This commit is contained in:
@@ -892,51 +892,6 @@ public class ArrayUtil
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the String representation of the specified Object, which may or may not be an array.
|
||||
*/
|
||||
public static String safeToString (Object o)
|
||||
{
|
||||
return ((o == null) || !o.getClass().isArray()) ? String.valueOf(o) : toString(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the String representation of the specified Object, which <em>must</em> be an array.
|
||||
*
|
||||
* @throws IllegalArgumentException if array is not actually an array.
|
||||
*/
|
||||
public static String toString (Object array)
|
||||
{
|
||||
if (array instanceof Object[]) {
|
||||
return Arrays.deepToString((Object[])array); // go deep, baby
|
||||
|
||||
} else if (array instanceof int[]) {
|
||||
return Arrays.toString((int[])array);
|
||||
|
||||
} else if (array instanceof byte[]) {
|
||||
return Arrays.toString((byte[])array);
|
||||
|
||||
} else if (array instanceof char[]) {
|
||||
return Arrays.toString((char[])array);
|
||||
|
||||
} else if (array instanceof short[]) {
|
||||
return Arrays.toString((short[])array);
|
||||
|
||||
} else if (array instanceof long[]) {
|
||||
return Arrays.toString((long[])array);
|
||||
|
||||
} else if (array instanceof float[]) {
|
||||
return Arrays.toString((float[])array);
|
||||
|
||||
} else if (array instanceof double[]) {
|
||||
return Arrays.toString((double[])array);
|
||||
|
||||
} else if (array instanceof boolean[]) {
|
||||
return Arrays.toString((boolean[])array);
|
||||
}
|
||||
throw new IllegalArgumentException("Not an array: " + array);
|
||||
}
|
||||
|
||||
/** The default random object used when shuffling an array. */
|
||||
protected static final Random _rnd = new Random();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class LogBuilder
|
||||
}
|
||||
_log.append(args[ii]).append('=');
|
||||
try {
|
||||
_log.append(ArrayUtil.safeToString(args[ii + 1]));
|
||||
_log.append(StringUtil.toString(args[ii + 1]));
|
||||
} catch (Throwable t) {
|
||||
_log.append("<toString() failure: ").append(t).append('>');
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public abstract class Logger
|
||||
}
|
||||
buf.append(args[ii]).append('=');
|
||||
try {
|
||||
buf.append(ArrayUtil.safeToString(args[ii + 1]));
|
||||
buf.append(StringUtil.toString(args[ii + 1]));
|
||||
} catch (Throwable t) {
|
||||
buf.append("<toString() failure: ").append(t).append(">");
|
||||
}
|
||||
|
||||
@@ -355,16 +355,8 @@ public class StringUtil
|
||||
* Converts the supplied object to a string. Normally this is accomplished via the object's
|
||||
* built in <code>toString()</code> method, but in the case of arrays, <code>toString()</code>
|
||||
* is called on each element and the contents are listed like so:
|
||||
*
|
||||
* <pre>
|
||||
* (value, value, value)
|
||||
* </pre>
|
||||
*
|
||||
* Arrays of ints, longs, floats and doubles are also handled for convenience.
|
||||
*
|
||||
* <p> Additionally, <code>Enumeration</code> or <code>Iterator</code> objects can be passed
|
||||
* and they will be enumerated and output in a similar manner to arrays. Bear in mind that this
|
||||
* uses up the enumeration or iterator in question.
|
||||
* <pre>(value, value, value)</pre>
|
||||
* Arrays of primitive types are also handled for convenience.
|
||||
*
|
||||
* <p> Also note that passing null will result in the string "null" being returned.
|
||||
*/
|
||||
@@ -375,10 +367,29 @@ public class StringUtil
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the supplied value to a string and appends it to the supplied string buffer. See
|
||||
* {@link #toString()} for more information.
|
||||
*
|
||||
* @param buf the string buffer to which we will append the string.
|
||||
* @param val the value from which to generate the string.
|
||||
*/
|
||||
public static void toString (StringBuilder buf, Object val)
|
||||
{
|
||||
// these boxes+sep will only be used for arrays
|
||||
toString(buf, val, "(", ")", ", ", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like the single argument {@link #toString(Object)} with the additional function of
|
||||
* specifying the characters that are used to box in list and array types. For example, if "["
|
||||
* and "]" were supplied, an int array might be formatted like so: <code>[1, 3, 5]</code>.
|
||||
* specifying the characters that are used to box in collection and array types. For example,
|
||||
* if "[" and "]" were supplied, an int array might be formatted like so: <code>[1, 3,
|
||||
* 5]</code>.
|
||||
*
|
||||
* <p> Note: in this method (unlike {@link #toString()}), <code>Enumeration</code> or
|
||||
* <code>Iterator</code> objects can be passed and they will be enumerated and output in a
|
||||
* similar manner to arrays. Bear in mind that this uses up the enumeration or iterator in
|
||||
* question.
|
||||
*/
|
||||
public static String toString (Object val, String openBox, String closeBox)
|
||||
{
|
||||
@@ -387,23 +398,16 @@ public class StringUtil
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the supplied value to a string and appends it to the supplied string buffer. See
|
||||
* the single argument version for more information.
|
||||
*
|
||||
* @param buf the string buffer to which we will append the string.
|
||||
* @param val the value from which to generate the string.
|
||||
*/
|
||||
public static void toString (StringBuilder buf, Object val)
|
||||
{
|
||||
toString(buf, val, "(", ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the supplied value to a string and appends it to the supplied string buffer. The
|
||||
* specified boxing characters are used to enclose list and array types. For example, if "["
|
||||
* and "]" were supplied, an int array might be formatted like so: <code>[1, 3, 5]</code>.
|
||||
*
|
||||
* <p> Note: in this method (unlike {@link #toString()}), <code>Enumeration</code> or
|
||||
* <code>Iterator</code> objects can be passed and they will be enumerated and output in a
|
||||
* similar manner to arrays. Bear in mind that this uses up the enumeration or iterator in
|
||||
* question.
|
||||
*
|
||||
* @param buf the string buffer to which we will append the string.
|
||||
* @param val the value from which to generate the string.
|
||||
* @param openBox the opening box character.
|
||||
@@ -419,150 +423,21 @@ public class StringUtil
|
||||
* specified boxing characters are used to enclose list and array types. For example, if "["
|
||||
* and "]" were supplied, an int array might be formatted like so: <code>[1, 3, 5]</code>.
|
||||
*
|
||||
* <p> Note: in this method (unlike {@link #toString()}), <code>Enumeration</code> or
|
||||
* <code>Iterator</code> objects can be passed and they will be enumerated and output in a
|
||||
* similar manner to arrays. Bear in mind that this uses up the enumeration or iterator in
|
||||
* question.
|
||||
*
|
||||
* @param buf the string buffer to which we will append the string.
|
||||
* @param val the value from which to generate the string.
|
||||
* @param openBox the opening box character.
|
||||
* @param closeBox the closing box character.
|
||||
* @param sep the separator string.
|
||||
*/
|
||||
public static void toString (
|
||||
StringBuilder buf, Object val, String openBox, String closeBox, String sep)
|
||||
public static void toString (StringBuilder buf, Object val, String openBox, String closeBox,
|
||||
String sep)
|
||||
{
|
||||
if (val instanceof byte[]) {
|
||||
buf.append(openBox);
|
||||
byte[] v = (byte[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof short[]) {
|
||||
buf.append(openBox);
|
||||
short[] v = (short[])val;
|
||||
for (short i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof int[]) {
|
||||
buf.append(openBox);
|
||||
int[] v = (int[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof long[]) {
|
||||
buf.append(openBox);
|
||||
long[] v = (long[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof float[]) {
|
||||
buf.append(openBox);
|
||||
float[] v = (float[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof double[]) {
|
||||
buf.append(openBox);
|
||||
double[] v = (double[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Object[]) {
|
||||
buf.append(openBox);
|
||||
Object[] v = (Object[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, v[i], openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof boolean[]) {
|
||||
buf.append(openBox);
|
||||
boolean[] v = (boolean[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i] ? "t" : "f");
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Iterable<?>) {
|
||||
toString(buf, ((Iterable<?>)val).iterator(), openBox, closeBox);
|
||||
|
||||
} else if (val instanceof Iterator<?>) {
|
||||
buf.append(openBox);
|
||||
Iterator<?> iter = (Iterator<?>)val;
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, iter.next(), openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Enumeration<?>) {
|
||||
buf.append(openBox);
|
||||
Enumeration<?> enm = (Enumeration<?>)val;
|
||||
for (int i = 0; enm.hasMoreElements(); i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, enm.nextElement(), openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Point2D) {
|
||||
Point2D p = (Point2D)val;
|
||||
buf.append(openBox);
|
||||
coordsToString(buf, (int)p.getX(), (int)p.getY());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Dimension2D) {
|
||||
Dimension2D d = (Dimension2D)val;
|
||||
buf.append(openBox);
|
||||
buf.append(d.getWidth()).append("x").append(d.getHeight());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Rectangle2D) {
|
||||
Rectangle2D r = (Rectangle2D)val;
|
||||
buf.append(openBox);
|
||||
buf.append(r.getWidth()).append("x").append(r.getHeight());
|
||||
coordsToString(buf, (int)r.getX(), (int)r.getY());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else {
|
||||
buf.append(val);
|
||||
}
|
||||
toString(buf, val, openBox, closeBox, sep, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1378,6 +1253,154 @@ public class StringUtil
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for the various {@link #toString} methods.
|
||||
*/
|
||||
protected static void toString (StringBuilder buf, Object val, String openBox, String closeBox,
|
||||
String sep, boolean traverseCollections)
|
||||
{
|
||||
if (val instanceof byte[]) {
|
||||
buf.append(openBox);
|
||||
byte[] v = (byte[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof short[]) {
|
||||
buf.append(openBox);
|
||||
short[] v = (short[])val;
|
||||
for (short i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof int[]) {
|
||||
buf.append(openBox);
|
||||
int[] v = (int[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof long[]) {
|
||||
buf.append(openBox);
|
||||
long[] v = (long[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof float[]) {
|
||||
buf.append(openBox);
|
||||
float[] v = (float[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof double[]) {
|
||||
buf.append(openBox);
|
||||
double[] v = (double[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i]);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Object[]) {
|
||||
buf.append(openBox);
|
||||
Object[] v = (Object[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, v[i], openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof boolean[]) {
|
||||
buf.append(openBox);
|
||||
boolean[] v = (boolean[])val;
|
||||
for (int i = 0; i < v.length; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
buf.append(v[i] ? "t" : "f");
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Point2D) {
|
||||
Point2D p = (Point2D)val;
|
||||
buf.append(openBox);
|
||||
coordsToString(buf, (int)p.getX(), (int)p.getY());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Dimension2D) {
|
||||
Dimension2D d = (Dimension2D)val;
|
||||
buf.append(openBox);
|
||||
buf.append(d.getWidth()).append("x").append(d.getHeight());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Rectangle2D) {
|
||||
Rectangle2D r = (Rectangle2D)val;
|
||||
buf.append(openBox);
|
||||
buf.append(r.getWidth()).append("x").append(r.getHeight());
|
||||
coordsToString(buf, (int)r.getX(), (int)r.getY());
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (traverseCollections) {
|
||||
if (val instanceof Iterable<?>) {
|
||||
toString(buf, ((Iterable<?>)val).iterator(), openBox, closeBox, sep, true);
|
||||
|
||||
} else if (val instanceof Iterator<?>) {
|
||||
buf.append(openBox);
|
||||
Iterator<?> iter = (Iterator<?>)val;
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, iter.next(), openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else if (val instanceof Enumeration<?>) {
|
||||
buf.append(openBox);
|
||||
Enumeration<?> enm = (Enumeration<?>)val;
|
||||
for (int i = 0; enm.hasMoreElements(); i++) {
|
||||
if (i > 0) {
|
||||
buf.append(sep);
|
||||
}
|
||||
toString(buf, enm.nextElement(), openBox, closeBox);
|
||||
}
|
||||
buf.append(closeBox);
|
||||
|
||||
} else {
|
||||
buf.append(val);
|
||||
}
|
||||
|
||||
} else {
|
||||
buf.append(val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for the various <code>join</code> methods.
|
||||
*/
|
||||
|
||||
@@ -56,12 +56,12 @@ public class ConfigTest
|
||||
slist.add(iter.nextElement().toString());
|
||||
}
|
||||
Collections.sort(slist);
|
||||
assertEquals("(sub1, sub2, sub3)", StringUtil.toString(slist));
|
||||
assertEquals("[sub1, sub2, sub3]", StringUtil.toString(slist));
|
||||
|
||||
// check the whole shebang
|
||||
List<String> list = CollectionUtil.addAll(new ArrayList<String>(), pconfig.keys());
|
||||
Collections.sort(list);
|
||||
assertEquals("(prop1, prop2, prop3, prop4, sub.sub1, sub.sub2, sub.sub3)",
|
||||
assertEquals("[prop1, prop2, prop3, prop4, sub.sub1, sub.sub2, sub.sub3]",
|
||||
StringUtil.toString(list));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,6 @@ public class HashIntMapTest
|
||||
assertTrue(valuestr + ".equals(" + exvals + ")", valuestr.equals(exvals));
|
||||
}
|
||||
|
||||
protected static final String TEST1 = "(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)";
|
||||
protected static final String TEST2 = "(10, 11)";
|
||||
protected static final String TEST1 = "[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]";
|
||||
protected static final String TEST2 = "[10, 11]";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user