Apache Commons CLI 的两个独占 OptionGroup

Two exclusive OptionGroup with Apache Commons CLI

我正在构建一个命令行 Java 应用程序,但我在使用 Apache Commons CLI 解析命令行参数时遇到问题。

我正在尝试涵盖我的场景,我需要有两个排他的命令行参数组,它们还有长 (--abc) 和短 (-a) 参数。

用例 1

用例 2:

所以我用正确的 Option 项创建了两个 OptionGroup

OptionGroup jdbcUrlGroup = new OptionGroup();
jdbcUrlGroup.setRequired(true);
jdbcUrlGroup.addOption(jdbcUrl);

第二组:

OptionGroup customConfigurationGroup = new OptionGroup();
customConfigurationGroup.setRequired(true);
customConfigurationGroup.addOption(host);
customConfigurationGroup.addOption(port);
customConfigurationGroup.addOption(sid);
customConfigurationGroup.addOption(user);
customConfigurationGroup.addOption(password);

然后我这样构建 Options 对象:

Options options = new Options();
options.addOptionGroup(jdbcUrlGroup);
options.addOptionGroup(customConfigurationGroup);
options.addOption(dialect);

但这不起作用,因为它希望同时定义两个组。

方言 Option 是这样定义的:

Option dialect = Option
        .builder("d")
        .longOpt("dialect")
        .required(false)
        .hasArg()
        .argName("DIALECT")
        .desc("supported SQL dialects: oracle. Default value: oracle")
        .build();

除了这个 属性:

之外,其他强制性 Option 定义看起来很相似
.required(true)

结果:

但我想要的是以下内容:如果提供了 JDBC URL,则不需要主机、端口等参数,或者相反。

我认为是时候忘记 Apache Commons CLI 并将其标记为已弃用的库。好吧,如果你只有几个命令行参数那么你可以使用它,否则最好不要使用。事实上,这个 Apache 项目最近(2019 年 2 月 17 日)进行了更新,但它仍然缺少许多功能,并且使用 Apache Commons CLI 库有点痛苦。

picocli project looks like a better candidate for parsing command line parameters. It is a quite intuitive library, easy to use, and has a nice and comprehensive documentation也是如此。我认为具有完善文档的中等评级工具优于没有任何文档的闪亮项目。

无论如何 picocli 是一个非常好的库,有完善的文档,所以我给它加倍加分 :)

这就是我用 picocli 涵盖我的用例的方式:

import picocli.CommandLine;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

@Command(name = "SqlRunner",
        sortOptions = false,
        usageHelpWidth = 100,
        description = "SQL command line tool. It executes the given SQL and show the result on the standard output.\n",
        parameterListHeading = "General options:\n",
        footerHeading = "\nPlease report issues at arnold.somogyi@gmail.com.",
        footer = "\nDocumentation, source code: https://github.com/zappee/sql-runner.git")
public class SqlRunner implements Runnable {

    /**
     * Definition of the general command line options.
     */
    @Option(names = {"-?", "--help"}, usageHelp = true, description = "Display this help and exit.")
    private boolean help;

    @Option(names = {"-d", "--dialect"}, defaultValue = "oracle", showDefaultValue = CommandLine.Help.Visibility.ALWAYS, description = "Supported SQL dialects: oracle.")
    private static String dialect;

    @ArgGroup(exclusive = true, multiplicity = "1", heading = "\nProvide a JDBC URL:\n")
    MainArgGroup mainArgGroup;

    /**
     * Two exclusive parameter groups:
     *    (1) JDBC URL parameter
     *    (2) Custom connection parameters
     */
    static class MainArgGroup {
        /**
         * JDBC URL option (only one parameter).
         */
        @Option(names = {"-j", "--jdbcUrl"}, arity = "1", description = "JDBC URL, example: jdbc:oracle:<drivertype>:@//<host>:<port>/<database>.")
        private static String jdbcUrl;

        /**
         * Custom connection parameter group.
         */
        @ArgGroup(exclusive = false, multiplicity = "1", heading = "\nCustom configuration:\n")
        CustomConfigurationGroup customConfigurationGroup;
    }

    /**
     * Definition of the SQL which will be executed.
     */
    @Parameters(index = "0", arity = "1", description = "SQL to be executed. Example: 'select 1 from dual'")
    String sql;

    /**
     * Custom connection parameters.
     */
    static class CustomConfigurationGroup {
        @Option(names = {"-h", "--host"}, required = true, description = "Name of the database server.")
        private static String host;

        @Option(names = {"-p", "--port"}, required = true, description = "Number of the port where the server listens for requests.")
        private static String port;

        @Option(names = {"-s", "--sid"}, required = true, description = "Name of the particular database on the server. Also known as the SID in Oracle terminology.")
        private static String sid;

        @Option(names = {"-U", "--user"}, required = true, description = "Name for the login.")
        private static String user;

        @Option(names = {"-P", "--password"}, required = true, description = "Password for the connecting user.")
        private static String password;
    }

    /**
     * The entry point of the executable JAR.
     *
     * @param args command line parameters
     */
    public static void main(String[] args) {
        CommandLine cmd = new CommandLine(new SqlRunner());
        int exitCode = cmd.execute(args);
        System.exit(exitCode);
    }

    /**
     * It is used to create a thread.
     */
    @Override
    public void run() {
        int exitCode = 0; //executeMyStaff();
        System.exit(exitCode);
    }
}

生成的帮助如下所示:

$ java -jar target/sql-runner-1.0-shaded.jar --help
Usage: SqlRunner [-?] [-d=<dialect>] (-j=<jdbcUrl> | (-h=<host> -p=<port> -s=<sid> -U=<user>
                 -P=<password>)) <sql>
SQL command line tool. It executes the given SQL and show the result on the standard output.

General settings:
      <sql>                 SQL to be executed. Example: 'select 1 from dual'
  -?, --help                Display this help and exit.
  -d, --dialect=<dialect>   Supported SQL dialects: oracle.
                              Default: oracle

Custom configuration:
  -h, --host=<host>         Name of the database server.
  -p, --port=<port>         Number of the port where the server listens for requests.
  -s, --sid=<sid>           Name of the particular database on the server. Also known as the SID in
                              Oracle terminology.
  -U, --user=<user>         Name for the login.
  -P, --password=<password> Password for the connecting user.

Provide a JDBC URL:
  -j, --jdbcUrl=<jdbcUrl>   JDBC URL, example: jdbc:oracle:<drivertype>:@//<host>:<port>/<database>.

Please report issues at arnold.somogyi@gmail.com.
Documentation, source code: https://github.com/zappee/sql-runner.git

这种外观比 Apache CLI 生成的帮助要好得多。