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