| #* |
| 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}Xpp3ReaderEx" ) |
| # |
| #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 ) ) |
| # |
| #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; |
| import java.util.ArrayList; |
| import java.util.Date; |
| 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; |
| import org.apache.maven.internal.xml.XmlNodeBuilder; |
| import ${packageModelV4}.InputSource; |
| import ${packageModelV4}.InputLocation; |
| #foreach ( $class in $model.allClasses ) |
| import ${packageModelV4}.${class.name}; |
| #end |
| import org.codehaus.plexus.util.ReaderFactory; |
| import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; |
| import org.codehaus.plexus.util.xml.pull.MXParser; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParser; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
| |
| @Generated |
| public class ${className} { |
| |
| private boolean addDefaultEntities = true; |
| |
| 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) |
| |
| /** |
| * @see ReaderFactory#newXmlReader |
| * |
| * @param reader a reader object. |
| * @param strict a strict object. |
| * @throws IOException IOException if any. |
| * @throws XmlPullParserException XmlPullParserException if |
| * any. |
| * @return ${root.name} |
| */ |
| public ${root.name} read(Reader reader, boolean strict, InputSource source) throws IOException, XmlPullParserException { |
| XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser(); |
| parser.setInput(reader); |
| return read(parser, strict, source); |
| } //-- ${root.name} read(Reader, boolean) |
| |
| /** |
| * Method read. |
| * |
| * @param in a in object. |
| * @param strict a strict object. |
| * @throws IOException IOException if any. |
| * @throws XmlPullParserException XmlPullParserException if |
| * any. |
| * @return ${root.name} |
| */ |
| public ${root.name} read(InputStream in, boolean strict, InputSource source) throws IOException, XmlPullParserException { |
| return read(ReaderFactory.newXmlReader(in), strict, source); |
| } //-- ${root.name} read(InputStream, boolean) |
| |
| /** |
| * Method read. |
| * |
| * @param parser a parser object. |
| * @param strict a strict object. |
| * @throws IOException IOException if any. |
| * @throws XmlPullParserException XmlPullParserException if |
| * any. |
| * @return ${root.name} |
| */ |
| public ${root.name} read(XmlPullParser parser, boolean strict, InputSource source) throws IOException, XmlPullParserException { |
| $rootUcapName $rootLcapName = null; |
| int eventType = parser.getEventType(); |
| boolean parsed = false; |
| while (eventType != XmlPullParser.END_DOCUMENT) { |
| if (eventType == XmlPullParser.START_TAG) { |
| if (strict && ! "${rootTag}".equals(parser.getName())) { |
| throw new XmlPullParserException("Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null); |
| } else if (parsed) { |
| // fallback, already expected a XmlPullParserException due to invalid XML |
| throw new XmlPullParserException("Duplicated tag: '${rootTag}'", parser, null); |
| } |
| $rootLcapName = parse${rootUcapName}(parser, strict, source); |
| parsed = true; |
| } |
| eventType = parser.next(); |
| } |
| if (parsed) { |
| return $rootLcapName; |
| } |
| throw new XmlPullParserException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null); |
| } //-- ${root.name} read(XmlPullParser, 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 ) ) |
| private ${classUcapName} parse${classUcapName}(XmlPullParser parser, boolean strict, InputSource source) throws IOException, XmlPullParserException { |
| String tagName = parser.getName(); |
| ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true); |
| ${classLcapName}.location("", new InputLocation(parser.getLineNumber(), parser.getColumnNumber(), source)); |
| for (int i = parser.getAttributeCount() - 1; i >= 0; i--) { |
| String name = parser.getAttributeName(i); |
| String value = parser.getAttributeValue(i); |
| if (name.indexOf(':') >= 0) { |
| // just ignore attributes with non-default namespace (for example: xmlns:xsi) |
| #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)) { |
| ${classLcapName}.location(name, new InputLocation(parser.getLineNumber(), parser.getColumnNumber(), source)); |
| #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<>(); |
| while ((strict ? parser.nextTag() : nextTag(parser)) == XmlPullParser.START_TAG) { |
| String childName = unalias(parser.getName()); |
| if (!parsed.add(childName)) { |
| throw new XmlPullParserException("Duplicated tag: '" + childName + "'", parser, null); |
| } |
| int line = parser.getLineNumber(); |
| int column = parser.getColumnNumber(); |
| Map<Object, InputLocation> locations = null; |
| switch (childName) { |
| #set( $ift = "if" ) |
| #foreach ( $field in $allFields ) |
| #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) |
| #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) |
| #if ( ! $fieldTagName ) |
| #set ( $fieldTagName = $field.name ) |
| #end |
| #set ( $fieldCapName = $Helper.capitalise($field.name)) |
| case "${fieldTagName}": { |
| #if ( $field.type == "String" ) |
| ${classLcapName}.${field.name}(interpolatedTrimmed(parser.nextText(), "${fieldTagName}")); |
| break; |
| #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) |
| ${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"), "${fieldTagName}", parser, ${field.defaultValue})); |
| break; |
| #elseif ( $field.type == "int" ) |
| ${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(parser.nextText(), "${fieldTagName}"), "${fieldTagName}", parser, strict, ${field.defaultValue})); |
| break; |
| #elseif ( $field.type == "DOM" ) |
| ${classLcapName}.${field.name}(XmlNodeBuilder.build(parser, true)); |
| break; |
| #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) |
| List<String> ${field.name} = new ArrayList<>(); |
| locations = new HashMap<>(); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) { |
| locations.put(Integer.valueOf(locations.size()), new InputLocation(parser.getLineNumber(), parser.getColumnNumber(), source)); |
| ${field.name}.add(interpolatedTrimmed(parser.nextText(), "${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<>(); |
| locations = new HashMap<>(); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| String key = parser.getName(); |
| String value = parser.nextText().trim(); |
| locations.put(key, new InputLocation(parser.getLineNumber(), parser.getColumnNumber(), source)); |
| ${field.name}.put(key, value); |
| } |
| ${classLcapName}.${field.name}(${field.name}); |
| break; |
| #elseif ( $field.to && $field.multiplicity == "1" ) |
| ${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, source )); |
| break; |
| #elseif ( $field.to && $field.multiplicity == "*" ) |
| List<$field.to> ${field.name} = new ArrayList<>(); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) { |
| ${field.name}.add(parse${field.toClass.name}(parser, strict, source)); |
| } 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; |
| } |
| } |
| ${classLcapName}.location(childName, new InputLocation(line, column, source, locations)); |
| } |
| #if ( $class == $root ) |
| ${classLcapName}.modelEncoding(parser.getInputEncoding()); |
| #end |
| return ${classLcapName}.build(); |
| } |
| |
| #end |
| #end |
| |
| private String unalias(String tagName) { |
| switch (tagName) { |
| #set( $aliases = { } ) |
| #foreach( $class in $model.allClasses ) |
| #foreach ( $field in $class.allFields ) |
| #if ( $field.alias ) |
| #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) |
| #end |
| #end |
| #end |
| #foreach( $entry in $aliases.entrySet() ) |
| case "${entry.key}": |
| return "${entry.value}"; |
| #end |
| default: |
| 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 XmlPullParserException XmlPullParserException if |
| * any. |
| * @throws IOException IOException if any. |
| */ |
| private void checkUnknownAttribute(XmlPullParser parser, String attribute, String tagName, boolean strict) throws XmlPullParserException, IOException { |
| // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too |
| if (strict) { |
| throw new XmlPullParserException("Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null); |
| } |
| } //-- void checkUnknownAttribute(XmlPullParser, String, String, boolean) |
| |
| /** |
| * Method checkUnknownElement. |
| * |
| * @param parser a parser object. |
| * @param strict a strict object. |
| * @throws XmlPullParserException XmlPullParserException if |
| * any. |
| * @throws IOException IOException if any. |
| */ |
| private void checkUnknownElement(XmlPullParser parser, boolean strict) throws XmlPullParserException, IOException { |
| if (strict) { |
| throw new XmlPullParserException("Unrecognised tag: '" + parser.getName() + "'", parser, null); |
| } |
| |
| for (int unrecognizedTagCount = 1; unrecognizedTagCount > 0;) { |
| int eventType = parser.next(); |
| if (eventType == XmlPullParser.START_TAG) { |
| unrecognizedTagCount++; |
| } else if (eventType == XmlPullParser.END_TAG) { |
| unrecognizedTagCount--; |
| } |
| } |
| } //-- void checkUnknownElement(XmlPullParser, 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 XmlPullParserException XmlPullParserException if |
| * any. |
| * @return int |
| */ |
| private int nextTag(XmlPullParser parser) throws IOException, XmlPullParserException { |
| int eventType = parser.next(); |
| if (eventType == XmlPullParser.TEXT) { |
| eventType = parser.next(); |
| } |
| if (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG) { |
| throw new XmlPullParserException("expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null); |
| } |
| return eventType; |
| } //-- int nextTag(XmlPullParser) |
| |
| #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 XmlPullParserException XmlPullParserException if |
| * any. |
| * @return boolean |
| */ |
| private boolean getBooleanValue(String s, String attribute, XmlPullParser parser, boolean defaultValue) throws XmlPullParserException { |
| if (s != null && s.length() != 0) { |
| return Boolean.valueOf(s).booleanValue(); |
| } |
| return defaultValue; |
| } //-- boolean getBooleanValue(String, String, XmlPullParser, 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 XmlPullParserException XmlPullParserException if |
| * any. |
| * @return int |
| */ |
| private int getIntegerValue(String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue) throws XmlPullParserException { |
| if (s != null) { |
| try { |
| return Integer.valueOf(s).intValue(); |
| } catch (NumberFormatException nfe) { |
| if (strict) { |
| throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be an integer", parser, nfe); |
| } |
| } |
| } |
| return defaultValue; |
| } //-- int getIntegerValue(String, String, XmlPullParser, 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); |
| } |
| |
| } |