001: /*
002: $Id: XmlNodePrinter.java 2542 2005-07-13 18:54:45Z cstein $
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:
047: package groovy.util;
048:
049: import groovy.xml.QName;
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: import org.codehaus.groovy.runtime.InvokerHelper;
058:
059: /**
060: * Prints a node with all childs in XML format.
061: *
062: * @see groovy.util.NodePrinter
063: * @author Christian Stein
064: */
065: public class XmlNodePrinter {
066:
067: protected final IndentPrinter out;
068: private final String quote;
069:
070: public XmlNodePrinter() {
071: this (new PrintWriter(new OutputStreamWriter(System.out)));
072: }
073:
074: public XmlNodePrinter(PrintWriter out) {
075: this (out, " ");
076: }
077:
078: public XmlNodePrinter(PrintWriter out, String indent) {
079: this (out, indent, "\"");
080: }
081:
082: public XmlNodePrinter(PrintWriter out, String indent, String quote) {
083: this (new IndentPrinter(out, indent), quote);
084: }
085:
086: public XmlNodePrinter(IndentPrinter out, String quote) {
087: if (out == null) {
088: throw new IllegalArgumentException(
089: "Argument 'IndentPrinter out' must not be null!");
090: }
091: this .out = out;
092: this .quote = quote;
093: }
094:
095: public String getNameOfNode(Node node) {
096: if (node == null) {
097: throw new IllegalArgumentException("Node must not be null!");
098: }
099: Object name = node.name();
100: if (name instanceof QName) {
101: QName qname = (QName) name;
102: return /* qname.getPrefix() + ":" + */qname.getLocalPart();
103: }
104: return name.toString();
105: }
106:
107: public boolean isEmptyElement(Node node) {
108: if (node == null) {
109: throw new IllegalArgumentException("Node must not be null!");
110: }
111: if (!node.children().isEmpty()) {
112: return false;
113: }
114: String text = node.text();
115: if (text.length() > 0) {
116: return false;
117: }
118: return true;
119: }
120:
121: public void print(Node node) {
122: /*
123: * Handle empty elements like '<br/>', '<img/> or '<hr noshade="noshade"/>.
124: */
125: if (isEmptyElement(node)) {
126: // System.err.println("empty-dead");
127: printLineBegin();
128: out.print("<");
129: out.print(getNameOfNode(node));
130: printNameAttributes(node.attributes());
131: out.print("/>");
132: printLineEnd(); // "node named '" + node.name() + "'"
133: out.flush();
134: return;
135: }
136:
137: /*
138: * Handle GSP tag element!
139: */
140: if (printSpecialNode(node)) {
141: // System.err.println("special-dead");
142: out.flush();
143: return;
144: }
145:
146: /*
147: * Handle normal element like <html> ... </html>.
148: */
149: Object value = node.value();
150: if (value instanceof List) {
151: printName(node, true);
152: printList((List) value);
153: printName(node, false);
154: out.flush();
155: return;
156: }
157:
158: /*
159: * Still here?!
160: */
161: throw new RuntimeException("Unsupported node value: "
162: + node.value());
163: }
164:
165: protected void printLineBegin() {
166: out.printIndent();
167: }
168:
169: protected void printLineEnd() {
170: printLineEnd(null);
171: }
172:
173: protected void printLineEnd(String comment) {
174: if (comment != null) {
175: out.print(" <!-- ");
176: out.print(comment);
177: out.print(" -->");
178: }
179: out.print("\n");
180: }
181:
182: protected void printList(List list) {
183: out.incrementIndent();
184: for (Iterator iter = list.iterator(); iter.hasNext();) {
185: Object value = iter.next();
186: /*
187: * If the current value is a node, recurse into that node.
188: */
189: if (value instanceof Node) {
190: print((Node) value);
191: continue;
192: }
193: /*
194: * Print out "simple" text nodes.
195: */
196: printLineBegin();
197: out.print(InvokerHelper.toString(value));
198: printLineEnd();
199: }
200: out.decrementIndent();
201: }
202:
203: protected void printName(Node node, boolean begin) {
204: if (node == null) {
205: throw new NullPointerException("Node must not be null.");
206: }
207: Object name = node.name();
208: if (name == null) {
209: throw new NullPointerException("Name must not be null.");
210: }
211: printLineBegin();
212: out.print("<");
213: if (!begin) {
214: out.print("/");
215: }
216: out.print(getNameOfNode(node));
217: if (begin) {
218: printNameAttributes(node.attributes());
219: }
220: out.print(">");
221: printLineEnd();
222: }
223:
224: protected void printNameAttributes(Map attributes) {
225: if (attributes == null || attributes.isEmpty()) {
226: return;
227: }
228: out.print(" ");
229: boolean first = true;
230: for (Iterator iter = attributes.entrySet().iterator(); iter
231: .hasNext();) {
232: Map.Entry entry = (Map.Entry) iter.next();
233: if (first) {
234: first = false;
235: } else {
236: out.print(" ");
237: }
238: out.print(entry.getKey().toString());
239: out.print("=");
240: Object value = entry.getValue();
241: if (value instanceof String) {
242: out.print(quote);
243: out.print((String) value);
244: out.print(quote);
245: continue;
246: }
247: out.print(InvokerHelper.toString(value));
248: }
249: }
250:
251: protected boolean printSpecialNode(Node node) {
252: return false;
253: }
254:
255: }
|