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