From 084754f692073f308b2a317e333607b3182ba58e Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Sun, 24 Aug 2003 09:47:19 +0000 Subject: [PATCH] Improve debugPrint() and verbosePrint() bug 20740, from Arun Mammen Thomas git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/trunk@131113 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/commons/collections/MapUtils.java | 114 +++++++----- .../commons/collections/TestMapUtils.java | 168 +++++++++++++++++- 2 files changed, 239 insertions(+), 43 deletions(-) diff --git a/src/java/org/apache/commons/collections/MapUtils.java b/src/java/org/apache/commons/collections/MapUtils.java index 576bbc883..0e4d6aff9 100644 --- a/src/java/org/apache/commons/collections/MapUtils.java +++ b/src/java/org/apache/commons/collections/MapUtils.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/MapUtils.java,v 1.26 2003/08/20 21:03:16 scolebourne Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/java/org/apache/commons/collections/MapUtils.java,v 1.27 2003/08/24 09:47:19 scolebourne Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -105,7 +105,7 @@ import org.apache.commons.collections.decorators.TypedSortedMap; * * * @since Commons Collections 1.0 - * @version $Revision: 1.26 $ $Date: 2003/08/20 21:03:16 $ + * @version $Revision: 1.27 $ $Date: 2003/08/24 09:47:19 $ * * @author James Strachan * @author Nissim Karpenstein @@ -116,6 +116,7 @@ import org.apache.commons.collections.decorators.TypedSortedMap; * @author Arun Mammen Thomas * @author Janek Bogucki * @author Max Rydahl Andersen + * @author Arun Mammen Thomas */ public class MapUtils { @@ -130,7 +131,9 @@ public class MapUtils { */ public static final SortedMap EMPTY_SORTED_MAP = Collections.unmodifiableSortedMap(new TreeMap()); - private static int debugIndent = 0; + private static int indentDepth = 0; // must be synchronized + + private static final String INDENT_STRING = " "; /** * MapUtils should not normally be instantiated. @@ -677,36 +680,48 @@ public class MapUtils { //------------------------------------------------------------------------- /** - * Prints the given map with nice line breaks. + * Prints the given map with nice line breaks. + *

+ * This method prints a nicely formatted String decribing the Map. + * Each map entry will be printed with key and value. + * When the value is a Map, recursive behaviour occurs. * - * @param out the stream to print to - * @param label the label to be applied to the output generated. This - * may well be the key associated with this map within a - * surrounding map in which this is nested. - * @param map the map to print + * @param out the stream to print to, must not be null + * @param label the label to be applied to the output generated. This + * may well be the key associated with this map within a + * surrounding map in which this is nested. + * @param map the map to print, may be null + * @throws NullPointerException if the stream is null */ public static synchronized void verbosePrint( final PrintStream out, final Object label, final Map map) { + indentDepth = 0; verbosePrintInternal(out, label, map, false); } /** - * Prints the given map with nice line breaks. + * Prints the given map with nice line breaks. + *

+ * This method prints a nicely formatted String decribing the Map. + * Each map entry will be printed with key, value and value classname. + * When the value is a Map, recursive behaviour occurs. * - * @param out the stream to print to - * @param label the label to be applied to the output generated. This - * may well be the key associated with this map within a - * surrounding map in which this is nested. - * @param map the map to print + * @param out the stream to print to, must not be null + * @param label the label to be applied to the output generated. This + * may well be the key associated with this map within a + * surrounding map in which this is nested. + * @param map the map to print, may be null + * @throws NullPointerException if the stream is null */ public static synchronized void debugPrint( final PrintStream out, final Object label, final Map map) { + indentDepth = 0; verbosePrintInternal(out, label, map, true); } @@ -718,9 +733,9 @@ public class MapUtils { * * @param out the stream to indent */ - protected static void debugPrintIndent(PrintStream out) { - for (int i = 0; i < debugIndent; i++) { - out.print(" "); + protected static void printIndent(PrintStream out) { + for (int i = 0; i < indentDepth; i++) { + out.print(INDENT_STRING); } } @@ -737,53 +752,70 @@ public class MapUtils { * Implementation providing functionality for {@link #debugPrint} and for * {@link #verbosePrint}. This prints the given map with nice line breaks. * If the debug flag is true, it additionally prints the type of the object - * value. . + * value. * * @param out the stream to print to * @param label the label to be applied to the output generated. This - * may well be the key associated with this map within a - * surrounding map in which this is nested. - * @param map the map to print + * may well be the key associated with this map within a + * surrounding map in which this is nested. + * @param map the map to print, may be null * @param debug flag indicating whether type names should be output. */ - private static void verbosePrintInternal( + private static void verbosePrintInternal( // externally synchronized final PrintStream out, final Object label, final Map map, final boolean debug) { - debugPrintIndent(out); - out.println(label + " = "); + printIndent(out); - debugPrintIndent(out); + if (label != null) { + if (map == null) { + // Guard against null map. + out.println(label + " = null"); + return; + } else { + out.println(label + " = "); + } + } + if (map == null) { + return; + } + + printIndent(out); out.println("{"); - ++debugIndent; + indentDepth++; - for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); + for (Iterator it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry entry = (Map.Entry) it.next(); Object childKey = entry.getKey(); Object childValue = entry.getValue(); if (childValue instanceof Map) { - verbosePrintInternal(out, childKey, (Map) childValue, false); + if (childValue == map) { + printIndent(out); + out.println(childKey + " = this Map"); // should have stack really... + } else { + verbosePrintInternal(out, childKey, (Map) childValue, debug); + } } else { - debugPrintIndent(out); - - if (debug) { - String typeName = - (childValue != null) - ? childValue.getClass().getName() - : null; + printIndent(out); + if (debug && childValue != null) { out.println( - childKey + " = " + childValue + " class: " + typeName); + childKey + + " = " + + childValue + + " " + + childValue.getClass().getName() + ); } else { out.println(childKey + " = " + childValue); } } } - --debugIndent; - debugPrintIndent(out); - out.println("}"); + indentDepth--; + printIndent(out); + out.println(debug ? "} " + map.getClass().getName() : "}"); } // Misc diff --git a/src/test/org/apache/commons/collections/TestMapUtils.java b/src/test/org/apache/commons/collections/TestMapUtils.java index aa632f41d..fcfcf96d5 100644 --- a/src/test/org/apache/commons/collections/TestMapUtils.java +++ b/src/test/org/apache/commons/collections/TestMapUtils.java @@ -1,5 +1,5 @@ /* - * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestMapUtils.java,v 1.6 2003/08/20 21:03:16 scolebourne Exp $ + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//collections/src/test/org/apache/commons/collections/TestMapUtils.java,v 1.7 2003/08/24 09:47:19 scolebourne Exp $ * ==================================================================== * * The Apache Software License, Version 1.1 @@ -66,13 +66,14 @@ import java.util.ListResourceBundle; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; +import java.util.TreeMap; import junit.framework.Test; /** * Tests for MapUtils. * - * @version $Revision: 1.6 $ $Date: 2003/08/20 21:03:16 $ + * @version $Revision: 1.7 $ $Date: 2003/08/24 09:47:19 $ * * @author Stephen Colebourne * @author Arun Mammen Thomas @@ -332,4 +333,167 @@ public class TestMapUtils extends BulkTest { fail("No Casting should be occurring!"); } } + + public void testDebugAndVerbosePrintNullMap() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + final String LABEL = "Print Map"; + outPrint.println(LABEL + " = " + String.valueOf((Object) null)); + final String EXPECTED_OUT = out.toString(); + + out.reset(); + + MapUtils.debugPrint(outPrint, LABEL, null); + assertEquals(EXPECTED_OUT, out.toString()); + + out.reset(); + + MapUtils.verbosePrint(outPrint, LABEL, null); + assertEquals(EXPECTED_OUT, out.toString()); + } + + public void testVerbosePrintNullLabel() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + final String INDENT = " "; + + final Map map = new TreeMap(); // treeMap guarantees order across JDKs for test + map.put( new Integer(2) , "B" ); + map.put( new Integer(3) , "C" ); + + outPrint.println("{"); + outPrint.println(INDENT + "2 = B"); + outPrint.println(INDENT + "3 = C"); + outPrint.println("}"); + final String EXPECTED_OUT = out.toString(); + out.reset(); + + MapUtils.verbosePrint(outPrint, null, map); + assertEquals(EXPECTED_OUT, out.toString()); + } + + public void testDebugPrintNullLabel() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + final String INDENT = " "; + + final Map map = new TreeMap(); // treeMap guarantees order across JDKs for test + map.put( new Integer(2) , "B" ); + map.put( new Integer(3) , "C" ); + + outPrint.println("{"); + outPrint.println(INDENT + "2 = B " + String.class.getName()); + outPrint.println(INDENT + "3 = C " + String.class.getName()); + outPrint.println("} " + TreeMap.class.getName()); + final String EXPECTED_OUT = out.toString(); + out.reset(); + + MapUtils.debugPrint(outPrint, null, map); + assertEquals(EXPECTED_OUT, out.toString()); + } + + public void testVerbosePrintNullLabelAndMap() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + MapUtils.verbosePrint(outPrint, null, null); + assertEquals("", out.toString()); + } + + public void testDebugPrintNullLabelAndMap() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + MapUtils.debugPrint(outPrint, null, null); + assertEquals("", out.toString()); + } + + public void testVerbosePrintNullStream() { + try { + MapUtils.verbosePrint(null, "Map", new HashMap()); + fail(); + } catch (NullPointerException ex) { + } + } + + public void testDebugPrintNullStream() { + try { + MapUtils.debugPrint(null, "Map", new HashMap()); + fail(); + } catch (NullPointerException ex) { + } + } + + public void testVerbosePrint() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + final String LABEL = "Print Map"; + final String INDENT = " "; + + outPrint.println(LABEL + " = "); + outPrint.println("{"); + outPrint.println(INDENT + "0 = A"); + outPrint.println(INDENT + "1 = "); + outPrint.println(INDENT + "{"); + outPrint.println(INDENT + INDENT + "2 = B"); + outPrint.println(INDENT + INDENT + "3 = C"); + outPrint.println(INDENT + "}"); + outPrint.println(INDENT + "7 = this Map"); + outPrint.println("}"); + + final String EXPECTED_OUT = out.toString(); + + out.reset(); + + final Map inner = new TreeMap(); // treeMap guarantees order across JDKs for test + inner.put( new Integer(2) , "B" ); + inner.put( new Integer(3) , "C" ); + + final Map outer = new TreeMap(); + outer.put( new Integer(1) , inner ); + outer.put( new Integer(0) , "A"); + outer.put( new Integer(7) , outer); + + MapUtils.verbosePrint(outPrint, "Print Map", outer); + assertEquals(EXPECTED_OUT, out.toString()); + } + + public void testDebugPrint() { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final PrintStream outPrint = new PrintStream(out); + + final String LABEL = "Print Map"; + final String INDENT = " "; + + outPrint.println(LABEL + " = "); + outPrint.println("{"); + outPrint.println(INDENT + "0 = A " + String.class.getName()); + outPrint.println(INDENT + "1 = "); + outPrint.println(INDENT + "{"); + outPrint.println(INDENT + INDENT + "2 = B " + String.class.getName()); + outPrint.println(INDENT + INDENT + "3 = C " + String.class.getName()); + outPrint.println(INDENT + "} " + TreeMap.class.getName()); + outPrint.println(INDENT + "7 = this Map"); + outPrint.println("} " + TreeMap.class.getName()); + + final String EXPECTED_OUT = out.toString(); + + out.reset(); + + final Map inner = new TreeMap(); // treeMap guarantees order across JDKs for test + inner.put( new Integer(2) , "B" ); + inner.put( new Integer(3) , "C" ); + + final Map outer = new TreeMap(); + outer.put( new Integer(1) , inner ); + outer.put( new Integer(0) , "A"); + outer.put( new Integer(7) , outer); + + MapUtils.debugPrint(outPrint, "Print Map", outer); + assertEquals(EXPECTED_OUT, out.toString()); + } }