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-hocon-extension.git

commit 2fa97fad15db1ce560f76417a1b7f0905f0be708
Author: Guillaume Nodet <[email protected]>
AuthorDate: Thu Sep 12 17:00:21 2024 +0200

    Hocon extension
---
 .github/dependabot.yml                             |  28 +++
 .github/workflows/maven-verify.yml                 |  31 ++++
 .gitignore                                         |  18 ++
 README.md                                          |  64 +++++++
 pom.xml                                            | 185 ++++++++++++++++++
 src/it/hocon-example/.mvn/extensions.xml           |  26 +++
 src/it/hocon-example/child/pom.hocon               |  35 ++++
 src/it/hocon-example/pom.xml                       |  34 ++++
 src/it/settings.xml                                |  25 +++
 .../org/apache/maven/hocon/HoconModelParser.java   |  63 +++++++
 .../java/org/apache/maven/hocon/PathSource.java    |  56 ++++++
 src/main/resources/META-INF/maven/extension.xml    |  27 +++
 .../META-INF/maven/org.apache.maven.api.di.Inject  |  17 ++
 src/mdo/hocon-reader.vm                            | 206 +++++++++++++++++++++
 .../java/org/apache/maven/hocon/ParsingTest.java   |  42 +++++
 src/test/resources/pom.hocon                       |  36 ++++
 16 files changed, 893 insertions(+)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..ce41a74
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,28 @@
+#
+#  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.
+#
+version: 2
+updates:
+
+  - package-ecosystem: maven
+    directory: "/"
+    schedule:
+      interval: daily
+
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "daily"
\ No newline at end of file
diff --git a/.github/workflows/maven-verify.yml 
b/.github/workflows/maven-verify.yml
new file mode 100644
index 0000000..99811aa
--- /dev/null
+++ b/.github/workflows/maven-verify.yml
@@ -0,0 +1,31 @@
+# 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.
+
+name: Verify
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  build:
+    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" ]'
+      jdk-matrix: '[ "17", "21" ]'
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e6cbeac
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+**/target/**
+.project
+.classpath
+.settings/
+.svn/
+# Intellij
+*.ipr
+*.iml
+.idea
+.DS_Store
+/bootstrap
+/dependencies.xml
+.java-version
+.checkstyle
+.factorypath
+.vscode/
+repo/
+/*.svg
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7c8a2eb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+<!---
+ 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.
+-->
+[Apache Maven Hocon 
Extension](https://maven.apache.org/extensions/maven-xinclude-extension/)
+==================================
+
+[![Apache License, Version 2.0, January 
2004](https://img.shields.io/github/license/apache/maven.svg?label=License)](https://www.apache.org/licenses/LICENSE-2.0)
+[![Maven 
Central](https://img.shields.io/maven-central/v/org.apache.maven.extensions/maven-xinclude-extension.svg?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.maven.extensions/maven-xinclude-extension)
+
+This project provides a Hocon POM parser extension for Maven 4. It allows POMs 
to 
+be written with the 
[Hocon](https://github.com/lightbend/config/blob/master/HOCON.md)
+syntax, which is a superset of the [JSON](https://json.org/) syntax.
+
+License
+-------
+This code is under the [Apache License, Version 2.0, January 2004][license].
+
+See the [`NOTICE`](./NOTICE) file for required notices and attributions.
+
+Usage
+-----
+To use this extension, the following declaration needs to be done in your 
`${rootDirectory}/.mvn/extensions.xml`:
+```
+<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.2.0";>
+    <extension>
+        <groupId>org.apache.maven.extensions</groupId>
+        <artifactId>maven-hocon-extension</artifactId>
+        <version>@project.version@</version>
+    </extension>
+</extensions>
+```
+This allows defining a POM using Hocon syntax:
+```
+modelVersion = 4.1.0
+parent {
+    groupId = org.apache.maven.hocon.its
+    artifactId = parent
+    version = 1.0.0-SNAPSHOT
+}
+artifactId = test
+
+properties = {
+  "my.property" = foo
+  pluginVersion = 3.9
+}
+
+dependencies = [
+    # just add one dummy dependency
+    "com.typesafe:config:1.4.2"
+]
+```
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..fc29277
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.1.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 
http://maven.apache.org/xsd/maven-4.1.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.extensions</groupId>
+    <artifactId>maven-extensions</artifactId>
+    <version>43</version>
+    <relativePath />
+  </parent>
+
+  <artifactId>maven-hocon-extension</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <name>Hocon extension for Maven 4</name>
+  <description>Provides Hocon syntax support</description>
+
+  <properties>
+    <javaVersion>17</javaVersion>
+    <maven.version>4.0.0-beta-4</maven.version>
+    <junit.version>5.11.0</junit.version>
+    <hocon.version>1.4.2</hocon.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-spi</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-core</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-di</artifactId>
+      <version>${maven.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-api-impl</artifactId>
+      <version>${maven.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.typesafe</groupId>
+      <artifactId>config</artifactId>
+      <version>${hocon.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <version>${junit.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>3.3.0</version>
+        <!-- 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-4,)</version>
+                  <!-- Specify the required Maven version -->
+                  <message>You need Maven 4.0.0-beta-4 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.7.1</version>
+        <executions>
+          <execution>
+            <id>copy-mdo</id>
+            <goals>
+              <goal>copy</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <outputDirectory>${project.build.directory}/mdo</outputDirectory>
+              
<artifact>org.apache.maven:maven-api-model:${maven.version}:mdo</artifact>
+              <stripVersion>true</stripVersion>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.modello</groupId>
+        <artifactId>modello-maven-plugin</artifactId>
+        <version>2.4.0</version>
+        <executions>
+          <execution>
+            <id>generate-hocon-reader</id>
+            <goals>
+              <goal>velocity</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <version>4.2.0</version>
+              <models>
+                <model>target/mdo/maven-api-model.mdo</model>
+              </models>
+              <templates>
+                <template>src/mdo/hocon-reader.vm</template>
+              </templates>
+              <params>
+                <param>packageModelV4=org.apache.maven.api.model</param>
+              </params>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.11.0</version>
+        <configuration>
+          <release>${javaVersion}</release>
+          <proc>full</proc>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>run-its</id>
+      <build>
+        <pluginManagement>
+          <plugins>
+            <plugin>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-invoker-plugin</artifactId>
+              <version>3.8.0</version>
+              <configuration>
+                <showErrors>true</showErrors>
+                
<cloneProjectsTo>${project.build.directory}/its</cloneProjectsTo>
+                <cloneClean>true</cloneClean>
+                
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
+                <settingsFile>src/it/settings.xml</settingsFile>
+              </configuration>
+            </plugin>
+          </plugins>
+        </pluginManagement>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/src/it/hocon-example/.mvn/extensions.xml 
b/src/it/hocon-example/.mvn/extensions.xml
new file mode 100644
index 0000000..90ec8fc
--- /dev/null
+++ b/src/it/hocon-example/.mvn/extensions.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.2.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.2.0 
https://maven.apache.org/xsd/core-extensions-1.2.0.xsd";>
+    <extension>
+        <groupId>org.apache.maven.extensions</groupId>
+        <artifactId>maven-hocon-extension</artifactId>
+        <version>@project.version@</version>
+    </extension>
+</extensions>
\ No newline at end of file
diff --git a/src/it/hocon-example/child/pom.hocon 
b/src/it/hocon-example/child/pom.hocon
new file mode 100644
index 0000000..97c8295
--- /dev/null
+++ b/src/it/hocon-example/child/pom.hocon
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+modelVersion = 4.1.0
+parent {
+    groupId = org.apache.maven.hocon.its
+    artifactId = parent
+    version = 1.0.0-SNAPSHOT
+}
+artifactId = test
+
+properties = {
+  "my.property" = foo
+  pluginVersion = 3.9
+}
+
+dependencies = [
+    # just add one dummy dependency
+    "com.typesafe:config:1.4.2"
+]
\ No newline at end of file
diff --git a/src/it/hocon-example/pom.xml b/src/it/hocon-example/pom.xml
new file mode 100644
index 0000000..c2c98ac
--- /dev/null
+++ b/src/it/hocon-example/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.1.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 
http://maven.apache.org/xsd/maven-4.1.0.xsd";>
+  <parent>
+    <groupId>org.apache.maven.extensions</groupId>
+    <artifactId>maven-extensions</artifactId>
+    <version>43</version>
+  </parent>
+  <groupId>org.apache.maven.hocon.its</groupId>
+  <artifactId>parent</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>child</module>
+  </modules>
+</project>
diff --git a/src/it/settings.xml b/src/it/settings.xml
new file mode 100644
index 0000000..0317296
--- /dev/null
+++ b/src/it/settings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<settings xmlns="http://maven.apache.org/SETTINGS/1.3.0";
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.3.0 
https://maven.apache.org/xsd/settings-1.3.0.xsd";>
+</settings>
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/hocon/HoconModelParser.java 
b/src/main/java/org/apache/maven/hocon/HoconModelParser.java
new file mode 100644
index 0000000..fb3cb68
--- /dev/null
+++ b/src/main/java/org/apache/maven/hocon/HoconModelParser.java
@@ -0,0 +1,63 @@
+/*
+ * 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.hocon;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Optional;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Priority;
+import org.apache.maven.api.model.Model;
+import org.apache.maven.api.services.Source;
+import org.apache.maven.api.spi.ModelParser;
+import org.apache.maven.api.spi.ModelParserException;
+
+@Named("hocon")
+@Priority(10)
+public class HoconModelParser implements ModelParser {
+
+    @Override
+    public Optional<Source> locate(Path path) {
+        Path pom = Files.isDirectory(path) ? path.resolve("pom.hocon") : path;
+        return Files.isRegularFile(pom) ? Optional.of(new PathSource(pom)) : 
Optional.empty();
+    }
+
+    @Override
+    public Model parse(Source source, Map<String, ?> map) throws 
ModelParserException {
+        Config config;
+        if (source.getPath() != null) {
+            config = ConfigFactory.parseFile(source.getPath().toFile());
+        } else {
+            try (InputStream input = source.openStream()) {
+                config = ConfigFactory.parseReader(new 
InputStreamReader(input, StandardCharsets.UTF_8));
+            } catch (IOException e) {
+                throw new ModelParserException("Unable to parse: " + 
source.getLocation(), e);
+            }
+        }
+        return new HoconReader().parseModel(config.root());
+    }
+}
diff --git a/src/main/java/org/apache/maven/hocon/PathSource.java 
b/src/main/java/org/apache/maven/hocon/PathSource.java
new file mode 100644
index 0000000..cdf5b7b
--- /dev/null
+++ b/src/main/java/org/apache/maven/hocon/PathSource.java
@@ -0,0 +1,56 @@
+/*
+ * 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.hocon;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+
+import org.apache.maven.api.services.Source;
+
+public class PathSource implements Source {
+
+    private final Path path;
+
+    public PathSource(Path path) {
+        this.path = Objects.requireNonNull(path);
+    }
+
+    @Override
+    public Path getPath() {
+        return path;
+    }
+
+    @Override
+    public InputStream openStream() throws IOException {
+        return Files.newInputStream(path);
+    }
+
+    @Override
+    public String getLocation() {
+        return path.toString();
+    }
+
+    @Override
+    public Source resolve(String s) {
+        return new PathSource(path.resolve(s));
+    }
+}
diff --git a/src/main/resources/META-INF/maven/extension.xml 
b/src/main/resources/META-INF/maven/extension.xml
new file mode 100644
index 0000000..77ffe86
--- /dev/null
+++ b/src/main/resources/META-INF/maven/extension.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+<!-- START SNIPPET: core-extension -->
+<extension>
+    <exportedPackages>
+        <exportedPackage>org.apache.maven.hocon</exportedPackage>
+        <exportedPackage>META-INF.maven</exportedPackage>
+    </exportedPackages>
+</extension>
\ No newline at end of file
diff --git a/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject 
b/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
new file mode 100644
index 0000000..6778661
--- /dev/null
+++ b/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
@@ -0,0 +1,17 @@
+# 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.
+org.apache.maven.hocon.HoconModelParser
diff --git a/src/mdo/hocon-reader.vm b/src/mdo/hocon-reader.vm
new file mode 100644
index 0000000..b21925f
--- /dev/null
+++ b/src/mdo/hocon-reader.vm
@@ -0,0 +1,206 @@
+#*
+  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.
+*#
+#set ( $package = "org.apache.maven.hocon" )
+#set ( $className = "HoconReader" )
+#
+#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
+#set ( $rootXml = $Helper.xmlClassMetadata( $root ) )
+#set ( $rootTag = $rootXml.tagName )
+#set ( $rootUcapName = $Helper.capitalise( $root.name ) )
+#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) )
+#
+#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
+// =================== DO NOT EDIT THIS FILE ====================
+//  Generated by Modello Velocity from ${template}
+//  template, any modifications will be overwritten.
+// ==============================================================
+package ${package};
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import org.apache.maven.api.annotations.Generated;
+#foreach ( $class in $model.allClasses )
+import ${packageModelV4}.${class.name};
+#end
+import com.typesafe.config.ConfigList;
+import com.typesafe.config.ConfigObject;
+import com.typesafe.config.ConfigValue;
+import com.typesafe.config.ConfigValueType;
+
+@Generated
+public class ${className} {
+
+#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
+    public ${classUcapName} parse${classUcapName}(ConfigValue value) {
+        if (value instanceof ConfigObject) {
+            ${classUcapName}.Builder ${classLcapName} = 
${classUcapName}.newBuilder(true);
+            ((ConfigObject) value).forEach((k, v) -> {
+                switch (k) {
+  #foreach ( $field in $allFields )
+    #if ( ! $Helper.xmlFieldMetadata( $field ).transient && $field.name != 
"root" )
+      #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}(getStringValue(v));
+                        break;
+      #elseif ( $field.type == "boolean" || $field.type == "Boolean" )
+                        ${classLcapName}.${field.name}(getBooleanValue(v));
+                        break;
+      #elseif ( $field.type == "int" )
+                        ${classLcapName}.${field.name}(getIntegerValue(v));
+                        break;
+      #elseif ( $field.type == "DOM" )
+//                        
${classLcapName}.${field.name}(XmlNodeBuilder.build(parser, true));
+                        break;
+      #elseif ( $field.type == "java.util.List" && $field.to == "String" && 
$field.multiplicity == "*" )
+                        ${classLcapName}.${field.name}(getStringList(v));
+                        break;
+      #elseif ( $field.type == "java.util.Properties" && $field.to == "String" 
&& $field.multiplicity == "*" )
+                        ${classLcapName}.${field.name}(getStringMap(v));
+                        break;
+      #elseif ( $field.to && $field.multiplicity == "1" )
+                        
${classLcapName}.${field.name}(parse${field.toClass.name}(v));
+                        break;
+      #elseif ( $field.to && $field.multiplicity == "*" && 
$Helper.isFlatItems( $field ) )
+                        ${field.name}.add(parse${field.toClass.name}(v));
+                        break;
+      #elseif ( $field.to && $field.multiplicity == "*" )
+                        ${classLcapName}.${field.name}(getList(v, 
this::parse${field.toClass.name}));
+                        break;
+      #else
+                        // TODO: type=${field.type} to=${field.to} 
multiplicity=${field.multiplicity}
+                        break;
+      #end
+                    }
+    #end
+  #end
+                    default: {
+                        checkUnknownElement(k, v);
+                        break;
+                    }
+                }
+            });
+  #foreach ( $field in $allFields )
+    #if ( $Helper.isFlatItems( $field ) )
+            ${classLcapName}.${field.name}(${field.name});
+    #end
+  #end
+            return ${classLcapName}.build();
+  #if($class.name=="Dependency")
+        } else if (value != null && value.valueType() == 
ConfigValueType.STRING) {
+            Dependency.Builder dependency = Dependency.newBuilder(true);
+            String[] tokens = ((String) value.unwrapped()).split(":");
+            if (tokens.length < 3 || tokens.length > 5) {
+                throw new RuntimeException("Invalid artifact, you must specify 
"
+                        + "groupId:artifactId:version[:packaging[:classifier]] 
" + value);
+            }
+            dependency.groupId(tokens[0]);
+            dependency.artifactId(tokens[1]);
+            dependency.version(tokens[2]);
+            if (tokens.length >= 4) {
+                dependency.type(tokens[3]);
+            }
+            if (tokens.length == 5) {
+                dependency.classifier(tokens[4]);
+            }
+            return dependency.build();
+    #end
+        } else if (value != null) {
+            throw new IllegalArgumentException("Invalid syntax: cannot parse: 
" + value);
+        }
+        return null;
+    }
+
+ #end
+#end
+
+    protected String getStringValue(ConfigValue v) {
+        return v.unwrapped().toString();
+    }
+
+    protected List<String> getStringList(ConfigValue v) {
+        if (v instanceof ConfigList) {
+            return ((ConfigList) v).unwrapped().stream().map(Object::toString)
+                .collect(Collectors.toList());
+        }
+        throw new IllegalArgumentException("Unable to convert to List<String>: 
'" + v + "'");
+    }
+
+    protected boolean getBooleanValue(ConfigValue v) {
+        return Boolean.parseBoolean(v.unwrapped().toString());
+    }
+
+    protected int getIntegerValue(ConfigValue v) {
+        return Integer.parseInt(v.unwrapped().toString());
+    }
+
+    protected ConfigList getList(ConfigValue v) {
+        if (v instanceof ConfigList) {
+            return (ConfigList) v;
+        }
+        throw new IllegalArgumentException("Unable to convert to List<?>: '" + 
v + "'");
+    }
+
+    protected <T> List<T> getList(ConfigValue v, Function<ConfigValue, T> 
parser) {
+        return getList(v).stream().map(parser).collect(Collectors.toList());
+    }
+
+    protected Map<String, String> getStringMap(ConfigValue v) {
+        if (v instanceof ConfigObject) {
+            return ((ConfigObject) 
v).entrySet().stream().collect(Collectors.toMap(
+                e -> e.getKey(),
+                e -> getStringValue(e.getValue())
+            ));
+        }
+        throw new IllegalArgumentException("Unable to convert to Map<String, 
String>: '" + v + "'");
+    }
+
+    protected void checkUnknownElement(String k, Object v) {
+        throw new IllegalArgumentException("Unrecognized element '" + k + "' 
with value '" + v + "'");
+    }
+
+}
diff --git a/src/test/java/org/apache/maven/hocon/ParsingTest.java 
b/src/test/java/org/apache/maven/hocon/ParsingTest.java
new file mode 100644
index 0000000..6f611af
--- /dev/null
+++ b/src/test/java/org/apache/maven/hocon/ParsingTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.hocon;
+
+import java.io.File;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import org.apache.maven.api.model.Model;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ParsingTest {
+
+    @Test
+    void testParse() throws Exception {
+        Config config = ConfigFactory.parseFile(new 
File("src/test/resources/pom.hocon"));
+
+        Model model = new HoconReader().parseModel(config.root());
+
+        assertEquals("40", model.getParent().getVersion());
+        assertEquals(1, model.getDependencies().size());
+        assertEquals(2, model.getProperties().size());
+    }
+}
diff --git a/src/test/resources/pom.hocon b/src/test/resources/pom.hocon
new file mode 100644
index 0000000..c51b554
--- /dev/null
+++ b/src/test/resources/pom.hocon
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+modelVersion = 4.0.0
+parent {
+    groupId =  org.apache.maven.extensions
+    artifactId = maven-extensions
+    version = 40
+}
+groupId = org.apache.maven.extensions
+artifactId = maven-hocon-extension
+version = 1.0.0-SNAPSHOT
+
+properties = {
+  "my.property" = foo
+  pluginVersion = 3.9
+}
+
+dependencies = [
+    { groupId =  org.apache.maven, artifactId = maven-api-core, version = 
4.0.0-alpha-8-SNAPSHOT }
+]
\ No newline at end of file


Reply via email to