From 881ee30047a95a78af25f435eadd787bd573ddd9 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Wed, 1 Jun 2011 11:40:26 -0700 Subject: [PATCH] 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. --- .../java/com/samskivert/util/ArrayUtil.java | 45 --- .../java/com/samskivert/util/LogBuilder.java | 2 +- src/main/java/com/samskivert/util/Logger.java | 2 +- .../java/com/samskivert/util/StringUtil.java | 345 ++++++++++-------- .../java/com/samskivert/util/ConfigTest.java | 4 +- .../com/samskivert/util/HashIntMapTest.java | 4 +- 6 files changed, 190 insertions(+), 212 deletions(-) diff --git a/src/main/java/com/samskivert/util/ArrayUtil.java b/src/main/java/com/samskivert/util/ArrayUtil.java index 4b9fa08f..7db9d5d7 100644 --- a/src/main/java/com/samskivert/util/ArrayUtil.java +++ b/src/main/java/com/samskivert/util/ArrayUtil.java @@ -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 must 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(); } diff --git a/src/main/java/com/samskivert/util/LogBuilder.java b/src/main/java/com/samskivert/util/LogBuilder.java index 1be1eced..be73c726 100644 --- a/src/main/java/com/samskivert/util/LogBuilder.java +++ b/src/main/java/com/samskivert/util/LogBuilder.java @@ -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("'); } diff --git a/src/main/java/com/samskivert/util/Logger.java b/src/main/java/com/samskivert/util/Logger.java index 9eab8de7..800c6f5c 100644 --- a/src/main/java/com/samskivert/util/Logger.java +++ b/src/main/java/com/samskivert/util/Logger.java @@ -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(""); } diff --git a/src/main/java/com/samskivert/util/StringUtil.java b/src/main/java/com/samskivert/util/StringUtil.java index 68349bc2..6ce021a4 100644 --- a/src/main/java/com/samskivert/util/StringUtil.java +++ b/src/main/java/com/samskivert/util/StringUtil.java @@ -355,16 +355,8 @@ public class StringUtil * Converts the supplied object to a string. Normally this is accomplished via the object's * built in toString() method, but in the case of arrays, toString() * is called on each element and the contents are listed like so: - * - *
-     * (value, value, value)
-     * 
- * - * Arrays of ints, longs, floats and doubles are also handled for convenience. - * - *

Additionally, Enumeration or Iterator 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. + *

(value, value, value)
+ * Arrays of primitive types are also handled for convenience. * *

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: [1, 3, 5]. + * 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: [1, 3, + * 5]. + * + *

Note: in this method (unlike {@link #toString()}), Enumeration or + * Iterator 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: [1, 3, 5]. * + *

Note: in this method (unlike {@link #toString()}), Enumeration or + * Iterator 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: [1, 3, 5]. * + *

Note: in this method (unlike {@link #toString()}), Enumeration or + * Iterator 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 join methods. */ diff --git a/src/test/java/com/samskivert/util/ConfigTest.java b/src/test/java/com/samskivert/util/ConfigTest.java index 678b08f6..95ecbbff 100644 --- a/src/test/java/com/samskivert/util/ConfigTest.java +++ b/src/test/java/com/samskivert/util/ConfigTest.java @@ -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 list = CollectionUtil.addAll(new ArrayList(), 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)); } } diff --git a/src/test/java/com/samskivert/util/HashIntMapTest.java b/src/test/java/com/samskivert/util/HashIntMapTest.java index aad02d9d..85a73e56 100644 --- a/src/test/java/com/samskivert/util/HashIntMapTest.java +++ b/src/test/java/com/samskivert/util/HashIntMapTest.java @@ -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]"; }