View Javadoc

1   /*
2    $Id: XmlNodePrinter.java,v 1.1 2005/07/13 18:54:45 cstein Exp $
3   
4    Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5   
6    Redistribution and use of this software and associated documentation
7    ("Software"), with or without modification, are permitted provided
8    that the following conditions are met:
9   
10   1. Redistributions of source code must retain copyright
11   statements and notices.  Redistributions must also contain a
12   copy of this document.
13  
14   2. Redistributions in binary form must reproduce the
15   above copyright notice, this list of conditions and the
16   following disclaimer in the documentation and/or other
17   materials provided with the distribution.
18  
19   3. The name "groovy" must not be used to endorse or promote
20   products derived from this Software without prior written
21   permission of The Codehaus.  For written permission,
22   please contact info@codehaus.org.
23  
24   4. Products derived from this Software may not be called "groovy"
25   nor may "groovy" appear in their names without prior written
26   permission of The Codehaus. "groovy" is a registered
27   trademark of The Codehaus.
28  
29   5. Due credit should be given to The Codehaus -
30   http://groovy.codehaus.org/
31  
32   THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
33   ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
34   NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
35   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
36   THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
37   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
43   OF THE POSSIBILITY OF SUCH DAMAGE.
44  
45   */
46  
47  package groovy.util;
48  
49  import groovy.xml.QName;
50  
51  import java.io.OutputStreamWriter;
52  import java.io.PrintWriter;
53  import java.util.Iterator;
54  import java.util.List;
55  import java.util.Map;
56  
57  import org.codehaus.groovy.runtime.InvokerHelper;
58  
59  /***
60   * Prints a node with all childs in XML format.
61   * 
62   * @see groovy.util.NodePrinter
63   * @author Christian Stein
64   */
65  public class XmlNodePrinter {
66  
67      protected final IndentPrinter out;
68      private final String quote;
69  
70      public XmlNodePrinter() {
71          this(new PrintWriter(new OutputStreamWriter(System.out)));
72      }
73  
74      public XmlNodePrinter(PrintWriter out) {
75          this(out, "  ");
76      }
77  
78      public XmlNodePrinter(PrintWriter out, String indent) {
79          this(out, indent, "\"");
80      }
81  
82      public XmlNodePrinter(PrintWriter out, String indent, String quote) {
83          this(new IndentPrinter(out, indent), quote);
84      }
85  
86      public XmlNodePrinter(IndentPrinter out, String quote) {
87          if (out == null) {
88              throw new IllegalArgumentException("Argument 'IndentPrinter out' must not be null!");
89          }
90          this.out = out;
91          this.quote = quote;
92      }
93  
94      public String getNameOfNode(Node node) {
95          if (node == null) {
96              throw new IllegalArgumentException("Node must not be null!");
97          }
98          Object name = node.name();
99          if (name instanceof QName) {
100             QName qname = (QName) name;
101             return /* qname.getPrefix() + ":" + */qname.getLocalPart();
102         }
103         return name.toString();
104     }
105 
106     public boolean isEmptyElement(Node node) {
107         if (node == null) {
108             throw new IllegalArgumentException("Node must not be null!");
109         }
110         if (!node.children().isEmpty()) {
111             return false;
112         }
113         String text = node.text();
114         if (text.length() > 0) {
115             return false;
116         }
117         return true;
118     }
119 
120     public void print(Node node) {
121         /*
122          * Handle empty elements like '<br/>', '<img/> or '<hr noshade="noshade"/>.
123          */
124         if (isEmptyElement(node)) {
125             // System.err.println("empty-dead");
126             printLineBegin();
127             out.print("<");
128             out.print(getNameOfNode(node));
129             printNameAttributes(node.attributes());
130             out.print("/>");
131             printLineEnd(); // "node named '" + node.name() + "'"
132             out.flush();
133             return;
134         }
135 
136         /*
137          * Handle GSP tag element!
138          */
139         if (printSpecialNode(node)) {
140             // System.err.println("special-dead");
141             out.flush();
142             return;
143         }
144 
145         /*
146          * Handle normal element like <html> ... </html>.
147          */
148         Object value = node.value();
149         if (value instanceof List) {
150             printName(node, true);
151             printList((List) value);
152             printName(node, false);
153             out.flush();
154             return;
155         }
156 
157         /*
158          * Still here?!
159          */
160         throw new RuntimeException("Unsupported node value: " + node.value());
161     }
162 
163     protected void printLineBegin() {
164         out.printIndent();
165     }
166 
167     protected void printLineEnd() {
168         printLineEnd(null);
169     }
170 
171     protected void printLineEnd(String comment) {
172         if (comment != null) {
173             out.print(" <!-- ");
174             out.print(comment);
175             out.print(" -->");
176         }
177         out.print("\n");
178     }
179 
180     protected void printList(List list) {
181         out.incrementIndent();
182         for (Iterator iter = list.iterator(); iter.hasNext();) {
183             Object value = iter.next();
184             /*
185              * If the current value is a node, recurse into that node.
186              */
187             if (value instanceof Node) {
188                 print((Node) value);
189                 continue;
190             }
191             /*
192              * Print out "simple" text nodes.
193              */
194             printLineBegin();
195             out.print(InvokerHelper.toString(value));
196             printLineEnd();
197         }
198         out.decrementIndent();
199     }
200 
201     protected void printName(Node node, boolean begin) {
202         if (node == null) {
203             throw new NullPointerException("Node must not be null.");
204         }
205         Object name = node.name();
206         if (name == null) {
207             throw new NullPointerException("Name must not be null.");
208         }
209         printLineBegin();
210         out.print("<");
211         if (!begin) {
212             out.print("/");
213         }
214         out.print(getNameOfNode(node));
215         if (begin) {
216             printNameAttributes(node.attributes());
217         }
218         out.print(">");
219         printLineEnd();
220     }
221 
222     protected void printNameAttributes(Map attributes) {
223         if (attributes == null || attributes.isEmpty()) {
224             return;
225         }
226         out.print(" ");
227         boolean first = true;
228         for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
229             Map.Entry entry = (Map.Entry) iter.next();
230             if (first) {
231                 first = false;
232             } else {
233                 out.print(" ");
234             }
235             out.print(entry.getKey().toString());
236             out.print("=");
237             Object value = entry.getValue();
238             if (value instanceof String) {
239                 out.print(quote);
240                 out.print((String) value);
241                 out.print(quote);
242                 continue;
243             }
244             out.print(InvokerHelper.toString(value));
245         }
246     }
247 
248     protected boolean printSpecialNode(Node node) {
249         return false;
250     }
251 
252 }