1 package org.codehaus.modello.plugin.stax;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import javax.inject.Named;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Properties;
31
32 import org.codehaus.modello.ModelloException;
33 import org.codehaus.modello.model.Model;
34 import org.codehaus.modello.plugin.java.javasource.JClass;
35 import org.codehaus.modello.plugin.java.javasource.JConstructor;
36 import org.codehaus.modello.plugin.java.javasource.JField;
37 import org.codehaus.modello.plugin.java.javasource.JMethod;
38 import org.codehaus.modello.plugin.java.javasource.JParameter;
39 import org.codehaus.modello.plugin.java.javasource.JSourceCode;
40 import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
41 import org.codehaus.modello.plugin.java.javasource.JType;
42 import org.codehaus.plexus.util.StringUtils;
43
44
45
46
47
48
49 @Named("stax-serializer")
50 public class StaxSerializerGenerator extends AbstractStaxGenerator {
51
52 public void generate(Model model, Properties parameters) throws ModelloException {
53 initialize(model, parameters);
54
55 try {
56 generateStaxSerializer();
57 } catch (IOException ex) {
58 throw new ModelloException("Exception while generating StAX serializer.", ex);
59 }
60 }
61
62 private void generateStaxSerializer() throws ModelloException, IOException {
63 Model objectModel = getModel();
64
65 String packageName =
66 objectModel.getDefaultPackageName(isPackageWithVersion(), getGeneratedVersion()) + ".io.stax";
67
68 String className = "IndentingXMLStreamWriter";
69
70 JSourceWriter sourceWriter = newJSourceWriter(packageName, className);
71
72 JClass jClass = new JClass(packageName + '.' + className);
73 jClass.getModifiers().makePackage();
74 jClass.addInterface("XMLStreamWriter");
75 initHeader(jClass);
76 suppressAllWarnings(objectModel, jClass);
77
78 jClass.addImport("javax.xml.namespace.NamespaceContext");
79 jClass.addImport("javax.xml.stream.XMLStreamException");
80 jClass.addImport("javax.xml.stream.XMLStreamWriter");
81
82 addField(jClass, "XMLStreamWriter", "out", null, false);
83 addField(jClass, "String", "NEW_LINE", "\"\\n\"", true);
84 addField(jClass, "String", "newLine", "NEW_LINE", false);
85 addField(jClass, "String", "indent", "\" \"", false);
86 addField(jClass, "char[]", "linePrefix", "\" \".toCharArray()", false);
87 addField(jClass, "int", "depth", null, false);
88 addField(jClass, "byte[]", "states", "{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }", false);
89 addField(jClass, "int", "ELEMENT_HAS_DATA", "0x1", true);
90 addField(jClass, "int", "ELEMENT_HAS_MARKUP", "0x2", true);
91
92 JConstructor constructor = jClass.createConstructor();
93 constructor.addParameter(new JParameter(new JType("XMLStreamWriter"), "out"));
94 constructor.getSourceCode().add("this.out = out;");
95
96 JMethod jMethod;
97 JSourceCode sc;
98
99 jMethod = new JMethod("setNewLine");
100 jMethod.addParameter(new JParameter(new JType("String"), "newLine"));
101 jMethod.getSourceCode().add("this.newLine = newLine;");
102 jClass.addMethod(jMethod);
103
104 jMethod = new JMethod("getLineSeparator", new JType("String"), null);
105 sc = jMethod.getSourceCode();
106 sc.add("try");
107 sc.add("{");
108 sc.addIndented("return System.getProperty( \"line.separator\", NEW_LINE );");
109 sc.add("}");
110 sc.add("catch ( Exception e )");
111 sc.add("{");
112 sc.addIndented("return NEW_LINE;");
113 sc.add("}");
114 jClass.addMethod(jMethod);
115
116 jMethod = new JMethod("beforeMarkup");
117 jMethod.getModifiers().makePrivate();
118 sc = jMethod.getSourceCode();
119 sc.add("int state = states[depth];");
120 sc.add("if ( ( state & ELEMENT_HAS_DATA ) == 0 && ( depth > 0 || state != 0 ) )");
121 sc.add("{");
122 sc.indent();
123 sc.add("newLine( depth );");
124 sc.add("if ( depth > 0 && indent.length() > 0 )");
125 sc.add("{");
126 sc.addIndented("afterMarkup();");
127 sc.add("}");
128 sc.unindent();
129 sc.add("}");
130 jClass.addMethod(jMethod);
131
132 jMethod = new JMethod("afterMarkup");
133 jMethod.getModifiers().makePrivate();
134 jMethod.getSourceCode().add("states[depth] |= ELEMENT_HAS_MARKUP;");
135 jClass.addMethod(jMethod);
136
137 jMethod = new JMethod("beforeStartElement");
138 jMethod.getModifiers().makePrivate();
139 sc = jMethod.getSourceCode();
140 sc.add("beforeMarkup();");
141 sc.add("if ( states.length <= depth + 1 )");
142 sc.add("{");
143 sc.indent();
144 sc.add("byte[] tmp = new byte[states.length * 2];");
145 sc.add("System.arraycopy( states, 0, tmp, 0, states.length );");
146 sc.add("states = tmp;");
147 sc.unindent();
148 sc.add("}");
149 sc.add("states[depth + 1] = 0;");
150 jClass.addMethod(jMethod);
151
152 jMethod = new JMethod("afterStartElement");
153 jMethod.getModifiers().makePrivate();
154 sc = jMethod.getSourceCode();
155 sc.add("afterMarkup();");
156 sc.add("depth++;");
157 jClass.addMethod(jMethod);
158
159 jMethod = new JMethod("beforeEndElement");
160 jMethod.getModifiers().makePrivate();
161 sc = jMethod.getSourceCode();
162 sc.add("if ( depth > 0 && states[depth] == ELEMENT_HAS_MARKUP )");
163 sc.add("{");
164 sc.addIndented("newLine( depth - 1 );");
165 sc.add("}");
166 jClass.addMethod(jMethod);
167
168 jMethod = new JMethod("afterEndElement");
169 jMethod.getModifiers().makePrivate();
170 sc = jMethod.getSourceCode();
171 sc.add("if ( depth > 0 )");
172 sc.add("{");
173 sc.indent();
174 sc.add("depth--;");
175 sc.add("if ( depth <= 0 )");
176 sc.add("{");
177 sc.addIndented("newLine( 0 );");
178 sc.add("}");
179 sc.unindent();
180 sc.add("}");
181 jClass.addMethod(jMethod);
182
183 jMethod = new JMethod("afterData");
184 jMethod.getModifiers().makePrivate();
185 jMethod.getSourceCode().add("states[depth] |= ELEMENT_HAS_DATA;");
186 jClass.addMethod(jMethod);
187
188 jMethod = new JMethod("newLine");
189 jMethod.addParameter(new JParameter(JType.INT, "depth"));
190 jMethod.getModifiers().makePrivate();
191 sc = jMethod.getSourceCode();
192 sc.add("try");
193 sc.add("{");
194 sc.indent();
195 sc.add("out.writeCharacters( newLine );");
196 sc.add("int prefixLength = depth * indent.length();");
197 sc.add("while ( linePrefix.length < prefixLength )");
198 sc.add("{");
199 sc.indent();
200 sc.add("char[] tmp = new char[linePrefix.length * 2];");
201 sc.add("System.arraycopy( linePrefix, 0, tmp, 0, linePrefix.length );");
202 sc.add("System.arraycopy( linePrefix, 0, tmp, linePrefix.length, linePrefix.length );");
203 sc.add("linePrefix = tmp;");
204 sc.unindent();
205 sc.add("}");
206 sc.add("out.writeCharacters( linePrefix, 0, prefixLength );");
207 sc.unindent();
208 sc.add("}");
209 sc.add("catch ( Exception e )");
210 sc.add("{");
211 sc.add("}");
212 jClass.addMethod(jMethod);
213
214 jMethod = new JMethod("close");
215 jMethod.addException(new JClass("XMLStreamException"));
216 jMethod.getSourceCode().add("out.close();");
217 jClass.addMethod(jMethod);
218
219 jMethod = new JMethod("flush");
220 jMethod.addException(new JClass("XMLStreamException"));
221 jMethod.getSourceCode().add("out.flush();");
222 jClass.addMethod(jMethod);
223
224 jMethod = new JMethod("getNamespaceContext", new JType("NamespaceContext"), null);
225 jMethod.getSourceCode().add("return out.getNamespaceContext();");
226 jClass.addMethod(jMethod);
227
228 jMethod = new JMethod("getPrefix", new JType("String"), null);
229 jMethod.addException(new JClass("XMLStreamException"));
230 jMethod.addParameter(param("String", "uri"));
231 jMethod.getSourceCode().add("return out.getPrefix( uri );");
232 jClass.addMethod(jMethod);
233
234 jMethod = new JMethod("getProperty", new JType("Object"), null);
235 jMethod.addException(new JClass("IllegalArgumentException"));
236 jMethod.addParameter(param("String", "name"));
237 jMethod.getSourceCode().add("return out.getProperty( name );");
238 jClass.addMethod(jMethod);
239
240 jMethod = new JMethod("setDefaultNamespace");
241 jMethod.addException(new JClass("XMLStreamException"));
242 jMethod.addParameter(param("String", "uri"));
243 jMethod.getSourceCode().add("out.setDefaultNamespace( uri );");
244 jClass.addMethod(jMethod);
245
246 jMethod = new JMethod("setNamespaceContext");
247 jMethod.addException(new JClass("XMLStreamException"));
248 jMethod.addParameter(param("NamespaceContext", "context"));
249 jMethod.getSourceCode().add("out.setNamespaceContext( context );");
250 jClass.addMethod(jMethod);
251
252 jMethod = new JMethod("setPrefix");
253 jMethod.addException(new JClass("XMLStreamException"));
254 jMethod.addParameter(param("String", "prefix"));
255 jMethod.addParameter(param("String", "uri"));
256 jMethod.getSourceCode().add("out.setPrefix( prefix, uri );");
257 jClass.addMethod(jMethod);
258
259 add(jClass, "Attribute", null, null, param("String", "localName"), param("String", "value"));
260 add(
261 jClass,
262 "Attribute",
263 null,
264 null,
265 param("String", "namespaceURI"),
266 param("String", "localName"),
267 param("String", "value"));
268 add(
269 jClass,
270 "Attribute",
271 null,
272 null,
273 param("String", "prefix"),
274 param("String", "namespaceURI"),
275 param("String", "localName"),
276 param("String", "value"));
277
278 add(jClass, "CData", null, "Data", param("String", "data"));
279
280 add(jClass, "Characters", null, "Data", param("String", "text"));
281 add(jClass, "Characters", null, "Data", param("char[]", "text"), param("int", "start"), param("int", "len"));
282
283 add(jClass, "Comment", "Markup", "Markup", param("String", "data"));
284
285 add(jClass, "DTD", "Markup", "Markup", param("String", "dtd"));
286
287 add(jClass, "DefaultNamespace", null, null, param("String", "namespaceURI"));
288
289 add(jClass, "EmptyElement", "Markup", "Markup", param("String", "localName"));
290 add(jClass, "EmptyElement", "Markup", "Markup", param("String", "namespaceURI"), param("String", "localName"));
291 add(
292 jClass,
293 "EmptyElement",
294 "Markup",
295 "Markup",
296 param("String", "prefix"),
297 param("String", "namespaceURI"),
298 param("String", "localName"));
299
300 add(jClass, "EndDocument", null, null);
301
302 add(jClass, "EndElement", "EndElement", "EndElement");
303
304 add(jClass, "EntityRef", null, "Data", param("String", "name"));
305
306 add(jClass, "Namespace", null, null, param("String", "prefix"), param("String", "namespaceURI"));
307
308 add(jClass, "ProcessingInstruction", "Markup", "Markup", param("String", "target"));
309 add(jClass, "ProcessingInstruction", "Markup", "Markup", param("String", "target"), param("String", "data"));
310
311 add(jClass, "StartDocument", "Markup", "Markup");
312 add(jClass, "StartDocument", "Markup", "Markup", param("String", "version"));
313 add(jClass, "StartDocument", "Markup", "Markup", param("String", "encoding"), param("String", "version"));
314
315 add(jClass, "StartElement", "StartElement", "StartElement", param("String", "localName"));
316 add(
317 jClass,
318 "StartElement",
319 "StartElement",
320 "StartElement",
321 param("String", "namespaceURI"),
322 param("String", "localName"));
323 add(
324 jClass,
325 "StartElement",
326 "StartElement",
327 "StartElement",
328 param("String", "prefix"),
329 param("String", "localName"),
330 param("String", "namespaceURI"));
331
332 jClass.print(sourceWriter);
333
334 sourceWriter.close();
335 }
336
337 private void addField(JClass jClass, String fieldType, String fieldName, String initializer, boolean constant) {
338 JField jField = new JField(new JType(fieldType), fieldName);
339 jField.setInitString(initializer);
340 if (constant) {
341 jField.getModifiers().setFinal(true);
342 jField.getModifiers().setStatic(true);
343 }
344 jClass.addField(jField);
345 }
346
347 private void add(JClass jClass, String name, String before, String after, JParameter... params) {
348 List<String> names = new ArrayList<String>();
349
350 JMethod jMethod = new JMethod("write" + name);
351 jMethod.addException(new JClass("XMLStreamException"));
352
353 for (JParameter param : params) {
354 jMethod.addParameter(param);
355 names.add(param.getName());
356 }
357
358 JSourceCode sc = jMethod.getSourceCode();
359 if (before != null) {
360 sc.add("before" + before + "();");
361 }
362
363 sc.add("out.write" + name + "( " + StringUtils.join(names.iterator(), ", ") + " );");
364
365 if (after != null) {
366 sc.add("after" + after + "();");
367 }
368
369 jClass.addMethod(jMethod);
370 }
371
372 private static JParameter param(String type, String name) {
373 return new JParameter(new JType(type), name);
374 }
375 }