| #* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| *# |
| #parse ( "common.vm" ) |
| # |
| #set ( $package = "${packageToolV4}" ) |
| #set ( $className = "${model.name}StaxReader" ) |
| # |
| #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) |
| #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) |
| #set ( $rootTag = $rootXml.tagName ) |
| #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) |
| #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) |
| # |
| #set ( $needXmlContext = false ) |
| #foreach ( $class in $model.allClasses ) |
| #set ( $allFields = $Helper.xmlFields( $class ) ) |
| #foreach ( $field in $allFields ) |
| #if ( $Helper.xmlFieldMetadata( $field ).format ) |
| #set ( $needXmlContext = true ) |
| #end |
| #end |
| #end |
| # |
| #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java |
| // =================== DO NOT EDIT THIS FILE ==================== |
| // Generated by Modello Velocity from ${template} |
| // template, any modifications will be overwritten. |
| // ============================================================== |
| package ${package}; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.text.DateFormat; |
| #if ( $needXmlContext ) |
| import java.util.ArrayDeque; |
| #end |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| #if ( $needXmlContext ) |
| import java.util.Deque; |
| #end |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import org.apache.maven.api.annotations.Generated; |
| #if ( $locationTracking ) |
| import ${packageModelV4}.InputSource; |
| import ${packageModelV4}.InputLocation; |
| #end |
| #foreach ( $class in $model.allClasses ) |
| import ${packageModelV4}.${class.name}; |
| #end |
| import org.apache.maven.internal.xml.XmlNodeBuilder; |
| import org.apache.maven.api.xml.XmlNode; |
| import javax.xml.stream.XMLInputFactory; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamReader; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI; |
| import static javax.xml.XMLConstants.XML_NS_URI; |
| |
| @Generated |
| public class ${className} { |
| |
| private static final Map<String, String> DEFAULT_ENTITIES; |
| static { |
| Map<String, String> entities = new HashMap<>(); |
| entities.put("nbsp", "\u00a0"); |
| entities.put("iexcl", "\u00a1"); |
| entities.put("cent", "\u00a2"); |
| entities.put("pound", "\u00a3"); |
| entities.put("curren", "\u00a4"); |
| entities.put("yen", "\u00a5"); |
| entities.put("brvbar", "\u00a6"); |
| entities.put("sect", "\u00a7"); |
| entities.put("uml", "\u00a8"); |
| entities.put("copy", "\u00a9"); |
| entities.put("ordf", "\u00aa"); |
| entities.put("laquo", "\u00ab"); |
| entities.put("not", "\u00ac"); |
| entities.put("shy", "\u00ad"); |
| entities.put("reg", "\u00ae"); |
| entities.put("macr", "\u00af"); |
| entities.put("deg", "\u00b0"); |
| entities.put("plusmn", "\u00b1"); |
| entities.put("sup2", "\u00b2"); |
| entities.put("sup3", "\u00b3"); |
| entities.put("acute", "\u00b4"); |
| entities.put("micro", "\u00b5"); |
| entities.put("para", "\u00b6"); |
| entities.put("middot", "\u00b7"); |
| entities.put("cedil", "\u00b8"); |
| entities.put("sup1", "\u00b9"); |
| entities.put("ordm", "\u00ba"); |
| entities.put("raquo", "\u00bb"); |
| entities.put("frac14", "\u00bc"); |
| entities.put("frac12", "\u00bd"); |
| entities.put("frac34", "\u00be"); |
| entities.put("iquest", "\u00bf"); |
| entities.put("Agrave", "\u00c0"); |
| entities.put("Aacute", "\u00c1"); |
| entities.put("Acirc", "\u00c2"); |
| entities.put("Atilde", "\u00c3"); |
| entities.put("Auml", "\u00c4"); |
| entities.put("Aring", "\u00c5"); |
| entities.put("AElig", "\u00c6"); |
| entities.put("Ccedil", "\u00c7"); |
| entities.put("Egrave", "\u00c8"); |
| entities.put("Eacute", "\u00c9"); |
| entities.put("Ecirc", "\u00ca"); |
| entities.put("Euml", "\u00cb"); |
| entities.put("Igrave", "\u00cc"); |
| entities.put("Iacute", "\u00cd"); |
| entities.put("Icirc", "\u00ce"); |
| entities.put("Iuml", "\u00cf"); |
| entities.put("ETH", "\u00d0"); |
| entities.put("Ntilde", "\u00d1"); |
| entities.put("Ograve", "\u00d2"); |
| entities.put("Oacute", "\u00d3"); |
| entities.put("Ocirc", "\u00d4"); |
| entities.put("Otilde", "\u00d5"); |
| entities.put("Ouml", "\u00d6"); |
| entities.put("times", "\u00d7"); |
| entities.put("Oslash", "\u00d8"); |
| entities.put("Ugrave", "\u00d9"); |
| entities.put("Uacute", "\u00da"); |
| entities.put("Ucirc", "\u00db"); |
| entities.put("Uuml", "\u00dc"); |
| entities.put("Yacute", "\u00dd"); |
| entities.put("THORN", "\u00de"); |
| entities.put("szlig", "\u00df"); |
| entities.put("agrave", "\u00e0"); |
| entities.put("aacute", "\u00e1"); |
| entities.put("acirc", "\u00e2"); |
| entities.put("atilde", "\u00e3"); |
| entities.put("auml", "\u00e4"); |
| entities.put("aring", "\u00e5"); |
| entities.put("aelig", "\u00e6"); |
| entities.put("ccedil", "\u00e7"); |
| entities.put("egrave", "\u00e8"); |
| entities.put("eacute", "\u00e9"); |
| entities.put("ecirc", "\u00ea"); |
| entities.put("euml", "\u00eb"); |
| entities.put("igrave", "\u00ec"); |
| entities.put("iacute", "\u00ed"); |
| entities.put("icirc", "\u00ee"); |
| entities.put("iuml", "\u00ef"); |
| entities.put("eth", "\u00f0"); |
| entities.put("ntilde", "\u00f1"); |
| entities.put("ograve", "\u00f2"); |
| entities.put("oacute", "\u00f3"); |
| entities.put("ocirc", "\u00f4"); |
| entities.put("otilde", "\u00f5"); |
| entities.put("ouml", "\u00f6"); |
| entities.put("divide", "\u00f7"); |
| entities.put("oslash", "\u00f8"); |
| entities.put("ugrave", "\u00f9"); |
| entities.put("uacute", "\u00fa"); |
| entities.put("ucirc", "\u00fb"); |
| entities.put("uuml", "\u00fc"); |
| entities.put("yacute", "\u00fd"); |
| entities.put("thorn", "\u00fe"); |
| entities.put("yuml", "\u00ff"); |
| |
| // ---------------------------------------------------------------------- |
| // Special entities |
| // ---------------------------------------------------------------------- |
| |
| entities.put("OElig", "\u0152"); |
| entities.put("oelig", "\u0153"); |
| entities.put("Scaron", "\u0160"); |
| entities.put("scaron", "\u0161"); |
| entities.put("Yuml", "\u0178"); |
| entities.put("circ", "\u02c6"); |
| entities.put("tilde", "\u02dc"); |
| entities.put("ensp", "\u2002"); |
| entities.put("emsp", "\u2003"); |
| entities.put("thinsp", "\u2009"); |
| entities.put("zwnj", "\u200c"); |
| entities.put("zwj", "\u200d"); |
| entities.put("lrm", "\u200e"); |
| entities.put("rlm", "\u200f"); |
| entities.put("ndash", "\u2013"); |
| entities.put("mdash", "\u2014"); |
| entities.put("lsquo", "\u2018"); |
| entities.put("rsquo", "\u2019"); |
| entities.put("sbquo", "\u201a"); |
| entities.put("ldquo", "\u201c"); |
| entities.put("rdquo", "\u201d"); |
| entities.put("bdquo", "\u201e"); |
| entities.put("dagger", "\u2020"); |
| entities.put("Dagger", "\u2021"); |
| entities.put("permil", "\u2030"); |
| entities.put("lsaquo", "\u2039"); |
| entities.put("rsaquo", "\u203a"); |
| entities.put("euro", "\u20ac"); |
| |
| // ---------------------------------------------------------------------- |
| // Symbol entities |
| // ---------------------------------------------------------------------- |
| |
| entities.put("fnof", "\u0192"); |
| entities.put("Alpha", "\u0391"); |
| entities.put("Beta", "\u0392"); |
| entities.put("Gamma", "\u0393"); |
| entities.put("Delta", "\u0394"); |
| entities.put("Epsilon", "\u0395"); |
| entities.put("Zeta", "\u0396"); |
| entities.put("Eta", "\u0397"); |
| entities.put("Theta", "\u0398"); |
| entities.put("Iota", "\u0399"); |
| entities.put("Kappa", "\u039a"); |
| entities.put("Lambda", "\u039b"); |
| entities.put("Mu", "\u039c"); |
| entities.put("Nu", "\u039d"); |
| entities.put("Xi", "\u039e"); |
| entities.put("Omicron", "\u039f"); |
| entities.put("Pi", "\u03a0"); |
| entities.put("Rho", "\u03a1"); |
| entities.put("Sigma", "\u03a3"); |
| entities.put("Tau", "\u03a4"); |
| entities.put("Upsilon", "\u03a5"); |
| entities.put("Phi", "\u03a6"); |
| entities.put("Chi", "\u03a7"); |
| entities.put("Psi", "\u03a8"); |
| entities.put("Omega", "\u03a9"); |
| entities.put("alpha", "\u03b1"); |
| entities.put("beta", "\u03b2"); |
| entities.put("gamma", "\u03b3"); |
| entities.put("delta", "\u03b4"); |
| entities.put("epsilon", "\u03b5"); |
| entities.put("zeta", "\u03b6"); |
| entities.put("eta", "\u03b7"); |
| entities.put("theta", "\u03b8"); |
| entities.put("iota", "\u03b9"); |
| entities.put("kappa", "\u03ba"); |
| entities.put("lambda", "\u03bb"); |
| entities.put("mu", "\u03bc"); |
| entities.put("nu", "\u03bd"); |
| entities.put("xi", "\u03be"); |
| entities.put("omicron", "\u03bf"); |
| entities.put("pi", "\u03c0"); |
| entities.put("rho", "\u03c1"); |
| entities.put("sigmaf", "\u03c2"); |
| entities.put("sigma", "\u03c3"); |
| entities.put("tau", "\u03c4"); |
| entities.put("upsilon", "\u03c5"); |
| entities.put("phi", "\u03c6"); |
| entities.put("chi", "\u03c7"); |
| entities.put("psi", "\u03c8"); |
| entities.put("omega", "\u03c9"); |
| entities.put("thetasym", "\u03d1"); |
| entities.put("upsih", "\u03d2"); |
| entities.put("piv", "\u03d6"); |
| entities.put("bull", "\u2022"); |
| entities.put("hellip", "\u2026"); |
| entities.put("prime", "\u2032"); |
| entities.put("Prime", "\u2033"); |
| entities.put("oline", "\u203e"); |
| entities.put("frasl", "\u2044"); |
| entities.put("weierp", "\u2118"); |
| entities.put("image", "\u2111"); |
| entities.put("real", "\u211c"); |
| entities.put("trade", "\u2122"); |
| entities.put("alefsym", "\u2135"); |
| entities.put("larr", "\u2190"); |
| entities.put("uarr", "\u2191"); |
| entities.put("rarr", "\u2192"); |
| entities.put("darr", "\u2193"); |
| entities.put("harr", "\u2194"); |
| entities.put("crarr", "\u21b5"); |
| entities.put("lArr", "\u21d0"); |
| entities.put("uArr", "\u21d1"); |
| entities.put("rArr", "\u21d2"); |
| entities.put("dArr", "\u21d3"); |
| entities.put("hArr", "\u21d4"); |
| entities.put("forall", "\u2200"); |
| entities.put("part", "\u2202"); |
| entities.put("exist", "\u2203"); |
| entities.put("empty", "\u2205"); |
| entities.put("nabla", "\u2207"); |
| entities.put("isin", "\u2208"); |
| entities.put("notin", "\u2209"); |
| entities.put("ni", "\u220b"); |
| entities.put("prod", "\u220f"); |
| entities.put("sum", "\u2211"); |
| entities.put("minus", "\u2212"); |
| entities.put("lowast", "\u2217"); |
| entities.put("radic", "\u221a"); |
| entities.put("prop", "\u221d"); |
| entities.put("infin", "\u221e"); |
| entities.put("ang", "\u2220"); |
| entities.put("and", "\u2227"); |
| entities.put("or", "\u2228"); |
| entities.put("cap", "\u2229"); |
| entities.put("cup", "\u222a"); |
| entities.put("int", "\u222b"); |
| entities.put("there4", "\u2234"); |
| entities.put("sim", "\u223c"); |
| entities.put("cong", "\u2245"); |
| entities.put("asymp", "\u2248"); |
| entities.put("ne", "\u2260"); |
| entities.put("equiv", "\u2261"); |
| entities.put("le", "\u2264"); |
| entities.put("ge", "\u2265"); |
| entities.put("sub", "\u2282"); |
| entities.put("sup", "\u2283"); |
| entities.put("nsub", "\u2284"); |
| entities.put("sube", "\u2286"); |
| entities.put("supe", "\u2287"); |
| entities.put("oplus", "\u2295"); |
| entities.put("otimes", "\u2297"); |
| entities.put("perp", "\u22a5"); |
| entities.put("sdot", "\u22c5"); |
| entities.put("lceil", "\u2308"); |
| entities.put("rceil", "\u2309"); |
| entities.put("lfloor", "\u230a"); |
| entities.put("rfloor", "\u230b"); |
| entities.put("lang", "\u2329"); |
| entities.put("rang", "\u232a"); |
| entities.put("loz", "\u25ca"); |
| entities.put("spades", "\u2660"); |
| entities.put("clubs", "\u2663"); |
| entities.put("hearts", "\u2665"); |
| entities.put("diams", "\u2666"); |
| DEFAULT_ENTITIES = Collections.unmodifiableMap(entities); |
| } |
| |
| private boolean addDefaultEntities = true; |
| #if ( $locationTracking ) |
| private boolean addLocationInformation = true; |
| #end |
| |
| private final ContentTransformer contentTransformer; |
| |
| public ${className}() { |
| this((s, f) -> s); |
| } |
| |
| public ${className}(ContentTransformer contentTransformer) { |
| this.contentTransformer = contentTransformer; |
| } |
| |
| /** |
| * Returns the state of the "add default entities" flag. |
| * |
| * @return boolean |
| */ |
| public boolean getAddDefaultEntities() { |
| return addDefaultEntities; |
| } //-- boolean getAddDefaultEntities() |
| |
| /** |
| * Sets the state of the "add default entities" flag. |
| * |
| * @param addDefaultEntities a addDefaultEntities object. |
| */ |
| public void setAddDefaultEntities(boolean addDefaultEntities) { |
| this.addDefaultEntities = addDefaultEntities; |
| } //-- void setAddDefaultEntities(boolean) |
| |
| #if ( $locationTracking ) |
| /** |
| * Returns the state of the "add location information" flag. |
| * |
| * @return boolean |
| */ |
| public boolean getAddLocationInformation() { |
| return addLocationInformation; |
| } //-- boolean getAddLocationInformation() |
| |
| /** |
| * Sets the state of the "add location information" flag. |
| * |
| * @param addLocationInformation a addLocationInformation object. |
| */ |
| public void setAddLocationInformation(boolean addLocationInformation) { |
| this.addLocationInformation = addLocationInformation; |
| } //-- void setAddLocationInformation(boolean) |
| #end |
| |
| public ${root.name} read(Reader reader) throws XMLStreamException { |
| #if ( $locationTracking ) |
| return read(reader, true, null); |
| #else |
| return read(reader, true); |
| #end |
| } |
| |
| /** |
| * @param reader a reader object. |
| * @param strict a strict object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return ${root.name} |
| */ |
| #if ( $locationTracking ) |
| public ${root.name} read(Reader reader, boolean strict, InputSource source) throws XMLStreamException { |
| #else |
| public ${root.name} read(Reader reader, boolean strict) throws XMLStreamException { |
| #end |
| XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory(); |
| factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); |
| #if ( $locationTracking ) |
| StreamSource streamSource = new StreamSource(reader, source != null ? source.getLocation() : null); |
| #else |
| StreamSource streamSource = new StreamSource(reader); |
| #end |
| XMLStreamReader parser = factory.createXMLStreamReader(streamSource); |
| #if ( $locationTracking ) |
| return read(parser, strict, source); |
| #else |
| return read(parser, strict); |
| #end |
| } //-- ${root.name} read(Reader, boolean) |
| |
| public ${root.name} read(InputStream in) throws XMLStreamException { |
| #if ( $locationTracking ) |
| return read(in, true, null); |
| #else |
| return read(in, true); |
| #end |
| } |
| |
| /** |
| * Method read. |
| * |
| * @param in a in object. |
| * @param strict a strict object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return ${root.name} |
| */ |
| #if ( $locationTracking ) |
| public ${root.name} read(InputStream in, boolean strict, InputSource source) throws XMLStreamException { |
| #else |
| public ${root.name} read(InputStream in, boolean strict) throws XMLStreamException { |
| #end |
| XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory(); |
| factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); |
| #if ( $locationTracking ) |
| StreamSource streamSource = new StreamSource(in, source != null ? source.getLocation() : null); |
| #else |
| StreamSource streamSource = new StreamSource(in); |
| #end |
| XMLStreamReader parser = factory.createXMLStreamReader(streamSource); |
| #if ( $locationTracking ) |
| return read(parser, strict, source); |
| #else |
| return read(parser, strict); |
| #end |
| } //-- ${root.name} read(InputStream, boolean) |
| |
| /** |
| * Method read. |
| * |
| * @param parser a parser object. |
| * @param strict a strict object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return ${root.name} |
| */ |
| #if ( $locationTracking ) |
| public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException { |
| #else |
| public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException { |
| #end |
| #if ( $needXmlContext ) |
| Deque<Object> context = new ArrayDeque<>(); |
| #end |
| $rootUcapName $rootLcapName = null; |
| int eventType = parser.getEventType(); |
| boolean parsed = false; |
| while (eventType != XMLStreamReader.END_DOCUMENT) { |
| if (eventType == XMLStreamReader.START_ELEMENT) { |
| if (strict && ! "${rootTag}".equals(parser.getLocalName())) { |
| throw new XMLStreamException("Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser.getLocation(), null); |
| } else if (parsed) { |
| // fallback, already expected a XMLStreamException due to invalid XML |
| throw new XMLStreamException("Duplicated tag: '${rootTag}'", parser.getLocation(), null); |
| } |
| #if ( $locationTracking ) |
| $rootLcapName = parse${rootUcapName}(parser, strict, source); |
| #elseif ( $needXmlContext ) |
| $rootLcapName = parse${rootUcapName}(parser, strict, context); |
| #else |
| $rootLcapName = parse${rootUcapName}(parser, strict); |
| #end |
| parsed = true; |
| } |
| eventType = parser.next(); |
| } |
| if (parsed) { |
| return $rootLcapName; |
| } |
| throw new XMLStreamException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser.getLocation(), null); |
| } //-- ${root.name} read(XMLStreamReader, boolean) |
| |
| #foreach ( $class in $model.allClasses ) |
| #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) |
| #set ( $classUcapName = $Helper.capitalise( $class.name ) ) |
| #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) |
| #set ( $ancestors = $Helper.ancestors( $class ) ) |
| #set ( $allFields = $Helper.xmlFields( $class ) ) |
| #if ( $locationTracking ) |
| private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException { |
| #elseif ( $needXmlContext ) |
| private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, Deque<Object> context) throws XMLStreamException { |
| #else |
| private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict) throws XMLStreamException { |
| #end |
| String tagName = parser.getLocalName(); |
| ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true); |
| #if ( $locationTracking ) |
| if (addLocationInformation) { |
| ${classLcapName}.location("", new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source)); |
| } |
| #end |
| for (int i = parser.getAttributeCount() - 1; i >= 0; i--) { |
| String name = parser.getAttributeLocalName(i); |
| String ns = parser.getAttributeNamespace(i); |
| String value = parser.getAttributeValue(i); |
| if (W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || XML_NS_URI.equals(ns)) { |
| // just ignore attributes with non-default namespace (for example: xsi and xml) |
| #if ( $class == $root ) |
| } else if ("xmlns".equals(name)) { |
| // ignore xmlns attribute in root class, which is a reserved attribute name |
| #end |
| #foreach ( $field in $allFields ) |
| #if ( $Helper.xmlFieldMetadata( $field ).attribute ) |
| #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) |
| #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) |
| } else if ("$fieldTagName".equals(name)) { |
| #if ( $locationTracking ) |
| if (addLocationInformation) { |
| ${classLcapName}.location(name, new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source)); |
| } |
| #end |
| #if ( $field.type == "String" ) |
| ${classLcapName}.${field.name}(interpolatedTrimmed(value, "$fieldTagName")); |
| #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) |
| ${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(value, "$fieldTagName"), "$fieldTagName", parser, ${field.defaultValue})); |
| #else |
| // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} |
| #end |
| #end |
| #end |
| } else { |
| checkUnknownAttribute(parser, name, tagName, strict); |
| } |
| } |
| Set<String> parsed = new HashSet<>(); |
| #foreach ( $field in $allFields ) |
| #if ( $Helper.isFlatItems( $field ) ) |
| List<$field.to> ${field.name} = new ArrayList<>(); |
| #end |
| #end |
| #if ( $needXmlContext ) |
| context.addLast( ${classLcapName} ); |
| #end |
| while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) { |
| String childName = checkDuplicate(parser.getLocalName(), parser, parsed); |
| #if ( $locationTracking ) |
| int line = addLocationInformation ? parser.getLocation().getLineNumber() : -1; |
| int column = addLocationInformation ? parser.getLocation().getColumnNumber() : -1; |
| Map<Object, InputLocation> locations = null; |
| #end |
| switch (childName) { |
| #set( $ift = "if" ) |
| #foreach ( $field in $allFields ) |
| #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient && ! $Helper.xmlFieldMetadata( $field ).format ) |
| #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) |
| #if ( ! $fieldTagName ) |
| #set ( $fieldTagName = $field.name ) |
| #end |
| #if ( $Helper.isFlatItems( $field ) ) |
| #set ( $fieldTagName = $Helper.singular( $fieldTagName ) ) |
| #end |
| #set ( $fieldCapName = $Helper.capitalise($field.name)) |
| case "${fieldTagName}": { |
| #if ( $field.type == "String" ) |
| ${classLcapName}.${field.name}(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}")); |
| break; |
| #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) |
| ${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"), "${fieldTagName}", parser, ${field.defaultValue})); |
| break; |
| #elseif ( $field.type == "int" ) |
| ${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"), "${fieldTagName}", parser, strict, ${field.defaultValue})); |
| break; |
| #elseif ( $field.type == "DOM" ) |
| #if ( $locationTracking ) |
| ${classLcapName}.${field.name}(buildXmlNode(parser, source)); |
| #else |
| ${classLcapName}.${field.name}(buildXmlNode(parser)); |
| #end |
| break; |
| #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) |
| List<String> ${field.name} = new ArrayList<>(); |
| #if ( $locationTracking ) |
| locations = new HashMap<>(); |
| #end |
| while (parser.nextTag() == XMLStreamReader.START_ELEMENT) { |
| if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) { |
| #if ( $locationTracking ) |
| if (addLocationInformation) { |
| locations.put(Integer.valueOf(locations.size()), new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source)); |
| } |
| #end |
| ${field.name}.add(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}")); |
| } else { |
| checkUnknownElement(parser, strict); |
| } |
| } |
| ${classLcapName}.${field.name}(${field.name}); |
| break; |
| #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) |
| Map<String, String> ${field.name} = new LinkedHashMap<>(); |
| #if ( $locationTracking ) |
| locations = new HashMap<>(); |
| #end |
| while (parser.nextTag() == XMLStreamReader.START_ELEMENT) { |
| String key = parser.getLocalName(); |
| String value = nextText(parser, strict).trim(); |
| #if ( $locationTracking ) |
| if (addLocationInformation) { |
| locations.put(key, new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source)); |
| } |
| #end |
| ${field.name}.put(key, value); |
| } |
| ${classLcapName}.${field.name}(${field.name}); |
| break; |
| #elseif ( $field.to && $field.multiplicity == "1" ) |
| #if ( $locationTracking ) |
| ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, source)); |
| #elseif ( $needXmlContext ) |
| ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, context)); |
| #else |
| ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict)); |
| #end |
| break; |
| #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) |
| ${field.name}.add(parse${field.toClass.name}(parser, strict)); |
| break; |
| #elseif ( $field.to && $field.multiplicity == "*" ) |
| List<$field.to> ${field.name} = new ArrayList<>(); |
| while (parser.nextTag() == XMLStreamReader.START_ELEMENT) { |
| if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) { |
| #if ( $locationTracking ) |
| ${field.name}.add(parse${field.toClass.name}(parser, strict, source)); |
| #elseif ( $needXmlContext ) |
| ${field.name}.add(parse${field.toClass.name}(parser, strict, context)); |
| #else |
| ${field.name}.add(parse${field.toClass.name}(parser, strict)); |
| #end |
| } else { |
| checkUnknownElement(parser, strict); |
| } |
| } |
| ${classLcapName}.${field.name}(${field.name}); |
| break; |
| #else |
| // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} |
| break; |
| #end |
| } |
| #set( $ift = "else if" ) |
| #end |
| #end |
| default: { |
| checkUnknownElement(parser, strict); |
| break; |
| } |
| } |
| #if ( $locationTracking ) |
| if (addLocationInformation) { |
| ${classLcapName}.location(childName, new InputLocation(line, column, source, locations)); |
| } |
| #end |
| } |
| #if ( $needXmlContext ) |
| context.removeLast(); |
| #end |
| #foreach ( $field in $allFields ) |
| #if ( $Helper.isFlatItems( $field ) ) |
| ${classLcapName}.${field.name}(${field.name}); |
| #end |
| #end |
| #foreach ( $field in $allFields ) |
| #if ( $Helper.xmlFieldMetadata( $field ).format ) |
| ${classLcapName}.${field.name}($Helper.xmlFieldMetadata( $field ).format); |
| #end |
| #end |
| #if ( $class == $root ) |
| ${classLcapName}.namespaceUri(parser.getNamespaceURI()); |
| ${classLcapName}.modelEncoding(parser.getEncoding()); |
| #end |
| return ${classLcapName}.build(); |
| } |
| |
| #end |
| #end |
| |
| private String checkDuplicate(String tagName, XMLStreamReader parser, Set<String> parsed) throws XMLStreamException { |
| #set( $aliases = { } ) |
| #set( $flats = { } ) |
| #foreach( $class in $model.allClasses ) |
| #foreach ( $field in $class.getFields($version) ) |
| #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) |
| #if ( ! $fieldTagName ) |
| #set ( $fieldTagName = $field.name ) |
| #end |
| #if ( $field.alias ) |
| #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) |
| #end |
| #if ( $Helper.isFlatItems( $field ) ) |
| #set ( $fieldTagName = $Helper.singular($fieldTagName) ) |
| #set ( $dummy = $flats.put( $fieldTagName, "" ) ) |
| #end |
| #end |
| #end |
| #if ( ! ${aliases.isEmpty()} ) |
| switch (tagName) { |
| #foreach( $entry in $aliases.entrySet() ) |
| case "${entry.key}": |
| tagName = "${entry.value}"; |
| break; |
| #end |
| } |
| #end |
| #if ( ! ${flats.isEmpty()} ) |
| switch (tagName) { |
| #foreach( $entry in $flats.entrySet() ) |
| case "${entry.key}": |
| #end |
| break; |
| default: |
| if (!parsed.add(tagName)) { |
| throw new XMLStreamException("Duplicated tag: '" + tagName + "'", parser.getLocation(), null); |
| } |
| } |
| #end |
| return tagName; |
| } |
| |
| /** |
| * Method checkUnknownAttribute. |
| * |
| * @param parser a parser object. |
| * @param strict a strict object. |
| * @param tagName a tagName object. |
| * @param attribute a attribute object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @throws IOException IOException if any. |
| */ |
| private void checkUnknownAttribute(XMLStreamReader parser, String attribute, String tagName, boolean strict) throws XMLStreamException { |
| // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too |
| if (strict) { |
| throw new XMLStreamException("Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser.getLocation(), null); |
| } |
| } //-- void checkUnknownAttribute(XMLStreamReader, String, String, boolean) |
| |
| /** |
| * Method checkUnknownElement. |
| * |
| * @param parser a parser object. |
| * @param strict a strict object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @throws IOException IOException if any. |
| */ |
| private void checkUnknownElement(XMLStreamReader parser, boolean strict) throws XMLStreamException { |
| if (strict) { |
| throw new XMLStreamException("Unrecognised tag: '" + parser.getName() + "'", parser.getLocation(), null); |
| } |
| |
| for (int unrecognizedTagCount = 1; unrecognizedTagCount > 0;) { |
| int eventType = nextTag(parser); |
| if (eventType == XMLStreamReader.START_ELEMENT) { |
| unrecognizedTagCount++; |
| } else if (eventType == XMLStreamReader.END_ELEMENT) { |
| unrecognizedTagCount--; |
| } |
| } |
| } //-- void checkUnknownElement(XMLStreamReader, boolean) |
| |
| /** |
| * Method getTrimmedValue. |
| * |
| * @param s a s object. |
| * @return String |
| */ |
| private String getTrimmedValue(String s) { |
| if (s != null) { |
| s = s.trim(); |
| } |
| return s; |
| } //-- String getTrimmedValue(String) |
| |
| /** |
| * Method interpolatedTrimmed. |
| * |
| * @param value a value object. |
| * @param context a context object. |
| * @return String |
| */ |
| private String interpolatedTrimmed(String value, String context) { |
| return getTrimmedValue(contentTransformer.transform(value, context)); |
| } //-- String interpolatedTrimmed(String, String) |
| |
| /** |
| * Method nextTag. |
| * |
| * @param parser a parser object. |
| * @throws IOException IOException if any. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return int |
| */ |
| private int nextTag(XMLStreamReader parser) throws XMLStreamException { |
| while (true) { |
| int next = parser.next(); |
| switch (next) { |
| case XMLStreamReader.SPACE: |
| case XMLStreamReader.COMMENT: |
| case XMLStreamReader.PROCESSING_INSTRUCTION: |
| case XMLStreamReader.CDATA: |
| case XMLStreamReader.CHARACTERS: |
| continue; |
| case XMLStreamReader.START_ELEMENT: |
| case XMLStreamReader.END_ELEMENT: |
| return next; |
| } |
| } |
| } //-- int nextTag(XMLStreamReader) |
| |
| private String nextText(XMLStreamReader parser, boolean strict) throws XMLStreamException { |
| int eventType = parser.getEventType(); |
| if (eventType != XMLStreamReader.START_ELEMENT) { |
| throw new XMLStreamException("parser must be on START_ELEMENT to read next text", parser.getLocation(), null); |
| } |
| eventType = parser.next(); |
| StringBuilder result = new StringBuilder(); |
| while (true) { |
| if (eventType == XMLStreamReader.CHARACTERS || eventType == XMLStreamReader.CDATA) { |
| result.append(parser.getText()); |
| } else if (eventType == XMLStreamReader.ENTITY_REFERENCE) { |
| String val = null; |
| if (strict) { |
| throw new XMLStreamException("Entities are not supported in strict mode", parser.getLocation(), null); |
| } else if (addDefaultEntities) { |
| val = DEFAULT_ENTITIES.get(parser.getLocalName()); |
| } |
| if (val != null) { |
| result.append(val); |
| } else { |
| result.append("&").append(parser.getLocalName()).append(";"); |
| } |
| } else if (eventType != XMLStreamReader.COMMENT) { |
| break; |
| } |
| eventType = parser.next(); |
| } |
| if (eventType != XMLStreamReader.END_ELEMENT) { |
| throw new XMLStreamException( |
| "TEXT must be immediately followed by END_ELEMENT and not " + eventType /*TODO: TYPES[eventType]*/, parser.getLocation(), null); |
| } |
| return result.toString(); |
| } |
| |
| #if ( $locationTracking ) |
| private XmlNode buildXmlNode(XMLStreamReader parser, InputSource source) throws XMLStreamException { |
| return XmlNodeBuilder.build(parser, |
| addLocationInformation |
| ? p -> new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source) |
| : null); |
| } |
| #else |
| private XmlNode buildXmlNode(XMLStreamReader parser) throws XMLStreamException { |
| return XmlNodeBuilder.build(parser); |
| } |
| #end |
| |
| #foreach ( $class in $model.allClasses ) |
| #foreach ( $field in $class.getFields($version) ) |
| #if ( $field.type == "boolean" || $field.type == "Boolean" ) |
| #set ( $hasBooleanField = true ) |
| #elseif ( $field.type == "int" || $field.type == "Integer" ) |
| #set ( $hasIntegerField = true ) |
| #end |
| #end |
| #end |
| #if ( $hasBooleanField ) |
| /** |
| * Method getBooleanValue. |
| * |
| * @param s a s object. |
| * @param defaultValue a defaultValue object. |
| * @param parser a parser object. |
| * @param attribute a attribute object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return boolean |
| */ |
| private boolean getBooleanValue(String s, String attribute, XMLStreamReader parser, boolean defaultValue) throws XMLStreamException { |
| if (s != null && s.length() != 0) { |
| return Boolean.valueOf(s).booleanValue(); |
| } |
| return defaultValue; |
| } //-- boolean getBooleanValue(String, String, XMLStreamReader, String) |
| |
| #end |
| #if ( $hasIntegerField ) |
| /** |
| * Method getIntegerValue. |
| * |
| * @param s a s object. |
| * @param strict a strict object. |
| * @param parser a parser object. |
| * @param attribute a attribute object. |
| * @throws XMLStreamException XMLStreamException if |
| * any. |
| * @return int |
| */ |
| private int getIntegerValue(String s, String attribute, XMLStreamReader parser, boolean strict, int defaultValue) throws XMLStreamException { |
| if (s != null) { |
| try { |
| return Integer.valueOf(s).intValue(); |
| } catch (NumberFormatException nfe) { |
| if (strict) { |
| throw new XMLStreamException("Unable to parse element '" + attribute + "', must be an integer", parser.getLocation(), nfe); |
| } |
| } |
| } |
| return defaultValue; |
| } //-- int getIntegerValue(String, String, XMLStreamReader, boolean) |
| |
| #end |
| public static interface ContentTransformer { |
| /** |
| * Interpolate the value read from the xpp3 document |
| * @param source The source value |
| * @param fieldName A description of the field being interpolated. The implementation may use this to |
| * log stuff. |
| * @return The interpolated value. |
| */ |
| String transform(String source, String fieldName); |
| } |
| |
| } |