001    /*
002     $Id: NodePrinter.java,v 1.3 2004/05/17 07:53:29 jstrachan Exp $
003    
004     Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005    
006     Redistribution and use of this software and associated documentation
007     ("Software"), with or without modification, are permitted provided
008     that the following conditions are met:
009    
010     1. Redistributions of source code must retain copyright
011        statements and notices.  Redistributions must also contain a
012        copy of this document.
013    
014     2. Redistributions in binary form must reproduce the
015        above copyright notice, this list of conditions and the
016        following disclaimer in the documentation and/or other
017        materials provided with the distribution.
018    
019     3. The name "groovy" must not be used to endorse or promote
020        products derived from this Software without prior written
021        permission of The Codehaus.  For written permission,
022        please contact info@codehaus.org.
023    
024     4. Products derived from this Software may not be called "groovy"
025        nor may "groovy" appear in their names without prior written
026        permission of The Codehaus. "groovy" is a registered
027        trademark of The Codehaus.
028    
029     5. Due credit should be given to The Codehaus -
030        http://groovy.codehaus.org/
031    
032     THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033     ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034     NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035     FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
036     THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043     OF THE POSSIBILITY OF SUCH DAMAGE.
044    
045     */
046    package groovy.util;
047    
048    
049    import org.codehaus.groovy.runtime.InvokerHelper;
050    
051    import java.io.OutputStreamWriter;
052    import java.io.PrintWriter;
053    import java.util.Iterator;
054    import java.util.List;
055    import java.util.Map;
056    
057    /**
058     * A helper class for creating nested trees of data
059     * 
060     * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
061     * @version $Revision: 1.3 $
062     */
063    public class NodePrinter {
064    
065        private IndentPrinter out;
066    
067        public NodePrinter() {
068            this(new IndentPrinter(new PrintWriter(new OutputStreamWriter(System.out))));
069        }
070    
071        public NodePrinter(PrintWriter out) {
072            this(new IndentPrinter(out));
073        }
074    
075        public NodePrinter(IndentPrinter out) {
076            this.out = out;
077        }
078    
079        public void print(Node node) {
080            out.printIndent();
081            printName(node);
082            Map attributes = node.attributes();
083            boolean hasAttributes = attributes != null && !attributes.isEmpty();
084            if (hasAttributes) {
085                printAttributes(attributes);
086            }
087            Object value = node.value();
088            if (value instanceof List) {
089                if (!hasAttributes) {
090                    out.print("()");
091                }
092                printList((List) value);
093            }
094            else {
095                if (value instanceof String) {
096                    out.print("('");
097                    out.print((String) value);
098                    out.println("')");
099                }
100                else {
101                    out.println("()");
102                }
103            }
104            out.flush();
105        }
106    
107        protected void printName(Node node) {
108            Object name = node.name();
109            if (name != null) {
110                out.print(name.toString());
111            }
112            else {
113                out.print("null");
114            }
115        }
116    
117        protected void printList(List list) {
118            if (list.isEmpty()) {
119                out.println("");
120            }
121            else {
122                out.println(" {");
123                out.incrementIndent();
124                for (Iterator iter = list.iterator(); iter.hasNext();) {
125                    Object value = iter.next();
126                    if (value instanceof Node) {
127                        print((Node) value);
128                    }
129                    else {
130                        out.printIndent();
131                        out.print("builder.append(");
132                        out.print(InvokerHelper.toString(value));
133                        out.println(")");
134                    }
135                }
136                out.decrementIndent();
137                out.printIndent();
138                out.println("}");
139            }
140        }
141    
142    
143        protected void printAttributes(Map attributes) {
144            out.print("(");
145            boolean first = true;
146            for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
147                Map.Entry entry = (Map.Entry) iter.next();
148                if (first) {
149                    first = false;
150                }
151                else {
152                    out.print(", ");
153                }
154                out.print(entry.getKey().toString());
155                out.print(":");
156                if (entry.getValue() instanceof String) {
157                    out.print("'" + entry.getValue() + "'");
158                }
159                else {
160                    out.print(InvokerHelper.toString(entry.getValue()));
161                }
162            }
163            out.print(")");
164        }
165    
166    }