This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/maven-xinclude-extension.git


The following commit(s) were added to refs/heads/main by this push:
     new cefb0c5  Upgrade to Maven 4.0.0-rc-1 (#16)
cefb0c5 is described below

commit cefb0c581a9752856e7a21bb119492530198a2e1
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Tue Dec 10 23:13:28 2024 +0100

    Upgrade to Maven 4.0.0-rc-1 (#16)
---
 .github/workflows/maven-verify.yml                 |   4 +-
 pom.xml                                            |  84 +++-
 .../org/apache/maven/xinclude/StaxLocation.java    |  76 +++
 .../maven/xinclude/XIncludeModelXmlFactory.java    |   5 +-
 src/main/mdo/reader-stax.vm                        |  74 +--
 src/main/mdo/writer-stax.vm                        | 523 +++++++++++++++++++++
 .../org/apache/maven/xinclude/ModelXmlTest.java    |   3 +-
 7 files changed, 718 insertions(+), 51 deletions(-)

diff --git a/.github/workflows/maven-verify.yml 
b/.github/workflows/maven-verify.yml
index 99811aa..96bece9 100644
--- a/.github/workflows/maven-verify.yml
+++ b/.github/workflows/maven-verify.yml
@@ -26,6 +26,6 @@ jobs:
     name: Verify
     uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4
     with:
-      ff-maven: "4.0.0-beta-4"                     # Maven version for 
fail-fast-build
-      maven-matrix: '[ "4.0.0-beta-4" ]'
+      ff-maven: "4.0.0-beta-5"                     # Maven version for 
fail-fast-build
+      maven-matrix: '[ "4.0.0-beta-5", "4.0.0-rc-1" ]'
       jdk-matrix: '[ "17", "21" ]'
diff --git a/pom.xml b/pom.xml
index be0776c..a4f2e01 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,16 +33,15 @@ under the License.
 
   <properties>
     <javaVersion>17</javaVersion>
-    <maven.version>4.0.0-beta-4</maven.version>
-    <junit.version>5.11.3</junit.version>
+    <maven.version>4.0.0-rc-1</maven.version>
+
+    <versions.junit5>5.11.3</versions.junit5>
+    <version.maven-dependency-plugin>3.8.1</version.maven-dependency-plugin>
+    <version.maven-surefire-plugin>3.5.2</version.maven-surefire-plugin>
+    <version.maven-invoker-plugin>3.9.0</version.maven-invoker-plugin>
   </properties>
 
   <dependencies>
-    <dependency>
-      <groupId>com.fasterxml.woodstox</groupId>
-      <artifactId>woodstox-core</artifactId>
-      <version>7.1.0</version>
-    </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-api-core</artifactId>
@@ -57,24 +56,80 @@ under the License.
     </dependency>
     <dependency>
       <groupId>org.apache.maven</groupId>
-      <artifactId>maven-api-impl</artifactId>
+      <artifactId>maven-api-xml</artifactId>
       <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-model</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-meta</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>com.fasterxml.woodstox</groupId>
+      <artifactId>woodstox-core</artifactId>
+      <version>7.1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.woodstox</groupId>
+      <artifactId>stax2-api</artifactId>
+      <version>4.2.2</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-xml</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-impl</artifactId>
+      <version>${maven.version}</version>
+      <scope>test</scope>
     </dependency>
 
     <dependency>
       <groupId>org.junit.jupiter</groupId>
-      <artifactId>junit-jupiter</artifactId>
-      <version>${junit.version}</version>
+      <artifactId>junit-jupiter-api</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
 
   <build>
     <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <!-- Use the latest version of the plugin -->
+        <executions>
+          <execution>
+            <id>enforce-maven</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <requireMavenVersion>
+                  <version>[4.0.0-beta-5,)</version>
+                  <!-- Specify the required Maven version -->
+                  <message>You need Maven 4.0.0-beta-5 or higher to build this 
project.</message>
+                </requireMavenVersion>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
-        <version>3.8.1</version>
+        <version>${version.maven-dependency-plugin}</version>
         <executions>
           <execution>
             <id>copy-mdo</id>
@@ -109,6 +164,7 @@ under the License.
               </models>
               <templates>
                 <template>reader-stax.vm</template>
+                <template>writer-stax.vm</template>
               </templates>
               <params>
                 <param>forcedIOModelVersion=4.0.0</param>
@@ -133,10 +189,14 @@ under the License.
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-invoker-plugin</artifactId>
-              <version>3.9.0</version>
+              <version>${version.maven-invoker-plugin}</version>
               <configuration>
                 <showErrors>true</showErrors>
                 
<cloneProjectsTo>${project.build.directory}/its</cloneProjectsTo>
+                <collectedProjects>
+                  <project>entities-xinclude/pom.xml</project>
+                  <project>entities-xinclude/child/pom.xml</project>
+                </collectedProjects>
                 <cloneClean>true</cloneClean>
                 
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
                 <settingsFile>src/it/settings.xml</settingsFile>
diff --git a/src/main/java/org/apache/maven/xinclude/StaxLocation.java 
b/src/main/java/org/apache/maven/xinclude/StaxLocation.java
new file mode 100644
index 0000000..90b08fe
--- /dev/null
+++ b/src/main/java/org/apache/maven/xinclude/StaxLocation.java
@@ -0,0 +1,76 @@
+/*
+ * 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.xinclude;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.maven.api.services.xml.Location;
+
+public class StaxLocation implements Location {
+
+    private final javax.xml.stream.Location location;
+
+    public static Location getLocation(Exception e) {
+        return toLocation(e instanceof XMLStreamException xe ? 
xe.getLocation() : null);
+    }
+
+    public static Location toLocation(javax.xml.stream.Location location) {
+        return location != null ? new StaxLocation(location) : null;
+    }
+
+    public static String getMessage(Exception e) {
+        String message = e.getMessage();
+        if (e instanceof XMLStreamException xe && xe.getLocation() != null) {
+            int idx = message.indexOf("\nMessage: ");
+            if (idx >= 0) {
+                return message.substring(idx + "\nMessage: ".length());
+            }
+        }
+        return message;
+    }
+
+    public StaxLocation(javax.xml.stream.Location location) {
+        this.location = location;
+    }
+
+    @Override
+    public int getLineNumber() {
+        return location.getLineNumber();
+    }
+
+    @Override
+    public int getColumnNumber() {
+        return location.getColumnNumber();
+    }
+
+    @Override
+    public int getCharacterOffset() {
+        return location.getCharacterOffset();
+    }
+
+    @Override
+    public String getPublicId() {
+        return location.getPublicId();
+    }
+
+    @Override
+    public String getSystemId() {
+        return location.getSystemId();
+    }
+}
diff --git 
a/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java 
b/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java
index 59051f3..62c355e 100644
--- a/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java
+++ b/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java
@@ -40,12 +40,11 @@ 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.model.v4.MavenStaxWriter;
 import org.apache.maven.xinclude.stax.XInclude;
 import org.codehaus.stax2.io.Stax2FileSource;
 
-import static org.apache.maven.internal.impl.StaxLocation.getLocation;
-import static org.apache.maven.internal.impl.StaxLocation.getMessage;
+import static org.apache.maven.xinclude.StaxLocation.getLocation;
+import static org.apache.maven.xinclude.StaxLocation.getMessage;
 import static org.apache.maven.xinclude.Utils.nonNull;
 
 @Named
diff --git a/src/main/mdo/reader-stax.vm b/src/main/mdo/reader-stax.vm
index 6d777aa..c0c7cec 100644
--- a/src/main/mdo/reader-stax.vm
+++ b/src/main/mdo/reader-stax.vm
@@ -84,6 +84,7 @@ 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;
 
+@SuppressWarnings("deprecation")
 @Generated
 public class ${className} {
 
@@ -356,15 +357,39 @@ public class ${className} {
     private boolean addLocationInformation = true;
 #end
 
-    private ContentTransformer contentTransformer = (s, f) -> s;
-
-    private XMLResolver xmlResolver;
+    private final ContentTransformer contentTransformer;
+    private final XMLResolver xmlResolver;
 
     public ${className}() {
+        this(null, null);
     }
 
     public ${className}(ContentTransformer contentTransformer) {
+        this(contentTransformer, null);
+    }
+
+    public ${className}(XMLResolver xmlResolver) {
+        this(null, xmlResolver);
+    }
+
+    public ${className}(ContentTransformer contentTransformer, XMLResolver 
xmlResolver) {
         this.contentTransformer = contentTransformer;
+        this.xmlResolver = xmlResolver;
+    }
+
+    /**
+     * Returns the {@link XMLInputFactory} used by this reader.
+     *
+     * @return the {@link XMLInputFactory} used by this reader.
+     */
+    public XMLInputFactory getXMLInputFactory(boolean strict) {
+        XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
+        factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, 
true);
+        factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, 
true);
+        factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, 
false);
+        factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, 
xmlResolver);
+        factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, 
getUndeclaredXmlResolver(strict));
+        return factory;
     }
 
     /**
@@ -405,22 +430,6 @@ public class ${className} {
     } //-- void setAddLocationInformation(boolean)
 #end
 
-    public ContentTransformer getContentTransformer() {
-        return contentTransformer;
-    }
-
-    public void setContentTransformer(ContentTransformer contentTransformer) {
-        this.contentTransformer = contentTransformer;
-    }
-
-    public XMLResolver getXmlResolver() {
-        return xmlResolver;
-    }
-
-    public void setXmlResolver(XMLResolver xmlResolver) {
-        this.xmlResolver = xmlResolver;
-    }
-
     public ${root.name} read(Reader reader) throws XMLStreamException {
 #if ( $locationTracking )
         return read(reader, true, null);
@@ -441,17 +450,12 @@ public class ${className} {
 #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, 
true);
-        factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, 
true);
-        factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, 
false);
-        factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, 
xmlResolver);
-        factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, 
getUndeclaredXmlResolver(strict));
 #if ( $locationTracking )
         StreamSource streamSource = new StreamSource(reader, source != null ? 
source.getLocation() : null);
 #else
         StreamSource streamSource = new StreamSource(reader);
 #end
+        XMLInputFactory factory = getXMLInputFactory(strict);
         XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
 #if ( $locationTracking )
         return read(parser, strict, source);
@@ -482,17 +486,12 @@ public class ${className} {
 #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, 
true);
-        factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, 
true);
-        factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, 
false);
-        factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, 
xmlResolver);
-        factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, 
getUndeclaredXmlResolver(strict));
 #if ( $locationTracking )
         StreamSource streamSource = new StreamSource(in, source != null ? 
source.getLocation() : null);
 #else
         StreamSource streamSource = new StreamSource(in);
 #end
+        XMLInputFactory factory = getXMLInputFactory(strict);
         XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
 #if ( $locationTracking )
         return read(parser, strict, source);
@@ -579,6 +578,9 @@ public class ${className} {
   #foreach ( $field in $allFields )
     #if ( $Helper.xmlFieldMetadata( $field ).attribute )
       #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
+      #if ( ! $fieldTagName )
+        #set ( $fieldTagName = $field.name )
+      #end
       #set ( $fieldCapName = $Helper.capitalise( $field.name ) )
             } else if ("$fieldTagName".equals(name)) {
       #if ( $locationTracking )
@@ -590,6 +592,8 @@ public class ${className} {
                 ${classLcapName}.${field.name}(interpolatedTrimmed(value, 
"$fieldTagName"));
       #elseif ( $field.type == "boolean" || $field.type == "Boolean" )
                 
${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(value, 
"$fieldTagName"), "$fieldTagName", parser, ${field.defaultValue}));
+      #elseif ( $field.type == "int" || $field.type == "Integer" )
+                
${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(value, 
"$fieldTagName"), "$fieldTagName", parser, strict, ${field.defaultValue}));
       #else
                 // TODO: type=${field.type} to=${field.to} 
multiplicity=${field.multiplicity}
       #end
@@ -690,7 +694,13 @@ public class ${className} {
         #end
                     break;
       #elseif ( $field.to && $field.multiplicity == "*" && 
$Helper.isFlatItems( $field ) )
+        #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
                     break;
       #elseif ( $field.to && $field.multiplicity == "*" )
                     List<$field.to> ${field.name} = new ArrayList<>();
@@ -869,7 +879,7 @@ public class ${className} {
      * @return String
      */
     private String interpolatedTrimmed(String value, String context) {
-        return getTrimmedValue(contentTransformer.transform(value, context));
+        return getTrimmedValue(contentTransformer != null ? 
contentTransformer.transform(value, context) : value);
     } //-- String interpolatedTrimmed(String, String)
 
     /**
diff --git a/src/main/mdo/writer-stax.vm b/src/main/mdo/writer-stax.vm
new file mode 100644
index 0000000..6e9c8c6
--- /dev/null
+++ b/src/main/mdo/writer-stax.vm
@@ -0,0 +1,523 @@
+#*
+  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}StaxWriter" )
+#
+#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
+#set ( $xmlModelMetadata = $model.getMetadata( 
"org.codehaus.modello.plugins.xml.metadata.XmlModelMetadata" ) )
+#if ( $forcedIOModelVersion )
+  #set ( $Version = $model.class.classLoader.loadClass( 
"org.codehaus.modello.model.Version" ) )
+  #set ( $ioVersion = $Version.getConstructor( $package.class ).newInstance( 
$forcedIOModelVersion ) )
+#else
+  #set ( $ioVersion = $version )
+#end
+#set ( $namespace = $xmlModelMetadata.getNamespace($ioVersion) )
+#set ( $schemaLocation = $xmlModelMetadata.getSchemaLocation($ioVersion) )
+#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.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.Function;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import org.apache.maven.api.annotations.Generated;
+#if ( $locationTracking )
+import ${packageModelV4}.InputLocation;
+import ${packageModelV4}.InputLocationTracker;
+#end
+import org.apache.maven.api.xml.XmlNode;
+import org.apache.maven.internal.xml.XmlNodeBuilder;
+#foreach ( $class in $model.allClasses )
+  #if ( $class.name != "InputLocation" )
+import ${packageModelV4}.${class.name};
+  #end
+#end
+import org.codehaus.stax2.util.StreamWriterDelegate;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
+
+@SuppressWarnings("deprecation")
+@Generated
+public class ${className} {
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Default namespace.
+     */
+    private static final String NAMESPACE = "${namespace}";
+
+    /**
+     * Default schemaLocation.
+     */
+    private static final String SCHEMA_LOCATION = "${schemaLocation}";
+
+    /**
+     * Field namespace.
+     */
+    private String namespace = NAMESPACE;
+
+    /**
+     * Field schemaLocation.
+     */
+    private String schemaLocation = SCHEMA_LOCATION;
+
+    /**
+     * Field fileComment.
+     */
+    private String fileComment = null;
+
+#if ( $locationTracking )
+    private boolean addLocationInformation = true;
+
+    /**
+     * Field stringFormatter.
+     */
+    protected Function<InputLocation, String> stringFormatter;
+
+#end
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     * Method setNamespace.
+     *
+     * @param namespace the namespace to use.
+     */
+    public void setNamespace(String namespace) {
+        this.namespace = Objects.requireNonNull(namespace);
+    } //-- void setNamespace(String)
+
+    /**
+     * Method setSchemaLocation.
+     *
+     * @param schemaLocation the schema location to use.
+     */
+    public void setSchemaLocation(String schemaLocation) {
+        this.schemaLocation = Objects.requireNonNull(schemaLocation);
+        } //-- void setSchemaLocation(String)
+
+    /**
+     * Method setFileComment.
+     *
+     * @param fileComment a fileComment object.
+     */
+    public void setFileComment(String fileComment) {
+        this.fileComment = fileComment;
+    } //-- void setFileComment(String)
+
+#if ( $locationTracking )
+    /**
+     * Method setAddLocationInformation.
+     */
+    public void setAddLocationInformation(boolean addLocationInformation) {
+        this.addLocationInformation = addLocationInformation;
+    } //-- void setAddLocationInformation(String)
+
+    /**
+     * Method setStringFormatter.
+     *
+     * @param stringFormatter
+     */
+    public void setStringFormatter(Function<InputLocation, String> 
stringFormatter) {
+        this.stringFormatter = stringFormatter;
+    } //-- void setStringFormatter(Function<InputLocation, String>)
+
+#end
+    /**
+     * Method write.
+     *
+     * @param writer a writer object
+     * @param ${rootLcapName} a ${root.name} object
+     * @throws IOException IOException if any
+     */
+    public void write(Writer writer, ${root.name} ${rootLcapName}) throws 
IOException, XMLStreamException {
+        XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
+        factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+        
factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL,
 true);
