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.Arrays;
29 import java.util.List;
30 import java.util.Properties;
31
32 import org.codehaus.modello.ModelloException;
33 import org.codehaus.modello.ModelloParameterConstants;
34 import org.codehaus.modello.model.Model;
35 import org.codehaus.modello.model.ModelAssociation;
36 import org.codehaus.modello.model.ModelClass;
37 import org.codehaus.modello.model.ModelDefault;
38 import org.codehaus.modello.model.ModelField;
39 import org.codehaus.modello.model.Version;
40 import org.codehaus.modello.model.VersionDefinition;
41 import org.codehaus.modello.plugin.java.javasource.JClass;
42 import org.codehaus.modello.plugin.java.javasource.JField;
43 import org.codehaus.modello.plugin.java.javasource.JMethod;
44 import org.codehaus.modello.plugin.java.javasource.JParameter;
45 import org.codehaus.modello.plugin.java.javasource.JSourceCode;
46 import org.codehaus.modello.plugin.java.javasource.JSourceWriter;
47 import org.codehaus.modello.plugin.java.javasource.JType;
48 import org.codehaus.modello.plugin.java.metadata.JavaAssociationMetadata;
49 import org.codehaus.modello.plugin.java.metadata.JavaFieldMetadata;
50 import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata;
51 import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata;
52 import org.codehaus.modello.plugins.xml.metadata.XmlModelMetadata;
53 import org.codehaus.plexus.util.StringUtils;
54
55
56
57
58
59 @Named("stax-reader")
60 public class StaxReaderGenerator extends AbstractStaxGenerator {
61
62 private boolean requiresDomSupport;
63
64 public void generate(Model model, Properties parameters) throws ModelloException {
65 initialize(model, parameters);
66
67 requiresDomSupport = false;
68
69 try {
70 generateStaxReader();
71
72 VersionDefinition versionDefinition = model.getVersionDefinition();
73 if (versionDefinition != null) {
74 String versions = parameters.getProperty(ModelloParameterConstants.ALL_VERSIONS);
75
76 if (versions != null) {
77 generateStaxReaderDelegate(Arrays.asList(versions.split(",")));
78 }
79 }
80 } catch (IOException ex) {
81 throw new ModelloException("Exception while generating StAX Reader.", ex);
82 }
83 }
84
85
86
87
88
89
90
91
92 private void generateStaxReader() throws ModelloException, IOException {
93 Model objectModel = getModel();
94
95 String packageName =
96 objectModel.getDefaultPackageName(isPackageWithVersion(), getGeneratedVersion()) + ".io.stax";
97
98 String unmarshallerName = getFileName("StaxReader");
99
100 JSourceWriter sourceWriter = newJSourceWriter(packageName, unmarshallerName);
101
102 JClass jClass = new JClass(packageName + '.' + unmarshallerName);
103 initHeader(jClass);
104 suppressAllWarnings(objectModel, jClass);
105
106 jClass.addImport("java.io.IOException");
107 jClass.addImport("java.io.Reader");
108 jClass.addImport("java.io.FileInputStream");
109 jClass.addImport("java.io.InputStream");
110 jClass.addImport("java.io.StringWriter");
111 jClass.addImport("java.io.StringReader");
112 jClass.addImport("java.io.ByteArrayInputStream");
113 jClass.addImport("java.io.InputStreamReader");
114 jClass.addImport("java.text.DateFormat");
115 jClass.addImport("java.text.ParsePosition");
116 jClass.addImport("java.util.regex.Matcher");
117 jClass.addImport("java.util.regex.Pattern");
118 jClass.addImport("java.util.Locale");
119 jClass.addImport("javax.xml.XMLConstants");
120 jClass.addImport("javax.xml.stream.*");
121
122 addModelImports(jClass, null);
123
124
125
126
127
128 ModelClass root = objectModel.getClass(objectModel.getRoot(getGeneratedVersion()), getGeneratedVersion());
129 JClass rootType = new JClass(root.getName());
130
131 GeneratorNode rootNode = findRequiredReferenceResolvers(root, null);
132
133 writeReferenceResolvers(rootNode, jClass);
134 for (GeneratorNode node : rootNode.getNodesWithReferencableChildren().values()) {
135 writeReferenceResolvers(node, jClass);
136 }
137
138
139
140
141
142 writeAllClassesParser(objectModel, jClass);
143
144
145
146
147
148 writeHelpers(jClass);
149
150 if (requiresDomSupport) {
151 writeBuildDomMethod(jClass);
152 }
153
154
155
156
157
158 JMethod unmarshall = new JMethod("read", rootType, null);
159 unmarshall.getModifiers().makePrivate();
160
161 unmarshall.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
162 unmarshall.addParameter(new JParameter(JType.BOOLEAN, "strict"));
163
164 unmarshall.addException(new JClass("IOException"));
165 unmarshall.addException(new JClass("XMLStreamException"));
166
167 JSourceCode sc = unmarshall.getSourceCode();
168
169 String tagName = resolveTagName(root);
170 String className = root.getName();
171 String variableName = uncapitalise(className);
172
173 if (requiresDomSupport && !domAsXpp3) {
174 sc.add("if ( _doc_ == null )");
175 sc.add("{");
176 sc.indent();
177 sc.add("try");
178 sc.add("{");
179 sc.addIndented("initDoc();");
180 sc.add("}");
181 sc.add("catch ( javax.xml.parsers.ParserConfigurationException pce )");
182 sc.add("{");
183 sc.addIndented(
184 "throw new XMLStreamException( \"Unable to create DOM document: \" + pce.getMessage(), pce );");
185 sc.add("}");
186 sc.unindent();
187 sc.add("}");
188 }
189
190 sc.add("int eventType = xmlStreamReader.getEventType();");
191
192 sc.add("String encoding = null;");
193
194 sc.add("while ( eventType != XMLStreamConstants.END_DOCUMENT )");
195
196 sc.add("{");
197 sc.indent();
198
199 sc.add("if ( eventType == XMLStreamConstants.START_DOCUMENT )");
200 sc.add("{");
201 sc.addIndented("encoding = xmlStreamReader.getCharacterEncodingScheme();");
202 sc.add("}");
203
204 sc.add("if ( eventType == XMLStreamConstants.START_ELEMENT )");
205
206 sc.add("{");
207 sc.indent();
208
209 sc.add("if ( strict && ! \"" + tagName + "\".equals( xmlStreamReader.getLocalName() ) )");
210
211 sc.add("{");
212 sc.addIndented("throw new XMLStreamException( \"Expected root element '" + tagName + "' but "
213 + "found '\" + xmlStreamReader.getLocalName() + \"'\", xmlStreamReader.getLocation(), null );");
214 sc.add("}");
215
216 VersionDefinition versionDefinition = objectModel.getVersionDefinition();
217 if (versionDefinition != null && versionDefinition.isNamespaceType()) {
218 sc.add("String modelVersion = getVersionFromRootNamespace( xmlStreamReader );");
219
220 writeModelVersionCheck(sc);
221 }
222
223 sc.add(className + ' ' + variableName + " = parse" + root.getName() + "( xmlStreamReader, strict );");
224
225 sc.add(variableName + ".setModelEncoding( encoding );");
226
227 sc.add("resolveReferences( " + variableName + " );");
228
229 sc.add("return " + variableName + ';');
230
231 sc.unindent();
232 sc.add("}");
233
234 sc.add("eventType = xmlStreamReader.next();");
235
236 sc.unindent();
237 sc.add("}");
238
239 sc.add("throw new XMLStreamException( \"Expected root element '" + tagName + "' but "
240 + "found no element at all: invalid XML document\", xmlStreamReader.getLocation(), null );");
241
242 jClass.addMethod(unmarshall);
243
244
245
246
247
248 unmarshall = new JMethod("read", rootType, null);
249
250 unmarshall.addParameter(new JParameter(new JClass("Reader"), "reader"));
251 unmarshall.addParameter(new JParameter(JType.BOOLEAN, "strict"));
252
253 unmarshall.addException(new JClass("IOException"));
254 unmarshall.addException(new JClass("XMLStreamException"));
255
256 sc = unmarshall.getSourceCode();
257
258 sc.add("XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader( reader );");
259
260 sc.add("");
261
262 sc.add("return read( xmlStreamReader, strict );");
263
264 jClass.addMethod(unmarshall);
265
266
267
268 unmarshall = new JMethod("read", rootType, null);
269
270 unmarshall.addParameter(new JParameter(new JClass("Reader"), "reader"));
271
272 unmarshall.addException(new JClass("IOException"));
273 unmarshall.addException(new JClass("XMLStreamException"));
274
275 sc = unmarshall.getSourceCode();
276 sc.add("return read( reader, true );");
277
278 jClass.addMethod(unmarshall);
279
280
281
282
283
284 unmarshall = new JMethod("read", rootType, null);
285
286 unmarshall.addParameter(new JParameter(new JClass("InputStream"), "stream"));
287 unmarshall.addParameter(new JParameter(JType.BOOLEAN, "strict"));
288
289 unmarshall.addException(new JClass("IOException"));
290 unmarshall.addException(new JClass("XMLStreamException"));
291
292 sc = unmarshall.getSourceCode();
293
294 sc.add("XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader( stream );");
295
296 sc.add("");
297
298 sc.add("return read( xmlStreamReader, strict );");
299
300 jClass.addMethod(unmarshall);
301
302
303
304 unmarshall = new JMethod("read", rootType, null);
305
306 unmarshall.addParameter(new JParameter(new JClass("InputStream"), "stream"));
307
308 unmarshall.addException(new JClass("IOException"));
309 unmarshall.addException(new JClass("XMLStreamException"));
310
311 sc = unmarshall.getSourceCode();
312 sc.add("return read( stream, true );");
313
314 jClass.addMethod(unmarshall);
315
316
317
318
319
320 unmarshall = new JMethod("read", rootType, null);
321
322 unmarshall.addParameter(new JParameter(new JClass("String"), "filePath"));
323
324 unmarshall.addParameter(new JParameter(JType.BOOLEAN, "strict"));
325
326 unmarshall.addException(new JClass("IOException"));
327 unmarshall.addException(new JClass("XMLStreamException"));
328
329 sc = unmarshall.getSourceCode();
330
331 sc.add("java.io.File file = new java.io.File( filePath );");
332
333 sc.add("XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader( "
334 + "file.toURI().toURL().toExternalForm(), new FileInputStream( file ) );");
335
336 sc.add("");
337
338 sc.add("return read( xmlStreamReader, strict );");
339
340 jClass.addMethod(unmarshall);
341
342
343
344 unmarshall = new JMethod("read", rootType, null);
345
346 unmarshall.addParameter(new JParameter(new JClass("String"), "filePath"));
347
348 unmarshall.addException(new JClass("IOException"));
349 unmarshall.addException(new JClass("XMLStreamException"));
350
351 sc = unmarshall.getSourceCode();
352 sc.add("return read( filePath, true );");
353
354 jClass.addMethod(unmarshall);
355
356
357
358
359 if (versionDefinition != null) {
360 writeDetermineVersionMethod(jClass, objectModel);
361 }
362
363
364
365
366
367 jClass.print(sourceWriter);
368
369 sourceWriter.close();
370 }
371
372 private void generateStaxReaderDelegate(List<String> versions) throws ModelloException, IOException {
373 Model objectModel = getModel();
374
375 String packageName = objectModel.getDefaultPackageName(false, null) + ".io.stax";
376
377 String unmarshallerName = getFileName("StaxReaderDelegate");
378
379 JSourceWriter sourceWriter = newJSourceWriter(packageName, unmarshallerName);
380
381 JClass jClass = new JClass(packageName + '.' + unmarshallerName);
382
383 jClass.addImport("java.io.IOException");
384 jClass.addImport("java.io.Reader");
385
386 jClass.addImport("javax.xml.stream.*");
387
388 jClass.addImport("org.codehaus.plexus.util.IOUtil");
389 jClass.addImport("org.codehaus.plexus.util.xml.XmlStreamReader");
390
391 JMethod method = new JMethod("read", new JClass("Object"), null);
392
393 method.addParameter(new JParameter(new JClass("java.io.File"), "f"));
394
395 method.addParameter(new JParameter(JType.BOOLEAN, "strict"));
396
397 method.addException(new JClass("IOException"));
398 method.addException(new JClass("XMLStreamException"));
399
400 jClass.addMethod(method);
401
402 JSourceCode sc = method.getSourceCode();
403
404 sc.add("String modelVersion;");
405 sc.add("Reader reader = new XmlStreamReader( f );");
406
407 sc.add("try");
408 sc.add("{");
409 sc.addIndented("modelVersion = determineVersion( reader );");
410 sc.add("}");
411 sc.add("finally");
412 sc.add("{");
413 sc.addIndented("IOUtil.close( reader );");
414 sc.add("}");
415
416 sc.add("reader = new XmlStreamReader( f );");
417 sc.add("try");
418 sc.add("{");
419 sc.indent();
420
421 writeModelVersionHack(sc);
422
423 String prefix = "";
424 for (String version : versions) {
425 sc.add(prefix + "if ( \"" + version + "\".equals( modelVersion ) )");
426 sc.add("{");
427 sc.addIndented("return new " + getModel().getDefaultPackageName(true, new Version(version)) + ".io.stax."
428 + getFileName("StaxReader") + "().read( reader, strict );");
429 sc.add("}");
430
431 prefix = "else ";
432 }
433
434 sc.add("else");
435 sc.add("{");
436 sc.addIndented("throw new XMLStreamException( \"Document version '\" + modelVersion + \"' has no "
437 + "corresponding reader.\" );");
438 sc.add("}");
439
440 sc.unindent();
441 sc.add("}");
442 sc.add("finally");
443 sc.add("{");
444 sc.addIndented("IOUtil.close( reader );");
445 sc.add("}");
446
447
448
449 method = new JMethod("read", new JClass("Object"), null);
450
451 method.addParameter(new JParameter(new JClass("java.io.File"), "f"));
452
453 method.addException(new JClass("IOException"));
454 method.addException(new JClass("XMLStreamException"));
455
456 sc = method.getSourceCode();
457 sc.add("return read( f, true );");
458
459 jClass.addMethod(method);
460
461 writeDetermineVersionMethod(jClass, objectModel);
462
463 jClass.print(sourceWriter);
464
465 sourceWriter.close();
466 }
467
468 private static void writeModelVersionHack(JSourceCode sc) {
469 sc.add("// legacy hack for pomVersion == 3");
470 sc.add("if ( \"3\".equals( modelVersion ) )");
471 sc.add("{");
472 sc.addIndented("modelVersion = \"3.0.0\";");
473 sc.add("}");
474 }
475
476 private void writeDetermineVersionMethod(JClass jClass, Model objectModel) throws ModelloException {
477 VersionDefinition versionDefinition = objectModel.getVersionDefinition();
478
479 JMethod method = new JMethod("determineVersion", new JClass("String"), null);
480
481 method.addParameter(new JParameter(new JClass("Reader"), "reader"));
482
483 method.addException(new JClass("IOException"));
484 method.addException(new JClass("XMLStreamException"));
485
486 JSourceCode sc = method.getSourceCode();
487
488 sc.add("XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader( reader );");
489
490 sc.add("while ( xmlStreamReader.hasNext() )");
491
492 sc.add("{");
493 sc.indent();
494
495 sc.add("int eventType = xmlStreamReader.next();");
496
497 sc.add("if ( eventType == XMLStreamConstants.START_ELEMENT )");
498
499 sc.add("{");
500 sc.indent();
501
502 if (versionDefinition.isNamespaceType()) {
503 XmlModelMetadata xmlModelMetadata = (XmlModelMetadata) objectModel.getMetadata(XmlModelMetadata.ID);
504
505 String namespace = xmlModelMetadata.getNamespace();
506 if (namespace == null || !namespace.contains("${version}")) {
507 throw new ModelloException("versionDefinition is namespace, but the model does not declare "
508 + "xml.namespace on the model element");
509 }
510
511 sc.add("return getVersionFromRootNamespace( xmlStreamReader );");
512
513 writeNamespaceVersionGetMethod(namespace, jClass);
514 } else {
515 String value = versionDefinition.getValue();
516
517 ModelClass root = objectModel.getClass(objectModel.getRoot(getGeneratedVersion()), getGeneratedVersion());
518 ModelField field = root.getField(value, getGeneratedVersion());
519
520 if (field == null) {
521 throw new ModelloException("versionDefinition is field, but the model root element does not declare a "
522 + "field '" + value + "'.");
523 }
524
525 if (!"String".equals(field.getType())) {
526 throw new ModelloException("versionDefinition is field, but the field is not of type String");
527 }
528
529 sc.add("return getVersionFromField( xmlStreamReader );");
530
531 writeFieldVersionGetMethod(field, jClass);
532 }
533
534 sc.unindent();
535 sc.add("}");
536
537 sc.unindent();
538 sc.add("}");
539
540 sc.add("throw new XMLStreamException( \"Version not found in document\", xmlStreamReader.getLocation() );");
541
542 jClass.addMethod(method);
543 }
544
545 private static void writeFieldVersionGetMethod(ModelField field, JClass jClass) {
546 JMethod method = new JMethod("getVersionFromField", new JType("String"), null);
547 method.getModifiers().makePrivate();
548 method.addParameter(new JParameter(new JType("XMLStreamReader"), "xmlStreamReader"));
549 method.addException(new JClass("XMLStreamException"));
550 jClass.addMethod(method);
551
552 JSourceCode sc = method.getSourceCode();
553
554 XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
555 String value = xmlFieldMetadata.getTagName();
556 if (value == null) {
557 value = field.getName();
558 }
559
560
561
562 sc.add("int depth = 0;");
563
564 sc.add("while ( depth >= 0 )");
565
566 sc.add("{");
567 sc.indent();
568
569 sc.add("int eventType = xmlStreamReader.next();");
570
571 sc.add("if ( eventType == XMLStreamConstants.START_ELEMENT )");
572 sc.add("{");
573 sc.indent();
574
575 sc.add("if ( depth == 0 && \"" + value + "\".equals( xmlStreamReader.getLocalName() ) )");
576 sc.add("{");
577 sc.addIndented("return xmlStreamReader.getElementText();");
578 sc.add("}");
579
580 if (field.getAlias() != null) {
581 sc.add("if ( depth == 0 && \"" + field.getAlias() + "\".equals( xmlStreamReader.getLocalName() ) )");
582 sc.add("{");
583 sc.addIndented("return xmlStreamReader.getElementText();");
584 sc.add("}");
585 }
586
587 sc.add("depth++;");
588
589 sc.unindent();
590 sc.add("}");
591
592 sc.add("if ( eventType == XMLStreamConstants.END_ELEMENT )");
593 sc.add("{");
594 sc.addIndented("depth--;");
595 sc.add("}");
596
597 sc.unindent();
598 sc.add("}");
599
600 sc.add("throw new XMLStreamException( \"Field: '" + value
601 + "' does not exist in the document.\", xmlStreamReader.getLocation() );");
602 }
603
604 private static void writeNamespaceVersionGetMethod(String namespace, JClass jClass) {
605 JMethod method = new JMethod("getVersionFromRootNamespace", new JType("String"), null);
606 method.getModifiers().makePrivate();
607 method.addParameter(new JParameter(new JType("XMLStreamReader"), "xmlStreamReader"));
608 method.addException(new JClass("XMLStreamException"));
609 jClass.addMethod(method);
610
611 JSourceCode sc = method.getSourceCode();
612
613 sc.add("String uri = xmlStreamReader.getNamespaceURI( \"\" );");
614
615 sc.add("if ( uri == null )");
616
617 sc.add("{");
618 sc.addIndented("throw new XMLStreamException( \"No namespace specified, but versionDefinition requires it\", "
619 + "xmlStreamReader.getLocation() );");
620 sc.add("}");
621
622 int index = namespace.indexOf("${version}");
623
624 sc.add("String uriPrefix = \"" + namespace.substring(0, index) + "\";");
625 sc.add("String uriSuffix = \"" + namespace.substring(index + 10) + "\";");
626
627 sc.add("if ( !uri.startsWith( uriPrefix ) || !uri.endsWith( uriSuffix ) )");
628
629 sc.add("{");
630 sc.addIndented("throw new XMLStreamException( \"Namespace URI: '\" + uri + \"' does not match pattern '"
631 + namespace + "'\", xmlStreamReader.getLocation() );");
632 sc.add("}");
633
634 sc.add("return uri.substring( uriPrefix.length(), uri.length() - uriSuffix.length() );");
635 }
636
637
638
639
640
641
642
643
644
645 private void writeAllClassesParser(Model objectModel, JClass jClass) throws ModelloException {
646 ModelClass root = objectModel.getClass(objectModel.getRoot(getGeneratedVersion()), getGeneratedVersion());
647
648 for (ModelClass clazz : getClasses(objectModel)) {
649 writeClassParser(clazz, jClass, root.getName().equals(clazz.getName()));
650 }
651 }
652
653
654
655
656
657
658
659
660
661 private void writeClassParser(ModelClass modelClass, JClass jClass, boolean rootElement) throws ModelloException {
662 String className = modelClass.getName();
663
664 String capClassName = capitalise(className);
665
666 String uncapClassName = uncapitalise(className);
667
668 JMethod unmarshall = new JMethod("parse" + capClassName, new JClass(className), null);
669 unmarshall.getModifiers().makePrivate();
670
671 unmarshall.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
672 unmarshall.addParameter(new JParameter(JType.BOOLEAN, "strict"));
673
674 unmarshall.addException(new JClass("IOException"));
675 unmarshall.addException(new JClass("XMLStreamException"));
676
677 JSourceCode sc = unmarshall.getSourceCode();
678
679 sc.add(className + ' ' + uncapClassName + " = new " + className + "();");
680
681 ModelField contentField = getContentField(modelClass.getAllFields(getGeneratedVersion(), true));
682
683 if (contentField != null) {
684 writeAttributes(modelClass, uncapClassName, sc);
685
686 writePrimitiveField(
687 contentField,
688 contentField.getType(),
689 uncapClassName,
690 "set" + capitalise(contentField.getName()),
691 sc);
692 } else {
693 sc.add("java.util.Set parsed = new java.util.HashSet();");
694
695 String instanceFieldName = getInstanceFieldName(className);
696
697 writeAttributes(modelClass, uncapClassName, sc);
698
699 if (isAssociationPartToClass(modelClass)) {
700 jClass.addField(new JField(new JType("java.util.Map"), instanceFieldName));
701
702 sc.add("if ( " + instanceFieldName + " == null )");
703 sc.add("{");
704 sc.addIndented(instanceFieldName + " = new java.util.HashMap();");
705 sc.add("}");
706
707 sc.add("String v = xmlStreamReader.getAttributeValue( null, \"modello.id\" );");
708 sc.add("if ( v != null )");
709 sc.add("{");
710 sc.addIndented(instanceFieldName + ".put( v, " + uncapClassName + " );");
711 sc.add("}");
712 }
713
714 sc.add(
715 "while ( ( strict ? xmlStreamReader.nextTag() : nextTag( xmlStreamReader ) ) == XMLStreamConstants.START_ELEMENT )");
716
717 sc.add("{");
718 sc.indent();
719
720 boolean addElse = false;
721
722
723
724 for (ModelField field : modelClass.getAllFields(getGeneratedVersion(), true)) {
725 XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
726
727 if (!xmlFieldMetadata.isAttribute() && !xmlFieldMetadata.isTransient()) {
728 processField(field, xmlFieldMetadata, addElse, sc, uncapClassName, rootElement, jClass);
729
730 addElse = true;
731 }
732 }
733
734
735
736
737
738
739
740
741
742
743
744
745 if (addElse) {
746 sc.add("else");
747
748 sc.add("{");
749 sc.indent();
750 }
751
752 sc.add("checkUnknownElement( xmlStreamReader, strict );");
753
754 if (addElse) {
755 sc.unindent();
756 sc.add("}");
757 }
758
759 sc.unindent();
760 sc.add("}");
761
762
763 if (isAssociationPartToClass(modelClass)) {
764 List<ModelField> identifierFields = modelClass.getIdentifierFields(getGeneratedVersion());
765
766 if (identifierFields.size() == 1) {
767 ModelField field = (ModelField) identifierFields.get(0);
768
769 String v = uncapClassName + ".get" + capitalise(field.getName()) + "()";
770 v = getValue(field.getType(), v, (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID));
771 sc.add(instanceFieldName + ".put( " + v + ", " + uncapClassName + " );");
772 }
773 }
774 }
775
776 sc.add("return " + uncapClassName + ";");
777
778 jClass.addMethod(unmarshall);
779 }
780
781 private GeneratorNode findRequiredReferenceResolvers(ModelClass modelClass, GeneratorNode parent)
782 throws ModelloException {
783 String className = modelClass.getName();
784
785 GeneratorNode value = new GeneratorNode(className, parent);
786
787 for (ModelField field : modelClass.getAllFields(getGeneratedVersion(), true)) {
788 if (field instanceof ModelAssociation) {
789 ModelAssociation association = (ModelAssociation) field;
790
791 if (isClassInModel(association.getTo(), getModel())) {
792 ModelField referenceIdentifierField = getReferenceIdentifierField(association);
793
794 GeneratorNode child = null;
795 if (referenceIdentifierField != null) {
796 child = new GeneratorNode(association, parent);
797 child.setReferencable(true);
798 } else {
799 if (!value.getChain().contains(association.getTo())) {
800
801 child = findRequiredReferenceResolvers(association.getToClass(), value);
802 child.setAssociation(association);
803 }
804 }
805 if (child != null) {
806 value.addChild(child);
807 }
808 }
809 }
810 }
811
812
813 for (GeneratorNode child : value.getChildren()) {
814 if (child.isReferencable() || child.isReferencableChildren()) {
815 value.setReferencableChildren(true);
816 }
817
818 value.addNodesWithReferencableChildren(child.getNodesWithReferencableChildren());
819 }
820
821 return value;
822 }
823
824 private void writeReferenceResolvers(GeneratorNode node, JClass jClass) {
825 JMethod unmarshall = new JMethod("resolveReferences");
826
827 unmarshall.addParameter(new JParameter(new JClass(node.getTo()), "value"));
828
829 unmarshall.getModifiers().makePrivate();
830
831 JSourceCode sc = unmarshall.getSourceCode();
832
833 sc.add("java.util.Map refs;");
834
835 for (GeneratorNode child : node.getChildren()) {
836 if (child.isReferencable()) {
837 ModelAssociation association = child.getAssociation();
838 String refFieldName = getRefFieldName(association);
839 String to = association.getTo();
840 String instanceFieldName = getInstanceFieldName(to);
841
842 sc.add("if ( " + refFieldName + " != null )");
843 sc.add("{");
844 sc.indent();
845
846 sc.add("refs = (java.util.Map) " + refFieldName + ".get( value );");
847
848 sc.add("if ( refs != null )");
849 sc.add("{");
850 sc.indent();
851
852 String capAssocName = capitalise(association.getName());
853 if (association.isOneMultiplicity()) {
854 sc.add("String id = (String) refs.get( \"" + association.getName() + "\" );");
855 sc.add(to + " ref = (" + to + ") " + instanceFieldName + ".get( id );");
856
857
858
859
860 sc.add("if ( ref != null && !ref.equals( value.get" + capAssocName + "() ) )");
861 sc.add("{");
862 sc.addIndented("value.set" + capAssocName + "( ref );");
863 sc.add("}");
864 } else {
865 sc.add("for ( int i = 0; i < value.get" + capAssocName + "().size(); i++ )");
866 sc.add("{");
867 sc.indent();
868
869 sc.add("String id = (String) refs.get( \"" + association.getName() + ".\" + i );");
870 sc.add(to + " ref = (" + to + ") " + instanceFieldName + ".get( id );");
871 sc.add("if ( ref != null )");
872 sc.add("{");
873 sc.addIndented("value.get" + capAssocName + "().set( i, ref );");
874 sc.add("}");
875
876 sc.unindent();
877 sc.add("}");
878 }
879
880 sc.unindent();
881 sc.add("}");
882
883 sc.unindent();
884 sc.add("}");
885 }
886
887 if (child.isReferencableChildren()) {
888 ModelAssociation association = child.getAssociation();
889 if (association.isOneMultiplicity()) {
890 sc.add("resolveReferences( value.get" + capitalise(association.getName()) + "() );");
891 } else {
892 sc.add("for ( java.util.Iterator i = value.get" + capitalise(association.getName())
893 + "().iterator(); i.hasNext(); )");
894 sc.add("{");
895 sc.addIndented("resolveReferences( (" + association.getTo() + ") i.next() );");
896 sc.add("}");
897 }
898 }
899 }
900
901 jClass.addMethod(unmarshall);
902 }
903
904 private static String getRefFieldName(ModelAssociation association) {
905 return uncapitalise(association.getTo()) + "References";
906 }
907
908 private static String getInstanceFieldName(String to) {
909 return uncapitalise(to) + "Instances";
910 }
911
912
913
914
915
916
917
918
919
920 private void writeAttributes(ModelClass modelClass, String uncapClassName, JSourceCode sc) throws ModelloException {
921 for (ModelField field : modelClass.getAllFields(getGeneratedVersion(), true)) {
922 XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
923
924 if (xmlFieldMetadata.isAttribute() && !xmlFieldMetadata.isTransient()) {
925 writePrimitiveField(field, field.getType(), uncapClassName, "set" + capitalise(field.getName()), sc);
926 }
927 }
928 }
929
930
931
932
933
934
935
936
937
938
939
940
941
942 private void processField(
943 ModelField field,
944 XmlFieldMetadata xmlFieldMetadata,
945 boolean addElse,
946 JSourceCode sc,
947 String objectName,
948 boolean rootElement,
949 JClass jClass)
950 throws ModelloException {
951 String fieldTagName = resolveTagName(field, xmlFieldMetadata);
952
953 String capFieldName = capitalise(field.getName());
954
955 String singularName = singular(field.getName());
956
957 String alias;
958 if (StringUtils.isEmpty(field.getAlias())) {
959 alias = "null";
960 } else {
961 alias = "\"" + field.getAlias() + "\"";
962 }
963
964 String tagComparison = (addElse ? "else " : "") + "if ( checkFieldWithDuplicate( xmlStreamReader, \""
965 + fieldTagName + "\", " + alias + ", parsed ) )";
966
967 if (!(field instanceof ModelAssociation)) {
968 sc.add(tagComparison);
969
970 sc.add("{");
971 sc.indent();
972
973
974 writePrimitiveField(field, field.getType(), objectName, "set" + capFieldName, sc);
975
976 if (rootElement && field.isModelVersionField()) {
977 sc.add("String modelVersion = " + objectName + ".get" + capFieldName + "();");
978
979 writeModelVersionCheck(sc);
980 }
981
982 sc.unindent();
983 sc.add("}");
984 } else {
985 ModelAssociation association = (ModelAssociation) field;
986
987 String associationName = association.getName();
988
989 if (association.isOneMultiplicity()) {
990 sc.add(tagComparison);
991
992 sc.add("{");
993 sc.indent();
994
995 ModelField referenceIdentifierField = getReferenceIdentifierField(association);
996
997 if (referenceIdentifierField != null) {
998 addCodeToAddReferences(association, jClass, sc, referenceIdentifierField, objectName);
999
1000
1001 sc.add("while ( xmlStreamReader.getEventType() != XMLStreamConstants.END_ELEMENT )");
1002 sc.add("{");
1003 sc.addIndented("xmlStreamReader.next();");
1004 sc.add("}");
1005 } else {
1006 sc.add(objectName + ".set" + capFieldName + "( parse" + association.getTo()
1007 + "( xmlStreamReader, strict ) );");
1008 }
1009
1010 sc.unindent();
1011 sc.add("}");
1012 } else {
1013
1014
1015 XmlAssociationMetadata xmlAssociationMetadata =
1016 (XmlAssociationMetadata) association.getAssociationMetadata(XmlAssociationMetadata.ID);
1017
1018 String valuesTagName = resolveTagName(fieldTagName, xmlAssociationMetadata);
1019
1020 String type = association.getType();
1021
1022 boolean wrappedItems = xmlAssociationMetadata.isWrappedItems();
1023
1024 if (ModelDefault.LIST.equals(type) || ModelDefault.SET.equals(type)) {
1025 JavaFieldMetadata javaFieldMetadata =
1026 (JavaFieldMetadata) association.getMetadata(JavaFieldMetadata.ID);
1027 JavaAssociationMetadata javaAssociationMetadata =
1028 (JavaAssociationMetadata) association.getAssociationMetadata(JavaAssociationMetadata.ID);
1029
1030 String adder;
1031
1032 if (wrappedItems) {
1033 sc.add(tagComparison);
1034
1035 sc.add("{");
1036 sc.indent();
1037
1038 if (javaFieldMetadata.isSetter()) {
1039 sc.add(type + " " + associationName + " = " + association.getDefaultValue() + ";");
1040
1041 sc.add(objectName + ".set" + capFieldName + "( " + associationName + " );");
1042
1043 adder = associationName + ".add";
1044 } else {
1045 adder = objectName + ".add" + association.getTo();
1046 }
1047
1048 sc.add("while ( xmlStreamReader.nextTag() == XMLStreamConstants.START_ELEMENT )");
1049
1050 sc.add("{");
1051 sc.indent();
1052
1053 sc.add("if ( \"" + valuesTagName + "\".equals( xmlStreamReader.getLocalName() ) )");
1054
1055 sc.add("{");
1056 sc.indent();
1057 } else {
1058 sc.add((addElse ? "else " : "") + "if ( \"" + valuesTagName
1059 + "\".equals( xmlStreamReader.getLocalName() ) )");
1060
1061 sc.add("{");
1062 sc.indent();
1063
1064 if (javaFieldMetadata.isGetter() && javaFieldMetadata.isSetter()) {
1065 sc.add(type + " " + associationName + " = " + objectName + ".get" + capFieldName + "();");
1066
1067 sc.add("if ( " + associationName + " == null )");
1068
1069 sc.add("{");
1070 sc.indent();
1071
1072 sc.add(associationName + " = " + association.getDefaultValue() + ";");
1073
1074 sc.add(objectName + ".set" + capFieldName + "( " + associationName + " );");
1075
1076 sc.unindent();
1077 sc.add("}");
1078
1079 adder = associationName + ".add";
1080 } else {
1081 adder = objectName + ".add" + association.getTo();
1082 }
1083 }
1084
1085 if (isClassInModel(
1086 association.getTo(), field.getModelClass().getModel())) {
1087 ModelField referenceIdentifierField = getReferenceIdentifierField(association);
1088
1089 if (referenceIdentifierField != null) {
1090 addCodeToAddReferences(association, jClass, sc, referenceIdentifierField, objectName);
1091 }
1092
1093 if (association.getTo().equals(field.getModelClass().getName())
1094 || !javaAssociationMetadata.isAdder()) {
1095
1096
1097
1098
1099 sc.add(adder + "( parse" + association.getTo() + "( xmlStreamReader, strict ) );");
1100 } else {
1101 sc.add(objectName + ".add" + capitalise(singular(associationName)) + "( parse"
1102 + association.getTo() + "( xmlStreamReader, strict ) );");
1103 }
1104 } else {
1105 writePrimitiveField(association, association.getTo(), associationName, "add", sc);
1106 }
1107
1108 if (wrappedItems) {
1109 sc.unindent();
1110 sc.add("}");
1111
1112 sc.add("else");
1113
1114 sc.add("{");
1115 sc.addIndented("throw new XMLStreamException( \"Unrecognised tag: '\" + "
1116 + "xmlStreamReader.getLocalName() + \"'\", xmlStreamReader.getLocation() );");
1117 sc.add("}");
1118
1119 sc.unindent();
1120 sc.add("}");
1121
1122 sc.unindent();
1123 sc.add("}");
1124 } else {
1125
1126 sc.unindent();
1127 sc.add("}");
1128 }
1129 } else {
1130
1131
1132 sc.add(tagComparison);
1133
1134 sc.add("{");
1135 sc.indent();
1136
1137 if (xmlAssociationMetadata.isMapExplode()) {
1138 sc.add("while ( xmlStreamReader.nextTag() == XMLStreamConstants.START_ELEMENT )");
1139
1140 sc.add("{");
1141 sc.indent();
1142
1143 sc.add("if ( \"" + valuesTagName + "\".equals( xmlStreamReader.getLocalName() ) )");
1144
1145 sc.add("{");
1146 sc.indent();
1147
1148 sc.add("String key = null;");
1149
1150 sc.add("String value = null;");
1151
1152 sc.add("// " + xmlAssociationMetadata.getMapStyle() + " mode.");
1153
1154 sc.add("while ( xmlStreamReader.nextTag() == XMLStreamConstants.START_ELEMENT )");
1155
1156 sc.add("{");
1157 sc.indent();
1158
1159 sc.add("if ( \"key\".equals( xmlStreamReader.getLocalName() ) )");
1160
1161 sc.add("{");
1162 sc.addIndented("key = xmlStreamReader.getElementText();");
1163 sc.add("}");
1164
1165 sc.add("else if ( \"value\".equals( xmlStreamReader.getLocalName() ) )");
1166
1167 sc.add("{");
1168 sc.addIndented("value = xmlStreamReader.getElementText()"
1169 + (xmlFieldMetadata.isTrim() ? ".trim()" : "") + ";");
1170 sc.add("}");
1171
1172 sc.add("else");
1173
1174 sc.add("{");
1175 sc.addIndented("xmlStreamReader.getText();");
1176 sc.add("}");
1177
1178 sc.unindent();
1179 sc.add("}");
1180
1181 sc.add(objectName + ".add" + capitalise(singularName) + "( key, value );");
1182
1183 sc.unindent();
1184 sc.add("}");
1185
1186 sc.add("xmlStreamReader.next();");
1187
1188 sc.unindent();
1189 sc.add("}");
1190 } else {
1191
1192
1193 sc.add("while ( xmlStreamReader.nextTag() == XMLStreamConstants.START_ELEMENT )");
1194
1195 sc.add("{");
1196 sc.indent();
1197
1198 sc.add("String key = xmlStreamReader.getLocalName();");
1199
1200 sc.add("String value = xmlStreamReader.getElementText()"
1201 + (xmlFieldMetadata.isTrim() ? ".trim()" : "") + ";");
1202
1203 sc.add(objectName + ".add" + capitalise(singularName) + "( key, value );");
1204
1205 sc.unindent();
1206 sc.add("}");
1207 }
1208
1209 sc.unindent();
1210 sc.add("}");
1211 }
1212 }
1213 }
1214 }
1215
1216 private static void addCodeToAddReferences(
1217 ModelAssociation association,
1218 JClass jClass,
1219 JSourceCode sc,
1220 ModelField referenceIdentifierField,
1221 String referredFromClass) {
1222 String refFieldName = getRefFieldName(association);
1223 if (jClass.getField(refFieldName) == null) {
1224 jClass.addField(new JField(new JType("java.util.Map"), refFieldName));
1225 }
1226
1227 sc.add("String value = xmlStreamReader.getAttributeValue( null, \"" + referenceIdentifierField.getName()
1228 + "\" );");
1229 sc.add("if ( value != null )");
1230 sc.add("{");
1231 sc.indent();
1232
1233 sc.add("// This is a reference to an element elsewhere in the model");
1234 sc.add("if ( " + refFieldName + " == null )");
1235 sc.add("{");
1236 sc.addIndented(refFieldName + " = new java.util.HashMap();");
1237 sc.add("}");
1238
1239 sc.add("java.util.Map refs = (java.util.Map) " + refFieldName + ".get( " + referredFromClass + " );");
1240 sc.add("if ( refs == null )");
1241 sc.add("{");
1242 sc.indent();
1243
1244 sc.add("refs = new java.util.HashMap();");
1245 sc.add(refFieldName + ".put( " + referredFromClass + ", refs );");
1246
1247 sc.unindent();
1248 sc.add("}");
1249
1250 if (association.isOneMultiplicity()) {
1251 sc.add("refs.put( \"" + association.getName() + "\", value );");
1252 } else {
1253 sc.add("refs.put( \"" + association.getName() + ".\" + " + association.getName() + ".size(), value );");
1254 }
1255
1256 sc.unindent();
1257 sc.add("}");
1258 }
1259
1260 private void writeModelVersionCheck(JSourceCode sc) {
1261 writeModelVersionHack(sc);
1262
1263 sc.add("if ( !\"" + getGeneratedVersion() + "\".equals( modelVersion ) )");
1264 sc.add("{");
1265 sc.addIndented(
1266 "throw new XMLStreamException( \"Document model version of '\" + modelVersion + \"' doesn't match reader "
1267 + "version of '" + getGeneratedVersion() + "'\", xmlStreamReader.getLocation() );");
1268 sc.add("}");
1269 }
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281 private void writePrimitiveField(
1282 ModelField field, String type, String objectName, String setterName, JSourceCode sc) {
1283 XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata(XmlFieldMetadata.ID);
1284
1285 String tagName = resolveTagName(field, xmlFieldMetadata);
1286
1287 String parserGetter;
1288 if (xmlFieldMetadata.isAttribute()) {
1289 parserGetter = "xmlStreamReader.getAttributeValue( null, \"" + tagName + "\" )";
1290 } else {
1291 parserGetter = "xmlStreamReader.getElementText()";
1292 }
1293
1294
1295
1296
1297
1298
1299
1300 if (field.getDefaultValue() != null) {
1301 parserGetter = "getDefaultValue( " + parserGetter + ", \"" + field.getDefaultValue() + "\" )";
1302 }
1303
1304 if (xmlFieldMetadata.isTrim()) {
1305 parserGetter = "getTrimmedValue( " + parserGetter + " )";
1306 }
1307
1308 if ("boolean".equals(type) || "Boolean".equals(type)) {
1309 sc.add(objectName + "." + setterName + "( getBooleanValue( " + parserGetter + ", \"" + tagName
1310 + "\", xmlStreamReader ) );");
1311 } else if ("char".equals(type)) {
1312 sc.add(objectName + "." + setterName + "( getCharacterValue( " + parserGetter + ", \"" + tagName
1313 + "\", xmlStreamReader ) );");
1314 } else if ("double".equals(type)) {
1315 sc.add(objectName + "." + setterName + "( getDoubleValue( " + parserGetter + ", \"" + tagName
1316 + "\", xmlStreamReader, strict ) );");
1317 } else if ("float".equals(type)) {
1318 sc.add(objectName + "." + setterName + "( getFloatValue( " + parserGetter + ", \"" + tagName
1319 + "\", xmlStreamReader, strict ) );");
1320 } else if ("int".equals(type)) {
1321 sc.add(objectName + "." + setterName + "( getIntegerValue( " + parserGetter + ", \"" + tagName
1322 + "\", xmlStreamReader, strict ) );");
1323 } else if ("long".equals(type)) {
1324 sc.add(objectName + "." + setterName + "( getLongValue( " + parserGetter + ", \"" + tagName
1325 + "\", xmlStreamReader, strict ) );");
1326 } else if ("short".equals(type)) {
1327 sc.add(objectName + "." + setterName + "( getShortValue( " + parserGetter + ", \"" + tagName
1328 + "\", xmlStreamReader, strict ) );");
1329 } else if ("byte".equals(type)) {
1330 sc.add(objectName + "." + setterName + "( getByteValue( " + parserGetter + ", \"" + tagName
1331 + "\", xmlStreamReader, strict ) );");
1332 } else if ("String".equals(type)) {
1333
1334 sc.add(objectName + "." + setterName + "( " + parserGetter + " );");
1335 } else if ("Date".equals(type)) {
1336 sc.add("String dateFormat = "
1337 + (xmlFieldMetadata.getFormat() != null ? "\"" + xmlFieldMetadata.getFormat() + "\"" : "null")
1338 + ";");
1339 sc.add(objectName + "." + setterName + "( getDateValue( " + parserGetter + ", \"" + tagName
1340 + "\", dateFormat, xmlStreamReader ) );");
1341 } else if ("DOM".equals(type)) {
1342 sc.add(objectName + "." + setterName + "( buildDom( xmlStreamReader, " + xmlFieldMetadata.isTrim()
1343 + " ) );");
1344
1345 requiresDomSupport = true;
1346 } else {
1347 throw new IllegalArgumentException("Unknown type: " + type);
1348 }
1349 }
1350
1351 private void writeBuildDomMethod(JClass jClass) {
1352 if (domAsXpp3) {
1353 jClass.addImport("org.codehaus.plexus.util.xml.Xpp3Dom");
1354 } else {
1355 jClass.addField(new JField(new JClass("org.w3c.dom.Document"), "_doc_"));
1356 JMethod method = new JMethod("initDoc", null, null);
1357 method.getModifiers().makePrivate();
1358 method.addException(new JClass("javax.xml.parsers.ParserConfigurationException"));
1359
1360 JSourceCode sc = method.getSourceCode();
1361 sc.add(
1362 "javax.xml.parsers.DocumentBuilderFactory dbfac = javax.xml.parsers.DocumentBuilderFactory.newInstance();");
1363 sc.add("javax.xml.parsers.DocumentBuilder docBuilder = dbfac.newDocumentBuilder();");
1364 sc.add("_doc_ = docBuilder.newDocument();");
1365 jClass.addMethod(method);
1366 }
1367 String type = domAsXpp3 ? "Xpp3Dom" : "org.w3c.dom.Element";
1368 JMethod method = new JMethod("buildDom", new JType(type), null);
1369 method.getModifiers().makePrivate();
1370 method.addParameter(new JParameter(new JType("XMLStreamReader"), "xmlStreamReader"));
1371 method.addParameter(new JParameter(JType.BOOLEAN, "trim"));
1372 method.addException(new JClass("XMLStreamException"));
1373
1374 JSourceCode sc = method.getSourceCode();
1375
1376 sc.add("java.util.Stack elements = new java.util.Stack();");
1377
1378 sc.add("java.util.Stack values = new java.util.Stack();");
1379
1380 sc.add("int eventType = xmlStreamReader.getEventType();");
1381
1382 sc.add("boolean spacePreserve = false;");
1383
1384 sc.add("while ( xmlStreamReader.hasNext() )");
1385 sc.add("{");
1386 sc.indent();
1387
1388 sc.add("if ( eventType == XMLStreamConstants.START_ELEMENT )");
1389 sc.add("{");
1390 sc.indent();
1391 sc.add("spacePreserve = false;");
1392 sc.add("String rawName = xmlStreamReader.getLocalName();");
1393
1394 if (domAsXpp3) {
1395 sc.add("Xpp3Dom element = new Xpp3Dom( rawName );");
1396 } else {
1397 sc.add("org.w3c.dom.Element element = _doc_.createElement( rawName );");
1398 }
1399
1400 sc.add("if ( !elements.empty() )");
1401 sc.add("{");
1402 sc.indent();
1403 sc.add(type + " parent = (" + type + ") elements.peek();");
1404
1405 sc.add("parent." + (domAsXpp3 ? "addChild" : "appendChild") + "( element );");
1406 sc.unindent();
1407 sc.add("}");
1408
1409 sc.add("elements.push( element );");
1410
1411 sc.add("if ( xmlStreamReader.isEndElement() )");
1412 sc.add("{");
1413 sc.addIndented("values.push( null );");
1414 sc.add("}");
1415 sc.add("else");
1416 sc.add("{");
1417 sc.addIndented("values.push( new StringBuilder() );");
1418 sc.add("}");
1419
1420 sc.add("int attributesSize = xmlStreamReader.getAttributeCount();");
1421
1422 sc.add("for ( int i = 0; i < attributesSize; i++ )");
1423 sc.add("{");
1424 sc.indent();
1425 sc.add("String prefix = xmlStreamReader.getAttributePrefix( i );");
1426 sc.add("String localName = xmlStreamReader.getAttributeLocalName( i );");
1427 sc.add("String value = xmlStreamReader.getAttributeValue( i );");
1428 sc.add("if ( XMLConstants.DEFAULT_NS_PREFIX.equals( xmlStreamReader.getAttributeName( i ).getPrefix() ) )");
1429 sc.add("{");
1430 sc.addIndented("element.setAttribute( localName, value );");
1431 sc.add("}");
1432 sc.add("else");
1433 sc.add("{");
1434 sc.addIndented("element.setAttribute( prefix + ':'+ localName , value );");
1435 sc.add("}");
1436 sc.add(
1437 "spacePreserve = spacePreserve || ( \"xml\".equals( prefix ) && \"space\".equals( localName ) && \"preserve\".equals( value ) );");
1438 sc.unindent();
1439 sc.add("}");
1440 sc.unindent();
1441 sc.add("}");
1442 sc.add("else if ( eventType == XMLStreamConstants.CHARACTERS )");
1443 sc.add("{");
1444 sc.indent();
1445 sc.add("StringBuilder valueBuffer = (StringBuilder) values.peek();");
1446
1447 sc.add("String text = xmlStreamReader.getText();");
1448
1449 sc.add("if ( trim && !spacePreserve )");
1450 sc.add("{");
1451 sc.addIndented("text = text.trim();");
1452 sc.add("}");
1453
1454 sc.add("valueBuffer.append( text );");
1455 sc.unindent();
1456 sc.add("}");
1457 sc.add("else if ( eventType == XMLStreamConstants.END_ELEMENT )");
1458 sc.add("{");
1459 sc.indent();
1460
1461 sc.add(type + " element = (" + type + ") elements.pop();");
1462
1463 sc.add("// this Object could be null if it is a singleton tag");
1464 sc.add("Object accumulatedValue = values.pop();");
1465
1466 sc.add("if ( " + (domAsXpp3 ? "element.getChildCount() == 0" : "!element.hasChildNodes()") + " )");
1467 sc.add("{");
1468 sc.addIndented("element." + (domAsXpp3 ? "setValue" : "setTextContent")
1469 + "( ( accumulatedValue == null ) ? null : accumulatedValue.toString() );");
1470 sc.add("}");
1471
1472 sc.add("if ( values.empty() )");
1473 sc.add("{");
1474 sc.addIndented("return element;");
1475 sc.add("}");
1476 sc.unindent();
1477 sc.add("}");
1478
1479 sc.add("eventType = xmlStreamReader.next();");
1480
1481 sc.unindent();
1482 sc.add("}");
1483
1484 sc.add("throw new IllegalStateException( \"End of document found before returning to 0 depth\" );");
1485
1486 jClass.addMethod(method);
1487 }
1488
1489 private void writeHelpers(JClass jClass) {
1490 JMethod method = new JMethod("getTrimmedValue", new JClass("String"), null);
1491 method.getModifiers().makePrivate();
1492
1493 method.addParameter(new JParameter(new JClass("String"), "s"));
1494
1495 JSourceCode sc = method.getSourceCode();
1496
1497 sc.add("if ( s != null )");
1498
1499 sc.add("{");
1500 sc.addIndented("s = s.trim();");
1501 sc.add("}");
1502
1503 sc.add("return s;");
1504
1505 jClass.addMethod(method);
1506
1507
1508
1509 method = new JMethod("getDefaultValue", new JClass("String"), null);
1510 method.getModifiers().makePrivate();
1511
1512 method.addParameter(new JParameter(new JClass("String"), "s"));
1513 method.addParameter(new JParameter(new JClass("String"), "v"));
1514
1515 sc = method.getSourceCode();
1516
1517 sc.add("if ( s == null )");
1518
1519 sc.add("{");
1520 sc.addIndented("s = v;");
1521 sc.add("}");
1522
1523 sc.add("return s;");
1524
1525 jClass.addMethod(method);
1526
1527
1528
1529 method = new JMethod("getRequiredAttributeValue", new JClass("String"), null);
1530 method.addException(new JClass("XMLStreamException"));
1531 method.getModifiers().makePrivate();
1532
1533 method.addParameter(new JParameter(new JClass("String"), "s"));
1534 method.addParameter(new JParameter(new JClass("String"), "attribute"));
1535 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1536 method.addParameter(new JParameter(JType.BOOLEAN, "strict"));
1537
1538 sc = method.getSourceCode();
1539
1540 sc.add("if ( s == null )");
1541
1542 sc.add("{");
1543 sc.indent();
1544
1545 sc.add("if ( strict )");
1546
1547 sc.add("{");
1548 sc.addIndented("throw new XMLStreamException( \"Missing required value for attribute '\" + attribute + \"'\", "
1549 + "xmlStreamReader.getLocation() );");
1550 sc.add("}");
1551
1552 sc.unindent();
1553 sc.add("}");
1554
1555 sc.add("return s;");
1556
1557 jClass.addMethod(method);
1558
1559
1560
1561 method = new JMethod("getBooleanValue", JType.BOOLEAN, null);
1562 method.addException(new JClass("XMLStreamException"));
1563 method.getModifiers().makePrivate();
1564
1565 method.addParameter(new JParameter(new JClass("String"), "s"));
1566 method.addParameter(new JParameter(new JClass("String"), "attribute"));
1567 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1568
1569 sc = method.getSourceCode();
1570
1571 sc.add("if ( s != null )");
1572
1573 sc.add("{");
1574 sc.addIndented("return Boolean.valueOf( s ).booleanValue();");
1575 sc.add("}");
1576
1577 sc.add("return false;");
1578
1579 jClass.addMethod(method);
1580
1581
1582
1583 method = new JMethod("getCharacterValue", JType.CHAR, null);
1584 method.addException(new JClass("XMLStreamException"));
1585 method.getModifiers().makePrivate();
1586
1587 method.addParameter(new JParameter(new JClass("String"), "s"));
1588 method.addParameter(new JParameter(new JClass("String"), "attribute"));
1589 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1590
1591 sc = method.getSourceCode();
1592
1593 sc.add("if ( s != null )");
1594
1595 sc.add("{");
1596 sc.addIndented("return s.charAt( 0 );");
1597 sc.add("}");
1598
1599 sc.add("return 0;");
1600
1601 jClass.addMethod(method);
1602
1603
1604
1605 method = convertNumericalType("getIntegerValue", JType.INT, "Integer.valueOf( s ).intValue()", "an integer");
1606
1607 jClass.addMethod(method);
1608
1609
1610
1611 method = convertNumericalType(
1612 "getShortValue", JType.SHORT, "Short.valueOf( s ).shortValue()", "a short integer");
1613
1614 jClass.addMethod(method);
1615
1616
1617
1618 method = convertNumericalType("getByteValue", JType.BYTE, "Byte.valueOf( s ).byteValue()", "a byte");
1619
1620 jClass.addMethod(method);
1621
1622
1623
1624 method = convertNumericalType("getLongValue", JType.LONG, "Long.valueOf( s ).longValue()", "a long integer");
1625
1626 jClass.addMethod(method);
1627
1628
1629
1630 method = convertNumericalType(
1631 "getFloatValue", JType.FLOAT, "Float.valueOf( s ).floatValue()", "a floating point number");
1632
1633 jClass.addMethod(method);
1634
1635
1636
1637 method = convertNumericalType(
1638 "getDoubleValue", JType.DOUBLE, "Double.valueOf( s ).doubleValue()", "a floating point number");
1639
1640 jClass.addMethod(method);
1641
1642
1643
1644 method = new JMethod("getDateValue", new JClass("java.util.Date"), null);
1645 method.addException(new JClass("XMLStreamException"));
1646 method.getModifiers().makePrivate();
1647
1648 method.addParameter(new JParameter(new JClass("String"), "s"));
1649 method.addParameter(new JParameter(new JClass("String"), "attribute"));
1650 method.addParameter(new JParameter(new JClass("String"), "dateFormat"));
1651 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1652 method.addException(new JClass("XMLStreamException"));
1653
1654 writeDateParsingHelper(
1655 method.getSourceCode(), "new XMLStreamException( e.getMessage(), xmlStreamReader.getLocation(), e )");
1656
1657 jClass.addMethod(method);
1658
1659
1660
1661 method = new JMethod("checkFieldWithDuplicate", JType.BOOLEAN, null);
1662 method.getModifiers().makePrivate();
1663
1664 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1665 method.addParameter(new JParameter(new JClass("String"), "tagName"));
1666 method.addParameter(new JParameter(new JClass("String"), "alias"));
1667 method.addParameter(new JParameter(new JClass("java.util.Set"), "parsed"));
1668 method.addException(new JClass("XMLStreamException"));
1669
1670 sc = method.getSourceCode();
1671
1672 sc.add("if ( !( xmlStreamReader.getLocalName().equals( tagName ) ||"
1673 + " xmlStreamReader.getLocalName().equals( alias ) ) )");
1674
1675 sc.add("{");
1676 sc.addIndented("return false;");
1677 sc.add("}");
1678
1679 sc.add("if ( !parsed.add( tagName ) )");
1680
1681 sc.add("{");
1682 sc.addIndented(
1683 "throw new XMLStreamException( \"Duplicated tag: '\" + tagName + \"'\", xmlStreamReader.getLocation() );");
1684 sc.add("}");
1685
1686 sc.add("return true;");
1687
1688 jClass.addMethod(method);
1689
1690
1691
1692 method = new JMethod("checkUnknownElement", null, null);
1693 method.getModifiers().makePrivate();
1694
1695 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1696 method.addParameter(new JParameter(JType.BOOLEAN, "strict"));
1697 method.addException(new JClass("XMLStreamException"));
1698
1699 sc = method.getSourceCode();
1700
1701 sc.add("if ( strict )");
1702
1703 sc.add("{");
1704 sc.addIndented("throw new XMLStreamException( \"Unrecognised tag: '\" + xmlStreamReader.getLocalName() + "
1705 + "\"'\", xmlStreamReader.getLocation() );");
1706 sc.add("}");
1707
1708 sc.add("int unrecognizedTagCount = 1;");
1709 sc.add("while( unrecognizedTagCount != 0 )");
1710
1711 sc.add("{");
1712 sc.indent();
1713
1714 sc.add("xmlStreamReader.next();");
1715 sc.add("if ( xmlStreamReader.getEventType() == XMLStreamConstants.START_ELEMENT )");
1716
1717 sc.add("{");
1718 sc.addIndented("unrecognizedTagCount++;");
1719 sc.add("}");
1720
1721 sc.add("else if ( xmlStreamReader.getEventType() == XMLStreamConstants.END_ELEMENT )");
1722 sc.add("{");
1723 sc.addIndented("unrecognizedTagCount--;");
1724 sc.add("}");
1725
1726 sc.unindent();
1727 sc.add("}");
1728
1729 jClass.addMethod(method);
1730
1731
1732
1733 method = new JMethod("nextTag", JType.INT, null);
1734 method.getModifiers().makePrivate();
1735
1736 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1737 method.addException(new JClass("XMLStreamException"));
1738
1739 sc = method.getSourceCode();
1740
1741 sc.add("while ( true )");
1742 sc.add("{");
1743 sc.indent();
1744 sc.add("int eventType = xmlStreamReader.next();");
1745 sc.add("switch ( eventType )");
1746 sc.add("{");
1747 sc.indent();
1748 sc.add("case XMLStreamConstants.CHARACTERS:");
1749 sc.add("case XMLStreamConstants.CDATA:");
1750 sc.add("case XMLStreamConstants.SPACE:");
1751 sc.add("case XMLStreamConstants.PROCESSING_INSTRUCTION:");
1752 sc.add("case XMLStreamConstants.COMMENT:");
1753 sc.addIndented("break;");
1754 sc.add("case XMLStreamConstants.START_ELEMENT:");
1755 sc.add("case XMLStreamConstants.END_ELEMENT:");
1756 sc.addIndented("return eventType;");
1757 sc.add("default:");
1758 sc.addIndented("throw new XMLStreamException( \"expected start or end tag\", xmlStreamReader.getLocation() );");
1759 sc.unindent();
1760 sc.add("}");
1761 sc.unindent();
1762 sc.add("}");
1763
1764 jClass.addMethod(method);
1765 }
1766
1767 private JMethod convertNumericalType(String methodName, JType returnType, String expression, String typeDesc) {
1768 JMethod method = new JMethod(methodName, returnType, null);
1769 method.addException(new JClass("XMLStreamException"));
1770 method.getModifiers().makePrivate();
1771
1772 method.addParameter(new JParameter(new JClass("String"), "s"));
1773 method.addParameter(new JParameter(new JClass("String"), "attribute"));
1774 method.addParameter(new JParameter(new JClass("XMLStreamReader"), "xmlStreamReader"));
1775 method.addParameter(new JParameter(JType.BOOLEAN, "strict"));
1776
1777 JSourceCode sc = method.getSourceCode();
1778
1779 sc.add("if ( s != null )");
1780
1781 sc.add("{");
1782 sc.indent();
1783
1784 sc.add("try");
1785
1786 sc.add("{");
1787 sc.addIndented("return " + expression + ";");
1788 sc.add("}");
1789
1790 sc.add("catch ( NumberFormatException nfe )");
1791
1792 sc.add("{");
1793 sc.indent();
1794
1795 sc.add("if ( strict )");
1796
1797 sc.add("{");
1798 sc.addIndented("throw new XMLStreamException( \"Unable to parse element '\" + attribute + \"', must be "
1799 + typeDesc + " but was '\" + s + \"'\", xmlStreamReader.getLocation(), nfe );");
1800 sc.add("}");
1801
1802 sc.unindent();
1803 sc.add("}");
1804
1805 sc.unindent();
1806 sc.add("}");
1807
1808 sc.add("return 0;");
1809
1810 return method;
1811 }
1812 }