MavenのPOMをXMLを使わずに記述する

JJUG CCC 2019 fallの発表資料に目を通している中で、Mavenのpom.xmlをXMLを使わずに記述できるという発表があったので、サンプルコードを用意して実際に触ってみたいと思います。元の発表は[こちら](https://www.slideshare.net/kawasima/maven-196821326)を参照してください。

## polyglot-maven
XMLを使わずにPOMを設定するために[polyglot-maven](https://github.com/takari/polyglot-maven)というMavenのextensionを利用していきます。Maven3.3.1以上をサポートしています。
polyglot-mavenは、POMをXMLの他にも、Java, Kotlin, Clojure, Ruby, Groovy, Scala, Atom, YAMLで記述することができます。
今回はPOMをYAMLで記述するケースを紹介しますが、[各文法で記述されたサンプルコード](https://github.com/takari/polyglot-maven-examples)が公開されているので、他の文法が気になる方は参照してください。

## やってみる
### サンプルコード
今回は、サンプルコードとして以下のpom.xmlをpolyglot-mavenを使ってpom.yamlに変換していきたいと思います。
https://github.com/dais39/sample-polyglot-maven

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.dais39</groupId>
    <artifactId>sample-poliglot-maven</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>
```
### extensions.xmlを作成
プロジェクトルートに.mvnディレクトリを作成して、その配下にextensions.xmlを作成します。

```bash
$ mkdir .mvn
$ vim .mvn/extensions.xml
```

extensions.xmlのartifactIdには変換したい文法に応じたartifactIdを設定します。今回はYAMLに変換したいため、`polyglot-yaml`を設定します。他の文法については[こちら](https://github.com/takari/polyglot-maven#available-languages)を参照ください。

```xml:extensions.xml
<?xml version="1.0" encoding="UTF-8"?>
<extensions>
    <extension>
        <groupId>io.takari.polyglot</groupId>
        <artifactId>polyglot-yaml</artifactId>
        <version>0.4.4</version>
    </extension>
</extensions>
```

### pom.xmlを変換
プロジェクトルートで以下のコマンドを実行すると、pom.yamlが自動で生成されます。
`-Doutput=pom.yaml`は変換先の文法に合わせた拡張子を各自設定するようにしてください。

```bash
$ mvn io.takari.polyglot:polyglot-translate-plugin:translate -Dinput=pom.xml -Doutput=pom.yaml
```

```yaml:pom.yaml
modelEncoding: UTF-8
modelVersion: 4.0.0
groupId: com.dais39
artifactId: sample-poliglot-maven
version: 1.0-SNAPSHOT
packaging: jar

properties: {project.build.sourceEncoding: UTF-8}
```

以下のように`-Dinput`と`-Doutput`の値を逆に設定すれば、pom.yamlからpom.xmlに戻すこともできます。

```bash
$ mvn io.takari.polyglot:polyglot-translate-plugin:translate -Dinput=pom.yaml -Doutput=pom.xml
```

### 動作確認
pom.yamlを指定してmvnコマンドを実行すると、問題なくbuildが完了することを確認できます。

```bash
-> % mvn package -f pom.yaml

// 省略 

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.796 s
[INFO] Finished at: 2019-11-26T10:08:50+09:00
[INFO] ------------------------------------------------------------------------
```
## 参考

- polyglot-maven
https://github.com/takari/polyglot-maven

- 文法ごとのサンプルコード 
https://github.com/takari/polyglot-maven-examples

## おまけ
#### Ruby
```ruby:pom.rb
project 'sample-poliglot-maven' do

  model_version '4.0.0'
  id 'com.dais39:sample-poliglot-maven:1.0-SNAPSHOT'
  packaging 'jar'

  properties( 'project.build.sourceEncoding' => 'UTF-8' )

end
```
#### Java
```java:pom.java
public class pom extends org.sonatype.maven.polyglot.java.dsl.ModelFactory {
    public void project() {
        modelVersion = "4.0.0";
        groupId = "com.dais39";
        artifactId = "sample-poliglot-maven";
        packaging = "jar";
        version = "1.0-SNAPSHOT";
        properties(
            property("project.build.sourceEncoding", "UTF-8")
        );
    }
}
```
#### Kotlin
```kotlin:pom.kts
project("com.dais39:sample-poliglot-maven:1.0-SNAPSHOT:jar") {

    properties {
        "project.build.sourceEncoding" to "UTF-8"
    }
}
```