+        
factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM,
 true);
+        XMLStreamWriter serializer = new 
IndentingXMLStreamWriter(factory.createXMLStreamWriter(writer));
+        serializer.writeStartDocument(${rootLcapName}.getModelEncoding(), 
null);
+        write${root.name}("$rootTag", ${rootLcapName}, serializer);
+        serializer.writeEndDocument();
+    } //-- void write(Writer, ${root.name})
+
+    /**
+     * Method write.
+     *
+     * @param stream a stream object
+     * @param ${rootLcapName} a ${root.name} object
+     * @throws IOException IOException if any
+     */
+    public void write(OutputStream stream, ${root.name} ${rootLcapName}) 
throws IOException, XMLStreamException {
+        XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
+        factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+        
factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL,
 true);
+        
factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM,
 true);
+        XMLStreamWriter serializer = new 
IndentingXMLStreamWriter(factory.createXMLStreamWriter(stream, 
${rootLcapName}.getModelEncoding()));
+        serializer.writeStartDocument(${rootLcapName}.getModelEncoding(), 
null);
+        write${root.name}("$rootTag", ${rootLcapName}, serializer);
+        serializer.writeEndDocument();
+    } //-- void write(OutputStream, ${root.name})
+
+#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 ( $allFields = $Helper.xmlFields( $class ) )
+    private void write${classUcapName}(String tagName, ${classUcapName} 
${classLcapName}, XMLStreamWriter serializer)
+        throws IOException, XMLStreamException {
+        if (${classLcapName} != null) {
+  #if ( $class == $root )
+            if (this.fileComment != null) {
+                serializer.writeCharacters("\n");
+                serializer.writeComment(this.fileComment);
+                serializer.writeCharacters("\n");
+            }
+            serializer.writeStartElement("", tagName, namespace);
+            serializer.writeNamespace("", namespace);
+            serializer.writeNamespace("xsi", W3C_XML_SCHEMA_INSTANCE_NS_URI);
+            serializer.writeAttribute(W3C_XML_SCHEMA_INSTANCE_NS_URI, 
"schemaLocation", namespace + " " + schemaLocation);
+  #else
+            serializer.writeStartElement(namespace, tagName);
+  #end
+  #foreach ( $field in $allFields )
+    #if ( $Helper.xmlFieldMetadata( $field ).attribute && ! 
$Helper.xmlFieldMetadata( $field ).format )
+      #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
+      #if ( ! $fieldTagName )
+        #set ( $fieldTagName = $field.name )
+      #end
+      #set ( $fieldCapName = $Helper.capitalise( $field.name ) )
+      #if ( $field.type == "String" )
+            writeAttr("$fieldTagName", ${classLcapName}.get${fieldCapName}(), 
serializer);
+      #elseif ( $field.type == "boolean" )
+        #set ( $def = ${field.defaultValue} )
+        #if ( ${def} == "true" )
+            writeAttr("$fieldTagName", ${classLcapName}.is${fieldCapName}() ? 
null : "false", serializer);
+        #else
+            writeAttr("$fieldTagName", ${classLcapName}.is${fieldCapName}() ? 
"true" : null, serializer);
+        #end
+      #elseif ( $field.type == "int" || $field.type == "Integer" )
+            writeAttr("$fieldTagName", 
Integer.toString(${classLcapName}.get${fieldCapName}()), serializer);
+      #else
+            // TODO: type=${field.type} to=${field.to} 
multiplicity=${field.multiplicity}
+      #end
+    #end
+  #end
+  #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
+      #set ( $fieldCapName = $Helper.capitalise( $field.name ) )
+      #set ( $def = ${field.defaultValue} )
+      #if ( $locationTracking )
+        #set ( $loctrac = ", ${classLcapName}" )
+        #set ( $loctracnull = ", null" )
+      #else
+        #set ( $loctrac = "" )
+        #set ( $loctracnull = "" )
+      #end
+      #if ( $field.type == "String" )
+        #if ( ! $def )
+            writeTag("$fieldTagName", null, 
${classLcapName}.get${fieldCapName}(), serializer${loctrac});
+        #else
+            writeTag("$fieldTagName", "${def}", 
${classLcapName}.get${fieldCapName}(), serializer${loctrac});
+        #end
+      #elseif ( $field.type == "boolean" || $field.type == "Boolean" )
+        #if ( ${def} == "true" )
+            writeTag("$fieldTagName", "${def}", 
${classLcapName}.is${fieldCapName}() ? null : "false", serializer${loctrac});
+        #else
+            writeTag("$fieldTagName", "${def}", 
${classLcapName}.is${fieldCapName}() ? "true" : null, serializer${loctrac});
+        #end
+      #elseif ( $field.type == "int" )
+            writeTag("$fieldTagName", "${def}", 
Integer.toString(${classLcapName}.get${fieldCapName}()), serializer${loctrac});
+      #elseif ( $field.type == "DOM" )
+            writeDom(${classLcapName}.get${fieldCapName}(), serializer);
+      #elseif ( $field.type == "java.util.List" && $field.to == "String" && 
$field.multiplicity == "*" )
+        #set( $singularField = ${Helper.singular($fieldTagName)} )
+            writeList("$fieldTagName", ${classLcapName}.get${fieldCapName}(), 
serializer${loctrac},
+                    t -> writeTag("$singularField", null, t, 
serializer${loctracnull}));
+      #elseif ( $field.type == "java.util.Properties" && $field.to == "String" 
&& $field.multiplicity == "*" )
+            writeProperties("$fieldTagName", 
${classLcapName}.get${fieldCapName}(), serializer${loctrac});
+      #elseif ( $field.to && $field.multiplicity == "1" )
+            write${field.to}("$fieldTagName", 
${classLcapName}.get${fieldCapName}(), serializer);
+      #elseif ( $field.to && $field.multiplicity == "*" )
+        #set( $singularField = ${Helper.singular($fieldTagName)} )
+            writeList("$fieldTagName", $Helper.isFlatItems($field), 
${classLcapName}.get${fieldCapName}(), serializer${loctrac},
+                    t -> write${field.to}("$singularField", t, serializer));
+      #else
+            // TODO: name=${field.name} type=${field.type} to=${field.to} 
multiplicity=${field.multiplicity}
+      #end
+    #end
+  #end
+            serializer.writeEndElement();
+        }
+    }
+
+ #end
+#end
+    @FunctionalInterface
+    private interface ElementWriter<T> {
+        public void write(T t) throws IOException, XMLStreamException;
+    }
+
+#if ( $locationTracking )
+    private <T> void writeList(String tagName, List<T> list, XMLStreamWriter 
serializer, InputLocationTracker locationTracker, ElementWriter<T> writer) 
throws IOException, XMLStreamException {
+        writeList(tagName, false, list, serializer, locationTracker, writer);
+#else
+    private <T> void writeList(String tagName, List<T> list, XMLStreamWriter 
serializer, ElementWriter<T> writer) throws IOException, XMLStreamException {
+        writeList(tagName, false, list, serializer, writer);
+#end
+    }
+
+#if ( $locationTracking )
+    private <T> void writeList(String tagName, boolean flat, List<T> list, 
XMLStreamWriter serializer, InputLocationTracker locationTracker, 
ElementWriter<T> writer) throws IOException, XMLStreamException {
+#else
+    private <T> void writeList(String tagName, boolean flat, List<T> list, 
XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, 
XMLStreamException {
+#end
+        if (list != null && !list.isEmpty()) {
+            if (!flat) {
+                serializer.writeStartElement(namespace, tagName);
+            }
+            int index = 0;
+#if ( $locationTracking )
+            InputLocation location = locationTracker != null ? 
locationTracker.getLocation(tagName) : null;
+#end
+            for (T t : list) {
+                writer.write(t);
+#if ( $locationTracking )
+                writeLocationTracking(location, Integer.valueOf(index++), 
serializer);
+#end
+            }
+            if (!flat) {
+                serializer.writeEndElement();
+            }
+        }
+    }
+
+#if ( $locationTracking )
+    private <T> void writeProperties(String tagName, Map<String, String> 
props, XMLStreamWriter serializer, InputLocationTracker locationTracker) throws 
IOException, XMLStreamException {
+#else
+    private <T> void writeProperties(String tagName, Map<String, String> 
props, XMLStreamWriter serializer) throws IOException, XMLStreamException {
+#end
+        if (props != null && !props.isEmpty()) {
+            serializer.writeStartElement(namespace, tagName);
+#if ( $locationTracking )
+            InputLocation location = locationTracker != null ? 
locationTracker.getLocation(tagName) : null;
+#end
+            for (Map.Entry<String, String> entry : props.entrySet()) {
+                String key = entry.getKey();
+#if ( $locationTracking )
+                writeTag(key, null, entry.getValue(), serializer, null);
+                writeLocationTracking(location, key, serializer);
+#else
+                writeTag(key, null, entry.getValue(), serializer);
+#end
+            }
+            serializer.writeEndElement();
+        }
+    }
+
+    private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws 
IOException, XMLStreamException {
+        if (dom != null) {
+            serializer.writeStartElement(namespace, dom.getName());
+            for (Map.Entry<String, String> attr : 
dom.getAttributes().entrySet()) {
+                if (attr.getKey().startsWith("xml:")) {
+                    
serializer.writeAttribute("http://www.w3.org/XML/1998/namespace";,
+                    attr.getKey().substring(4), attr.getValue());
+                } else {
+                    serializer.writeAttribute(attr.getKey(), attr.getValue());
+                }
+            }
+            for (XmlNode child : dom.getChildren()) {
+                writeDom(child, serializer);
+            }
+            String value = dom.getValue();
+            if (value != null) {
+                serializer.writeCharacters(value);
+            }
+            serializer.writeEndElement();
+#if ( $locationTracking )
+            if (addLocationInformation && dom.getInputLocation() instanceof 
InputLocation && dom.getChildren().isEmpty()) {
+                serializer.writeComment(toString((InputLocation) 
dom.getInputLocation()));
+            }
+#end
+        }
+    }
+
+#if ( $locationTracking )
+    private void writeTag(String tagName, String defaultValue, String value, 
XMLStreamWriter serializer, InputLocationTracker locationTracker) throws 
IOException, XMLStreamException {
+#else
+    private void writeTag(String tagName, String defaultValue, String value, 
XMLStreamWriter serializer) throws IOException, XMLStreamException {
+#end
+        if (value != null && !Objects.equals(defaultValue, value)) {
+            serializer.writeStartElement(namespace, tagName);
+            serializer.writeCharacters(value);
+            serializer.writeEndElement();
+#if ( $locationTracking )
+            writeLocationTracking(locationTracker, tagName, serializer);
+#end
+        }
+    }
+
+    private void writeAttr(String attrName, String value, XMLStreamWriter 
serializer) throws IOException, XMLStreamException {
+        if (value != null) {
+            serializer.writeAttribute(attrName, value);
+        }
+    }
+#if ( $locationTracking )
+
+    /**
+     * Method writeLocationTracking.
+     *
+     * @param locationTracker
+     * @param serializer
+     * @param key
+     * @throws IOException
+     */
+    protected void writeLocationTracking(InputLocationTracker locationTracker, 
Object key, XMLStreamWriter serializer) throws IOException, XMLStreamException {
+        if (addLocationInformation) {
+            InputLocation location = (locationTracker == null) ? null : 
locationTracker.getLocation(key);
+            if (location != null) {
+                serializer.writeComment(toString(location));
+            }
+        }
+    } //-- void writeLocationTracking(InputLocationTracker, Object, 
XMLStreamWriter)
+
+    /**
+     * Method toString.
+     *
+     * @param location
+     * @return String
+     */
+    protected String toString(InputLocation location) {
+        if (stringFormatter != null) {
+            return stringFormatter.apply(location);
+        }
+        if (location.getSource() != null) {
+            return ' ' + location.getSource().toString() + ':' + 
location.getLineNumber() + ' ';
+        } else {
+            return " " + location.getLineNumber() + " ";
+        }
+    } //-- String toString(InputLocation)
+#end
+
+    static class IndentingXMLStreamWriter extends StreamWriterDelegate {
+
+        int depth = 0;
+        boolean hasChildren = false;
+
+        public IndentingXMLStreamWriter(XMLStreamWriter parent) {
+            super(parent);
+        }
+
+        @Override
+        public void writeEmptyElement(String localName) throws 
XMLStreamException {
+            indent();
+            super.writeEmptyElement(localName);
+            hasChildren = true;
+        }
+
+        @Override
+        public void writeEmptyElement(String namespaceURI, String localName) 
throws XMLStreamException {
+            indent();
+            super.writeEmptyElement(namespaceURI, localName);
+            hasChildren = true;
+        }
+
+        @Override
+        public void writeEmptyElement(String prefix, String localName, String 
namespaceURI) throws XMLStreamException {
+            indent();
+            super.writeEmptyElement(prefix, localName, namespaceURI);
+            hasChildren = true;
+        }
+
+        @Override
+        public void writeStartElement(String localName) throws 
XMLStreamException {
+            indent();
+            super.writeStartElement(localName);
+            depth++;
+            hasChildren = false;
+        }
+
+        @Override
+        public void writeStartElement(String namespaceURI, String localName) 
throws XMLStreamException {
+            indent();
+            super.writeStartElement(namespaceURI, localName);
+            depth++;
+            hasChildren = false;
+        }
+
+        @Override
+        public void writeStartElement(String prefix, String localName, String 
namespaceURI) throws XMLStreamException {
+            indent();
+            super.writeStartElement(prefix, localName, namespaceURI);
+            depth++;
+            hasChildren = false;
+        }
+
+        @Override
+        public void writeEndElement() throws XMLStreamException {
+            depth--;
+            if (hasChildren) {
+                indent();
+            }
+            super.writeEndElement();
+            hasChildren = true;
+        }
+
+        private void indent() throws XMLStreamException {
+            super.writeCharacters("\n");
+            for (int i = 0; i < depth; i++) {
+                super.writeCharacters("  ");
+            }
+        }
+    }
+}
diff --git a/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java 
b/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java
index 196195a..f88d1d3 100644
--- a/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java
+++ b/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java
@@ -59,8 +59,7 @@ class ModelXmlTest {
                 + "  <version>1.0-m7-SNAPSHOT</version>\n"
                 + "  &desc;\n"
                 + "</project>\n";
-        MavenStaxReader staxReader = new MavenStaxReader();
-        staxReader.setXmlResolver((publicID, systemID, baseURI, namespace) -> {
+        MavenStaxReader staxReader = new MavenStaxReader((publicID, systemID, 
baseURI, namespace) -> {
             if ("file:desc.xml".equals(systemID)) {
                 return "<?xml version='1.0' 
encoding='UTF-8'?><description>foo</description>";
             }


Reply via email to