1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
91
92
93
94
95
96
97
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("//'", """);
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 }