ApacheのCommons CLIでコマンドラインオプション解析をする。

#Apache Commons CLIとは
コマンドラインオプションを解析するAPIです。

例えば、hoge.jarを実行する際に3つのオプションがあるとします。
java -jar /usr/local/hoge.jar user age mail

で、このうち
・userはオプションを2つ取りたい
・age（年齢）は必須にしたい
・オプションが間違っている場合は指定するオプション情報（ヘルプ）を返したい

という要望に答えてくれるAPIがApache Commons CLIです。

# 導入してみる
次の環境にて導入してみました。
・java 1.8
・maven構成

```pom.xml
	<dependency>
	    <groupId>commons-cli</groupId>
	    <artifactId>commons-cli</artifactId>
	    <version>1.4</version>
	</dependency>
```

```main.java

    	// コマンドラインオプションの設定
        Options options = new Options();

        // 設定方法1
        // 引数名(-t), 引数を取得するか否か, 説明
        options.addOption("m", true, "メールアドレス");

        // 設定方法2
        // 引数毎にオプションを設定する

        Options.addOption(Option.builder("u")     // オプションの名前
        .argName("serviceid"))                    // 引数名
        .hasArg(2)                                // 引数を2つとる。
        .desc("ユーザー")                          // 説明
        .build());                                // インスタンスを生成

        Options.addOption(Option.builder("a")
        .argName("age"))
        .required()                               // 必須
        .hasArg()
        .desc("年齢")
        .build());

        // オプションのヘルプ情報を表示する。
        HelpFormatter hf = new HelpFormatter();
        hf.printHelp("[opts]", options);

        // コマンドライン解析
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = null;
        try {
			cmd = parser.parse(options, args);
		} catch (ParseException e) {
			log.error("cmd parser failed." , e);
		}

        // ユーザー
        cmd.hasOption("u");
		log.info("ユーザー["+String.join(",", cmd.getOptionValues("u"))+"]");

		// 年齢
        cmd.hasOption("a");
		log.info("年齢["+String.join(",", cmd.getOptionValues("a"))+"]");

		// メールアドレス
		cmd.hasOption("m");
		log.info("メールアドレス["+String.join(",", cmd.getOptionValues("m"))+"]");
```
次の引数で実行してみる。
-a 18 -u edy jeff -m hogehoge@mail.jp

```console.log
usage: [opts]
 -a <age>    年齢
 -m <arg>    メールアドレス
 -u <user>   ユーザー
INFO App - ユーザー[edy,jeff] (App.java:67)
INFO App - 年齢[18] (App.java:71)
INFO App - メールアドレス[hogehoge@mail.jp] (App.java:75)

```
オプション情報も表示され、指定した引数分取得している事がわかる。

ちなみに、必須項目の年齢を抜いてみると

```console.log
usage: [opts]
 -a <age>    年齢
 -m <arg>    メールアドレス
 -u <user>   ユーザー
ERROR App - cmd parser failed. (App.java:62)
org.apache.commons.cli.MissingOptionException: Missing required option: a
	at org.apache.commons.cli.DefaultParser.checkRequiredOptions(DefaultParser.java:199)
	at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:130)
	at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:76)
	at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:60)
	at free_dom.test.App.main(App.java:60)
Exception in thread "main" java.lang.NullPointerException
	at free_dom.test.App.main(App.java:66)

```
"a"オプションが無いよとOutputしてくれる。

バッチを作る際にこういうAPIが欲しいと思っていたので次から使ってみようと思います。
今更ではありますが(*´Д｀)

# 20190218 追記
Commons CLI1.3以降ではOptionBuilderを使うことは非推奨となっておりました。
このため、ソース部分も修正致しました。

```
OptionBuilder.withArgName("user").
              hasArgs(2).
              withDescription("ユーザー").
              create("u");
```

代わりに、Option.builderを使います。

```
Option.builder("u")
      .argName("user"))
      .hasArgs(2)
      .desc("ユーザー")
      .build()
```