diff --git a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java
index 9512d4a934e1..a8819f87b603 100644
--- a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java
+++ b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java
@@ -19,12 +19,11 @@
package org.apache.maven.settings;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.StandardCharsets;
+import java.io.InputStream;
+import java.nio.file.Files;
-import org.apache.maven.settings.v4.SettingsXpp3Reader;
+import org.apache.maven.api.settings.InputSource;
+import org.apache.maven.settings.v4.SettingsXpp3ReaderEx;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -43,8 +42,8 @@ void testValidGlobalSettings() throws Exception {
File globalSettingsFile = new File(basedir, "src/assembly/maven/conf/settings.xml");
assertTrue(globalSettingsFile.isFile(), globalSettingsFile.getAbsolutePath());
- try (Reader reader = new InputStreamReader(new FileInputStream(globalSettingsFile), StandardCharsets.UTF_8)) {
- new SettingsXpp3Reader().read(reader);
+ try (InputStream is = Files.newInputStream(globalSettingsFile.toPath())) {
+ new SettingsXpp3ReaderEx().read(is, true, new InputSource(globalSettingsFile.getAbsolutePath()));
}
}
}
diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml
index 3a05752c6009..db5265d2299d 100644
--- a/api/maven-api-settings/pom.xml
+++ b/api/maven-api-settings/pom.xml
@@ -61,6 +61,7 @@ under the License.
packageModelV4=org.apache.maven.api.settings
+ locationTracking=true
diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java
new file mode 100644
index 000000000000..b3ea387142b0
--- /dev/null
+++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+package org.apache.maven.api.settings;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Class InputLocation.
+ */
+public class InputLocation implements Serializable, InputLocationTracker {
+ private final int lineNumber;
+ private final int columnNumber;
+ private final InputSource source;
+ private final Map locations;
+
+ public InputLocation(InputSource source) {
+ this.lineNumber = -1;
+ this.columnNumber = -1;
+ this.source = source;
+ this.locations = Collections.singletonMap(0, this);
+ }
+
+ public InputLocation(int lineNumber, int columnNumber) {
+ this(lineNumber, columnNumber, null, null);
+ }
+
+ public InputLocation(int lineNumber, int columnNumber, InputSource source) {
+ this(lineNumber, columnNumber, source, null);
+ }
+
+ public InputLocation(int lineNumber, int columnNumber, InputSource source, Object selfLocationKey) {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ this.source = source;
+ this.locations =
+ selfLocationKey != null ? Collections.singletonMap(selfLocationKey, this) : Collections.emptyMap();
+ }
+
+ public InputLocation(int lineNumber, int columnNumber, InputSource source, Map locations) {
+ this.lineNumber = lineNumber;
+ this.columnNumber = columnNumber;
+ this.source = source;
+ this.locations = ImmutableCollections.copy(locations);
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ public int getColumnNumber() {
+ return columnNumber;
+ }
+
+ public InputSource getSource() {
+ return source;
+ }
+
+ public InputLocation getLocation(Object key) {
+ return locations != null ? locations.get(key) : null;
+ }
+
+ public Map getLocations() {
+ return locations;
+ }
+
+ /**
+ * Merges the {@code source} location into the {@code target} location.
+ *
+ * @param target the target location
+ * @param source the source location
+ * @param sourceDominant the boolean indicating of {@code source} is dominant compared to {@code target}
+ * @return the merged location
+ */
+ public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) {
+ if (source == null) {
+ return target;
+ } else if (target == null) {
+ return source;
+ }
+
+ Map locations;
+ Map sourceLocations = source.locations;
+ Map targetLocations = target.locations;
+ if (sourceLocations == null) {
+ locations = targetLocations;
+ } else if (targetLocations == null) {
+ locations = sourceLocations;
+ } else {
+ locations = new LinkedHashMap<>();
+ locations.putAll(sourceDominant ? targetLocations : sourceLocations);
+ locations.putAll(sourceDominant ? sourceLocations : targetLocations);
+ }
+
+ return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
+ } // -- InputLocation merge( InputLocation, InputLocation, boolean )
+
+ /**
+ * Merges the {@code source} location into the {@code target} location.
+ * This method is used when the locations refer to lists and also merges the indices.
+ *
+ * @param target the target location
+ * @param source the source location
+ * @param indices the list of integers for the indices
+ * @return the merged location
+ */
+ public static InputLocation merge(InputLocation target, InputLocation source, Collection indices) {
+ if (source == null) {
+ return target;
+ } else if (target == null) {
+ return source;
+ }
+
+ Map locations;
+ Map sourceLocations = source.locations;
+ Map targetLocations = target.locations;
+ if (sourceLocations == null) {
+ locations = targetLocations;
+ } else if (targetLocations == null) {
+ locations = sourceLocations;
+ } else {
+ locations = new LinkedHashMap<>();
+ for (int index : indices) {
+ InputLocation location;
+ if (index < 0) {
+ location = sourceLocations.get(~index);
+ } else {
+ location = targetLocations.get(index);
+ }
+ locations.put(locations.size(), location);
+ }
+ }
+
+ return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
+ } // -- InputLocation merge( InputLocation, InputLocation, java.util.Collection )
+
+ /**
+ * Class StringFormatter.
+ *
+ * @version $Revision$ $Date$
+ */
+ public interface StringFormatter {
+
+ // -----------/
+ // - Methods -/
+ // -----------/
+
+ /**
+ * Method toString.
+ */
+ String toString(InputLocation location);
+ }
+}
diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java
new file mode 100644
index 000000000000..d49d72307668
--- /dev/null
+++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+package org.apache.maven.api.settings;
+
+public interface InputLocationTracker {
+ InputLocation getLocation(Object field);
+}
diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java
new file mode 100644
index 000000000000..2450c1d79862
--- /dev/null
+++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package org.apache.maven.api.settings;
+
+import java.io.Serializable;
+
+/**
+ * Class InputSource.
+ */
+public class InputSource implements Serializable {
+
+ private final String location;
+
+ public InputSource(String location) {
+ this.location = location;
+ }
+
+ /**
+ * Get the path/URL of the settings definition or {@code null} if unknown.
+ *
+ * @return the location
+ */
+ public String getLocation() {
+ return this.location;
+ }
+
+ @Override
+ public String toString() {
+ return getLocation();
+ }
+}
diff --git a/api/maven-api-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo
index f1ec2e5bdc5b..caef275880ad 100644
--- a/api/maven-api-settings/src/main/mdo/settings.mdo
+++ b/api/maven-api-settings/src/main/mdo/settings.mdo
@@ -266,7 +266,7 @@
- 1.0.0+
+ 1.0.0/1.2.0
+
+ InputLocation
+ 2.0.0+
+
+
+
+
+
+ 2.0.0+
+
+
+
+
+
+
+
+ InputSource
+ 2.0.0+
+
+
+ location
+ 2.0.0+
+ String
+
+
+
+
+
+
+
+ 2.0.0+
+
+
+
+
+
+
diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java
index 39303e9cd0a6..811fd3c6b213 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java
@@ -28,14 +28,14 @@
import java.util.Objects;
import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.model.InputSource;
import org.apache.maven.api.services.xml.SettingsXmlFactory;
import org.apache.maven.api.services.xml.XmlReaderException;
import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.services.xml.XmlWriterException;
import org.apache.maven.api.services.xml.XmlWriterRequest;
+import org.apache.maven.api.settings.InputSource;
import org.apache.maven.api.settings.Settings;
-import org.apache.maven.settings.v4.SettingsXpp3Reader;
+import org.apache.maven.settings.v4.SettingsXpp3ReaderEx;
import org.apache.maven.settings.v4.SettingsXpp3Writer;
@Named
@@ -52,14 +52,14 @@ public Settings read(@Nonnull XmlReaderRequest request) throws XmlReaderExceptio
try {
InputSource source = null;
if (request.getModelId() != null || request.getLocation() != null) {
- source = new InputSource(request.getModelId(), request.getLocation());
+ source = new InputSource(request.getLocation());
}
- SettingsXpp3Reader xml = new SettingsXpp3Reader();
+ SettingsXpp3ReaderEx xml = new SettingsXpp3ReaderEx();
xml.setAddDefaultEntities(request.isAddDefaultEntities());
if (reader != null) {
- return xml.read(reader, request.isStrict());
+ return xml.read(reader, request.isStrict(), source);
} else {
- return xml.read(inputStream, request.isStrict());
+ return xml.read(inputStream, request.isStrict(), source);
}
} catch (Exception e) {
throw new XmlReaderException("Unable to read settings", e);
diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java
index 9eddc5c8b499..6f8710179559 100644
--- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java
+++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java
@@ -24,12 +24,12 @@
import java.io.File;
import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.maven.api.settings.InputSource;
import org.apache.maven.building.FileSource;
import org.apache.maven.building.Source;
import org.apache.maven.settings.Server;
@@ -39,6 +39,7 @@
import org.apache.maven.settings.io.SettingsReader;
import org.apache.maven.settings.io.SettingsWriter;
import org.apache.maven.settings.merge.MavenSettingsMerger;
+import org.apache.maven.settings.v4.SettingsTransformer;
import org.apache.maven.settings.validation.SettingsValidator;
import org.codehaus.plexus.interpolation.EnvarBasedValueSource;
import org.codehaus.plexus.interpolation.InterpolationException;
@@ -158,8 +159,9 @@ private Settings readSettings(
Settings settings;
try {
- Map options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.TRUE);
-
+ Map options = new HashMap<>();
+ options.put(SettingsReader.IS_STRICT, Boolean.TRUE);
+ options.put(InputSource.class.getName(), new InputSource(settingsSource.getLocation()));
try {
settings = settingsReader.read(settingsSource.getInputStream(), options);
} catch (SettingsParseException e) {
@@ -211,15 +213,6 @@ private Settings readSettings(
private Settings interpolate(
Settings settings, SettingsBuildingRequest request, SettingsProblemCollector problems) {
- StringWriter writer = new StringWriter(1024 * 4);
-
- try {
- settingsWriter.write(writer, null, settings);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to serialize settings to memory", e);
- }
-
- String serializedSettings = writer.toString();
RegexBasedInterpolator interpolator = new RegexBasedInterpolator();
@@ -238,37 +231,19 @@ private Settings interpolate(
e);
}
- interpolator.addPostProcessor((expression, value) -> {
- if (value != null) {
- // we're going to parse this back in as XML so we need to escape XML markup
- value = value.toString()
- .replace("&", "&")
- .replace("<", "<")
- .replace(">", ">");
- return value;
- }
- return null;
- });
-
- try {
- serializedSettings = interpolator.interpolate(serializedSettings, "settings");
- } catch (InterpolationException e) {
- problems.add(
- SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e);
-
- return settings;
- }
-
- Settings result;
- try {
- Map options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.FALSE);
- result = settingsReader.read(new StringReader(serializedSettings), options);
- } catch (IOException e) {
- problems.add(
- SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e);
- return settings;
- }
-
- return result;
+ return new Settings(new SettingsTransformer(value -> {
+ try {
+ return value != null ? interpolator.interpolate(value) : null;
+ } catch (InterpolationException e) {
+ problems.add(
+ SettingsProblem.Severity.WARNING,
+ "Failed to interpolate settings: " + e.getMessage(),
+ -1,
+ -1,
+ e);
+ return value;
+ }
+ })
+ .visit(settings.getDelegate()));
}
}
diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java
index fc96ad1a23ca..a30e2bbd2131 100644
--- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java
+++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java
@@ -29,8 +29,9 @@
import java.util.Map;
import java.util.Objects;
+import org.apache.maven.api.settings.InputSource;
import org.apache.maven.settings.Settings;
-import org.apache.maven.settings.v4.SettingsXpp3Reader;
+import org.apache.maven.settings.v4.SettingsXpp3ReaderEx;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
@@ -47,7 +48,8 @@ public Settings read(File input, Map options) throws IOException {
Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = Files.newInputStream(input.toPath())) {
- return new Settings(new SettingsXpp3Reader().read(in, isStrict(options)));
+ InputSource source = new InputSource(input.toString());
+ return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source));
} catch (XmlPullParserException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
@@ -58,7 +60,8 @@ public Settings read(Reader input, Map options) throws IOException {
Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) {
- return new Settings(new SettingsXpp3Reader().read(in, isStrict(options)));
+ InputSource source = (InputSource) options.get(InputSource.class.getName());
+ return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source));
} catch (XmlPullParserException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
@@ -69,7 +72,8 @@ public Settings read(InputStream input, Map options) throws IOExcepti
Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) {
- return new Settings(new SettingsXpp3Reader().read(in, isStrict(options)));
+ InputSource source = (InputSource) options.get(InputSource.class.getName());
+ return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source));
} catch (XmlPullParserException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e);
}
diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml
index c27963e9410e..a87b0c0f7036 100644
--- a/maven-settings/pom.xml
+++ b/maven-settings/pom.xml
@@ -60,6 +60,11 @@ under the License.
src/main/mdo/settings.mdo
+
+ packageModelV3=org.apache.maven.settings
+ packageModelV4=org.apache.maven.api.settings
+ packageToolV4=org.apache.maven.settings.v4
+
@@ -70,18 +75,31 @@ under the License.
generate-sources
- model-v3.vm
merger.vm
+ transformer.vm
reader.vm
+ reader-ex.vm
writer.vm
+ writer-ex.vm
-
- packageModelV3=org.apache.maven.settings
- packageModelV4=org.apache.maven.api.settings
- packageToolV4=org.apache.maven.settings.v4
+
+ locationTracking=true
+
+ v3
+
+ velocity
+
+ generate-sources
+
+ 1.2.0
+
+ model-v3.vm
+
+
+
diff --git a/src/mdo/model-v3.vm b/src/mdo/model-v3.vm
index afa0d498ada5..5508c618f44b 100644
--- a/src/mdo/model-v3.vm
+++ b/src/mdo/model-v3.vm
@@ -183,9 +183,17 @@ public class ${class.name}
public void set${cap}(${type} ${field.name}) {
#if ($field.type == "DOM")
- if (!Objects.equals(((Xpp3Dom) ${field.name}).getDom(), getDelegate().${pfx}${cap}())) {
- update(getDelegate().with${cap}(((Xpp3Dom) ${field.name}).getDom()));
- ((Xpp3Dom) ${field.name}).setChildrenTracking(this::replace);
+ if (${field.name} instanceof Xpp3Dom) {
+ if (!Objects.equals(((Xpp3Dom) ${field.name}).getDom(), getDelegate().${pfx}${cap}())) {
+ update(getDelegate().with${cap}(((Xpp3Dom) ${field.name}).getDom()));
+ ((Xpp3Dom) ${field.name}).setChildrenTracking(this::replace);
+ }
+ } else if (${field.name} == null) {
+ if (getDelegate().${pfx}${cap}() != null) {
+ update(getDelegate().with${cap}(null));
+ }
+ } else {
+ throw new IllegalArgumentException("Expected an Xpp3Dom object but received: " + ${field.name});
}
#elseif( $field.type == "java.util.Properties" )
Map map = ${field.name}.entrySet().stream()
@@ -194,7 +202,7 @@ public class ${class.name}
update(getDelegate().with${cap}(map));
}
#else
- if (!Objects.equals(${field.name}, getDelegate().${pfx}${cap}())) {
+ if (!Objects.equals(${field.name}, ${pfx}${cap}())) {
#if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" )
update(getDelegate().with${cap}(
${field.name}.stream().map(c -> c.getDelegate()).collect(Collectors.toList())));
diff --git a/src/mdo/reader.vm b/src/mdo/reader.vm
index b95ea612838f..a1b86af1d505 100644
--- a/src/mdo/reader.vm
+++ b/src/mdo/reader.vm
@@ -74,305 +74,595 @@ public class ${className} {
}
/**
- * Method checkFieldWithDuplicate.
+ * @see ReaderFactory#newXmlReader
*
- * @param parser a parser object.
- * @param parsed a parsed object.
- * @param alias a alias object.
- * @param tagName a tagName object.
+ * @param reader a reader object.
+ * @param strict a strict object.
+ * @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return boolean
+ * @return ${root.name}
*/
- private boolean checkFieldWithDuplicate(XmlPullParser parser, String tagName, String alias, Set parsed)
- throws XmlPullParserException {
- if (!(parser.getName().equals(tagName) || parser.getName().equals(alias))) {
- return false;
- }
- if (!parsed.add(tagName)) {
- throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
- }
- return true;
- } //-- boolean checkFieldWithDuplicate(XmlPullParser, String, String, Set)
+ public ${root.name} read(Reader reader, boolean strict) throws IOException, XmlPullParserException {
+ XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser();
+ parser.setInput(reader);
+ return read(parser, strict);
+ } //-- ${root.name} read(Reader, boolean)
/**
- * Method checkUnknownAttribute.
+ * @see ReaderFactory#newXmlReader
*
- * @param parser a parser object.
- * @param strict a strict object.
- * @param tagName a tagName object.
- * @param attribute a attribute object.
+ * @param reader a reader object.
+ * @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @throws IOException IOException if any.
+ * @return ${root.name}
*/
- 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)
+ public ${root.name} read(Reader reader) throws IOException, XmlPullParserException {
+ return read(reader, true);
+ } //-- ${root.name} read(Reader)
/**
- * Method checkUnknownElement.
+ * Method read.
*
- * @param parser a parser object.
+ * @param in a in 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)
-
- /**
- * Returns the state of the "add default entities" flag.
- *
- * @return boolean
- */
- public boolean getAddDefaultEntities() {
- return addDefaultEntities;
- } //-- boolean getAddDefaultEntities()
-
- /**
- * Method getBooleanValue.
- *
- * @param s a s object.
- * @param parser a parser object.
- * @param attribute a attribute object.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return boolean
+ * @return ${root.name}
*/
- private boolean getBooleanValue(String s, String attribute, XmlPullParser parser)
- throws XmlPullParserException {
- return getBooleanValue(s, attribute, parser, false);
- } //-- boolean getBooleanValue(String, String, XmlPullParser)
+ public ${root.name} read(InputStream in, boolean strict) throws IOException, XmlPullParserException {
+ return read(ReaderFactory.newXmlReader(in), strict);
+ } //-- ${root.name} read(InputStream, boolean)
/**
- * Method getBooleanValue.
+ * Method read.
*
- * @param s a s object.
- * @param defaultValue a defaultValue object.
- * @param parser a parser object.
- * @param attribute a attribute object.
+ * @param in a in object.
+ * @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return boolean
+ * @return ${root.name}
*/
- 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)
+ public ${root.name} read(InputStream in) throws IOException, XmlPullParserException {
+ return read(ReaderFactory.newXmlReader(in));
+ } //-- ${root.name} read(InputStream)
/**
- * Method getByteValue.
+ * Method read.
*
- * @param s a s object.
- * @param strict a strict object.
* @param parser a parser object.
- * @param attribute a attribute object.
+ * @param strict a strict object.
+ * @throws IOException IOException if any.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return byte
+ * @return ${root.name}
*/
- private byte getByteValue(String s, String attribute, XmlPullParser parser, boolean strict)
- throws XmlPullParserException {
- if (s != null) {
- try {
- return Byte.valueOf(s).byteValue();
- } catch (NumberFormatException nfe) {
- if (strict) {
- throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a byte", parser, nfe);
+ public ${root.name} read(XmlPullParser parser, boolean strict) 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);
+ parsed = true;
}
+ eventType = parser.next();
}
- return 0;
- } //-- byte getByteValue(String, String, XmlPullParser, boolean)
-
- /**
- * Method getCharacterValue.
- *
- * @param s a s object.
- * @param parser a parser object.
- * @param attribute a attribute object.
- * @throws XmlPullParserException XmlPullParserException if
- * any.
- * @return char
- */
- private char getCharacterValue(String s, String attribute, XmlPullParser parser)
- throws XmlPullParserException {
- if (s != null) {
- return s.charAt(0);
+ if (parsed) {
+ return $rootLcapName;
}
- return 0;
- } //-- char getCharacterValue(String, String, XmlPullParser)
-
- /**
- * Method getDateValue.
- *
- * @param s a s object.
- * @param parser a parser object.
- * @param attribute a attribute object.
- * @throws XmlPullParserException XmlPullParserException if
- * any.
- * @return Date
- */
- private Date getDateValue(String s, String attribute, XmlPullParser parser)
- throws XmlPullParserException {
- return getDateValue(s, attribute, null, parser);
- } //-- Date getDateValue(String, String, XmlPullParser)
+ throw new XmlPullParserException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null);
+ } //-- ${root.name} read(XmlPullParser, boolean)
- /**
- * Method getDateValue.
- *
- * @param s a s object.
- * @param parser a parser object.
- * @param dateFormat a dateFormat object.
- * @param attribute a attribute object.
- * @throws XmlPullParserException XmlPullParserException if
- * any.
- * @return Date
- */
- private Date getDateValue(String s, String attribute, String dateFormat, XmlPullParser parser)
- throws XmlPullParserException {
- if (s != null) {
- String effectiveDateFormat = dateFormat;
- if (dateFormat == null) {
- effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+#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 = [] )
+ #foreach ( $cl in $ancestors )
+ #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) )
+ #end
+ private ${classUcapName} parse${classUcapName}(XmlPullParser parser, boolean strict)
+ throws IOException, XmlPullParserException {
+ String tagName = parser.getName();
+ ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true);
+ 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
}
- if ("long".equals(effectiveDateFormat)) {
- try {
- return new java.util.Date(Long.parseLong(s));
- } catch (NumberFormatException e) {
- throw new XmlPullParserException(e.getMessage(), parser, e);
- }
- } else {
- try {
- DateFormat dateParser = new java.text.SimpleDateFormat(effectiveDateFormat, java.util.Locale.US);
- return dateParser.parse(s);
- } catch (java.text.ParseException e) {
- throw new XmlPullParserException(e.getMessage(), parser, e);
- }
+ #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 ( $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);
}
}
- return null;
- } //-- Date getDateValue(String, String, String, XmlPullParser)
-
- /**
- * Method getDoubleValue.
- *
- * @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 double
- */
- private double getDoubleValue(String s, String attribute, XmlPullParser parser, boolean strict)
- throws XmlPullParserException {
- if (s != null) {
- try {
- return Double.valueOf(s).doubleValue();
- } catch (NumberFormatException nfe) {
- if (strict) {
- throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
+ Set parsed = new HashSet<>();
+ #foreach ( $field in $allFields )
+ #if ( $Helper.isFlatItems( $field ) )
+ List<$field.to> ${field.name} = new ArrayList<>();
+ #end
+ #end
+ while ((strict ? parser.nextTag() : nextTag(parser)) == XmlPullParser.START_TAG) {
+ String childName = checkDuplicate(parser.getName(), parser, parsed);
+ 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
+ #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(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 ${field.name} = new ArrayList<>();
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
+ ${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 ${field.name} = new LinkedHashMap<>();
+ while (parser.nextTag() == XmlPullParser.START_TAG) {
+ String key = parser.getName();
+ String value = parser.nextText().trim();
+ ${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));
+ 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() == XmlPullParser.START_TAG) {
+ if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
+ ${field.name}.add(parse${field.toClass.name}(parser, strict));
+ } 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;
}
}
}
- return 0;
- } //-- double getDoubleValue(String, String, XmlPullParser, boolean)
+ #foreach ( $field in $allFields )
+ #if ( $Helper.isFlatItems( $field ) )
+ ${classLcapName}.${field.name}(${field.name});
+ #end
+ #end
+ #if ( $class == $root )
+ ${classLcapName}.modelEncoding(parser.getInputEncoding());
+ #end
+ return ${classLcapName}.build();
+ }
+
+ #end
+#end
+
+ private String checkDuplicate(String tagName, XmlPullParser parser, Set parsed) throws XmlPullParserException {
+#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}";
+ #end
+ }
+#end
+#if ( ! ${flats.isEmpty()} )
+ switch (tagName) {
+ #foreach( $entry in $flats.entrySet() )
+ case "${entry.key}":
+ #end
+ break;
+ default:
+ if (!parsed.add(tagName)) {
+ throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
+ }
+ }
+#end
+ return tagName;
+ }
/**
- * Method getFloatValue.
+ * 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)
+
+ 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);
+ }
+
+ /**
+ * Method checkFieldWithDuplicate.
*
- * @param s a s object.
- * @param strict a strict object.
* @param parser a parser object.
- * @param attribute a attribute object.
+ * @param parsed a parsed object.
+ * @param alias a alias object.
+ * @param tagName a tagName object.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return float
+ * @return boolean
*/
- private float getFloatValue(String s, String attribute, XmlPullParser parser, boolean strict)
- throws XmlPullParserException {
- if (s != null) {
- try {
- return Float.valueOf(s).floatValue();
- } catch (NumberFormatException nfe) {
- if (strict) {
- throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
- }
- }
+ private boolean checkFieldWithDuplicate(XmlPullParser parser, String tagName, String alias, Set parsed)
+ throws XmlPullParserException {
+ if (!(parser.getName().equals(tagName) || parser.getName().equals(alias))) {
+ return false;
}
- return 0;
- } //-- float getFloatValue(String, String, XmlPullParser, boolean)
+ if (!parsed.add(tagName)) {
+ throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
+ }
+ return true;
+ } //-- boolean checkFieldWithDuplicate(XmlPullParser, String, String, Set)
/**
- * Method getIntegerValue.
+ * Method checkUnknownAttribute.
*
- * @param s a s object.
* @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.
- * @return int
+ * @throws IOException IOException if any.
*/
- private int getIntegerValue(String s, String attribute, XmlPullParser parser, boolean strict)
- throws XmlPullParserException {
- return getIntegerValue(s, attribute, parser, strict, 0);
- } //-- int getBooleanValue(String, String, XmlPullParser)
+ 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 getIntegerValue.
+ * Method checkUnknownElement.
*
- * @param s a s object.
- * @param strict a strict object.
* @param parser a parser object.
- * @param attribute a attribute object.
+ * @param strict a strict object.
* @throws XmlPullParserException XmlPullParserException if
* any.
- * @return int
+ * @throws IOException IOException if any.
*/
- 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);
- }
+ 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--;
}
}
- return defaultValue;
- } //-- int getIntegerValue(String, String, XmlPullParser, boolean, int)
+ } //-- void checkUnknownElement(XmlPullParser, boolean)
/**
- * Method getLongValue.
+ * Returns the state of the "add default entities" flag.
*
- * @param s a s object.
- * @param strict a strict object.
- * @param parser a parser object.
- * @param attribute a attribute object.
+ * @return boolean
+ */
+ public boolean getAddDefaultEntities() {
+ return addDefaultEntities;
+ } //-- boolean getAddDefaultEntities()
+
+ /**
+ * Method getBooleanValue.
+ *
+ * @param s a s 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)
+ throws XmlPullParserException {
+ return getBooleanValue(s, attribute, parser, false);
+ } //-- boolean getBooleanValue(String, String, XmlPullParser)
+
+ /**
+ * 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)
+
+ /**
+ * Method getByteValue.
+ *
+ * @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 byte
+ */
+ private byte getByteValue(String s, String attribute, XmlPullParser parser, boolean strict)
+ throws XmlPullParserException {
+ if (s != null) {
+ try {
+ return Byte.valueOf(s).byteValue();
+ } catch (NumberFormatException nfe) {
+ if (strict) {
+ throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a byte", parser, nfe);
+ }
+ }
+ }
+ return 0;
+ } //-- byte getByteValue(String, String, XmlPullParser, boolean)
+
+ /**
+ * Method getCharacterValue.
+ *
+ * @param s a s object.
+ * @param parser a parser object.
+ * @param attribute a attribute object.
+ * @throws XmlPullParserException XmlPullParserException if
+ * any.
+ * @return char
+ */
+ private char getCharacterValue(String s, String attribute, XmlPullParser parser)
+ throws XmlPullParserException {
+ if (s != null) {
+ return s.charAt(0);
+ }
+ return 0;
+ } //-- char getCharacterValue(String, String, XmlPullParser)
+
+ /**
+ * Method getDateValue.
+ *
+ * @param s a s object.
+ * @param parser a parser object.
+ * @param attribute a attribute object.
+ * @throws XmlPullParserException XmlPullParserException if
+ * any.
+ * @return Date
+ */
+ private Date getDateValue(String s, String attribute, XmlPullParser parser)
+ throws XmlPullParserException {
+ return getDateValue(s, attribute, null, parser);
+ } //-- Date getDateValue(String, String, XmlPullParser)
+
+ /**
+ * Method getDateValue.
+ *
+ * @param s a s object.
+ * @param parser a parser object.
+ * @param dateFormat a dateFormat object.
+ * @param attribute a attribute object.
+ * @throws XmlPullParserException XmlPullParserException if
+ * any.
+ * @return Date
+ */
+ private Date getDateValue(String s, String attribute, String dateFormat, XmlPullParser parser)
+ throws XmlPullParserException {
+ if (s != null) {
+ String effectiveDateFormat = dateFormat;
+ if (dateFormat == null) {
+ effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+ }
+ if ("long".equals(effectiveDateFormat)) {
+ try {
+ return new java.util.Date(Long.parseLong(s));
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException(e.getMessage(), parser, e);
+ }
+ } else {
+ try {
+ DateFormat dateParser = new java.text.SimpleDateFormat(effectiveDateFormat, java.util.Locale.US);
+ return dateParser.parse(s);
+ } catch (java.text.ParseException e) {
+ throw new XmlPullParserException(e.getMessage(), parser, e);
+ }
+ }
+ }
+ return null;
+ } //-- Date getDateValue(String, String, String, XmlPullParser)
+
+ /**
+ * Method getDoubleValue.
+ *
+ * @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 double
+ */
+ private double getDoubleValue(String s, String attribute, XmlPullParser parser, boolean strict)
+ throws XmlPullParserException {
+ if (s != null) {
+ try {
+ return Double.valueOf(s).doubleValue();
+ } catch (NumberFormatException nfe) {
+ if (strict) {
+ throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
+ }
+ }
+ }
+ return 0;
+ } //-- double getDoubleValue(String, String, XmlPullParser, boolean)
+
+ /**
+ * Method getFloatValue.
+ *
+ * @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 float
+ */
+ private float getFloatValue(String s, String attribute, XmlPullParser parser, boolean strict)
+ throws XmlPullParserException {
+ if (s != null) {
+ try {
+ return Float.valueOf(s).floatValue();
+ } catch (NumberFormatException nfe) {
+ if (strict) {
+ throw new XmlPullParserException("Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe);
+ }
+ }
+ }
+ return 0;
+ } //-- float getFloatValue(String, String, XmlPullParser, boolean)
+
+ /**
+ * Method getIntegerValue.
+ *
+ * @param s a s 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)
+ throws XmlPullParserException {
+ return getIntegerValue(s, attribute, parser, strict, 0);
+ } //-- int getBooleanValue(String, String, XmlPullParser)
+
+ /**
+ * 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, int)
+
+ /**
+ * Method getLongValue.
+ *
+ * @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 long
@@ -481,294 +771,4 @@ public class ${className} {
return eventType;
} //-- int nextTag(XmlPullParser)
- /**
- * @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) throws IOException, XmlPullParserException {
- XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser();
- parser.setInput(reader);
- return read(parser, strict);
- } //-- ${root.name} read(Reader, boolean)
-
- /**
- * @see ReaderFactory#newXmlReader
- *
- * @param reader a reader object.
- * @throws IOException IOException if any.
- * @throws XmlPullParserException XmlPullParserException if
- * any.
- * @return ${root.name}
- */
- public ${root.name} read(Reader reader) throws IOException, XmlPullParserException {
- return read(reader, true);
- } //-- ${root.name} read(Reader)
-
- /**
- * 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) throws IOException, XmlPullParserException {
- return read(ReaderFactory.newXmlReader(in), strict);
- } //-- ${root.name} read(InputStream, boolean)
-
- /**
- * Method read.
- *
- * @param in a in object.
- * @throws IOException IOException if any.
- * @throws XmlPullParserException XmlPullParserException if
- * any.
- * @return ${root.name}
- */
- public ${root.name} read(InputStream in) throws IOException, XmlPullParserException {
- return read(ReaderFactory.newXmlReader(in));
- } //-- ${root.name} read(InputStream)
-
- /**
- * 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) 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);
- 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 = [] )
- #foreach ( $cl in $ancestors )
- #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) )
- #end
- private ${classUcapName} parse${classUcapName}(XmlPullParser parser, boolean strict)
- throws IOException, XmlPullParserException {
- String tagName = parser.getName();
- ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true);
- 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)) {
- #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 parsed = new HashSet<>();
- #foreach ( $field in $allFields )
- #if ( $Helper.isFlatItems( $field ) )
- List<$field.to> ${field.name} = new ArrayList<>();
- #end
- #end
- while ((strict ? parser.nextTag() : nextTag(parser)) == XmlPullParser.START_TAG) {
- String childName = checkDuplicate(parser.getName(), parser, parsed);
- 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
- #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(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 ${field.name} = new ArrayList<>();
- while (parser.nextTag() == XmlPullParser.START_TAG) {
- if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
- ${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 ${field.name} = new LinkedHashMap<>();
- while (parser.nextTag() == XmlPullParser.START_TAG) {
- String key = parser.getName();
- String value = parser.nextText().trim();
- ${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));
- 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() == XmlPullParser.START_TAG) {
- if ("${Helper.singular($fieldTagName)}".equals(parser.getName())) {
- ${field.name}.add(parse${field.toClass.name}(parser, strict));
- } 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;
- }
- }
- }
- #foreach ( $field in $allFields )
- #if ( $Helper.isFlatItems( $field ) )
- ${classLcapName}.${field.name}(${field.name});
- #end
- #end
- #if ( $class == $root )
- ${classLcapName}.modelEncoding(parser.getInputEncoding());
- #end
- return ${classLcapName}.build();
- }
-
- #end
-#end
-
- private String checkDuplicate(String tagName, XmlPullParser parser, Set parsed) throws XmlPullParserException {
-#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}";
- #end
- }
-#end
-#if ( ! ${flats.isEmpty()} )
- switch (tagName) {
- #foreach( $entry in $flats.entrySet() )
- case "${entry.key}":
- #end
- break;
- default:
- if (!parsed.add(tagName)) {
- throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null);
- }
- }
-#end
- return tagName;
- }
-
- /**
- * 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)
-
- 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);
- }
-
}