View Javadoc

1   /*
2    $Id: MarkupBuilder.java,v 1.8 2004/12/09 22:07:51 glaforge 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  package groovy.xml;
47  
48  import groovy.util.BuilderSupport;
49  import groovy.util.IndentPrinter;
50  
51  import java.io.PrintWriter;
52  import java.io.Writer;
53  import java.util.Iterator;
54  import java.util.Map;
55  
56  /***
57   * A helper class for creating XML or HTML markup
58   * 
59   * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
60   * @author Stefan Matthias Aust
61   * @version $Revision: 1.8 $
62   */
63  public class MarkupBuilder extends BuilderSupport {
64  
65      private IndentPrinter out;
66      private boolean nospace;
67      private int state;
68      private boolean nodeIsEmpty = true;
69  
70      public MarkupBuilder() {
71          this(new IndentPrinter());
72      }
73  
74      public MarkupBuilder(PrintWriter writer) {
75          this(new IndentPrinter(writer));
76      }
77  
78      public MarkupBuilder(Writer writer) {
79          this(new IndentPrinter(new PrintWriter(writer)));
80      }
81  
82      public MarkupBuilder(IndentPrinter out) {
83          this.out = out;
84      }
85  
86      protected void setParent(Object parent, Object child) {
87      }
88  
89      /*
90      public Object getProperty(String property) {
91          if (property.equals("_")) {
92              nospace = true;
93              return null;
94          } else {
95              Object node = createNode(property);
96              nodeCompleted(getCurrent(), node);
97              return node;
98          }
99      }
100     */
101 
102     protected Object createNode(Object name) {
103         toState(1, name);
104         return name;
105     }
106 
107     protected Object createNode(Object name, Object value) {
108         toState(2, name);
109         out.print(">");
110         out.print(value.toString());
111         return name;
112     }
113 
114     protected Object createNode(Object name, Map attributes, Object value) {
115         toState(1, name);
116         for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
117             Map.Entry entry = (Map.Entry) iter.next();
118             out.print(" ");
119             print(transformName(entry.getKey().toString()));
120             out.print("='");
121             print(transformValue(entry.getValue().toString()));
122             out.print("'");
123         }
124         if (value != null)
125         {
126             nodeIsEmpty = false;
127             out.print(">" + value + "</" + name + ">");
128         }
129         return name;
130     }
131 
132     protected Object createNode(Object name, Map attributes) {
133         return createNode(name, attributes, null);
134     }
135     
136     protected void nodeCompleted(Object parent, Object node) {
137         toState(3, node);
138         out.flush();
139     }
140 
141     protected void print(Object node) {
142         out.print(node == null ? "null" : node.toString());
143     }
144 
145     protected Object getName(String methodName) {
146 		return super.getName(transformName(methodName));
147 	}
148 
149     protected String transformName(String name) {
150     	if (name.startsWith("_")) name = name.substring(1);
151     	return name.replace('_', '-');
152     }
153 
154     protected String transformValue(String value) {
155         return value.replaceAll("//'", "&quot;");
156     }
157 
158     private void toState(int next, Object name) {
159         switch (state) {
160             case 0:
161                 switch (next) {
162                     case 1:
163                     case 2:
164                         out.print("<");
165                         print(name);
166                         break;
167                     case 3:
168                         throw new Error();
169                 }
170                 break;
171             case 1:
172                 switch (next) {
173                     case 1:
174                     case 2:
175                         out.print(">");
176                         if (nospace) {
177                             nospace = false;
178                         } else {
179                             out.println();
180                             out.incrementIndent();
181                             out.printIndent();
182                         }
183                         out.print("<");
184                         print(name);
185                         break;
186                     case 3:
187                         if (nodeIsEmpty) {
188                             out.print(" />");
189                         }
190                         break;
191                 }
192                 break;
193             case 2:
194                 switch (next) {
195                     case 1:
196                     case 2:
197                         throw new Error();
198                     case 3:
199                         out.print("</");
200                         print(name);
201                         out.print(">");
202                         break;
203                 }
204                 break;
205             case 3:
206                 switch (next) {
207                     case 1:
208                     case 2:
209                         if (nospace) {
210                             nospace = false;
211                         } else {
212                             out.println();
213                             out.printIndent();
214                         }
215                         out.print("<");
216                         print(name);
217                         break;
218                     case 3:
219                         if (nospace) {
220                             nospace = false;
221                         } else {
222                             out.println();
223                             out.decrementIndent();
224                             out.printIndent();
225                         }
226                         out.print("</");
227                         print(name);
228                         out.print(">");
229                         break;
230                 }
231                 break;
232         }
233         state = next;
234     }
235 
236 }