Apache Commons CLI 的两个独占 OptionGroup
Two exclusive OptionGroup with Apache Commons CLI
我正在构建一个命令行 Java 应用程序,但我在使用 Apache Commons CLI 解析命令行参数时遇到问题。
我正在尝试涵盖我的场景,我需要有两个排他的命令行参数组,它们还有长 (--abc
) 和短 (-a
) 参数。
用例 1
- 短参数:
-d oracle -j jdbc:oracle:thin:@//host:port/databa
- 相同但参数较长:
-dialect oracle -jdbcUrl jdbc:oracle:thin:@//host:port/databa
用例 2:
- 短参数:
-d oracle -h host -p 1521 -s database -U user -P pwd
- 相同但参数较长:
-dialect oracle -host host -port 1521 -sid database -user user -password pwd
所以我用正确的 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)
结果:
-d oracle
:缺少必需的选项:[-j ...]、[-h ...、-p ...、-s ...、-U ...、-P ...]
-d oracle -jdbcUrl xxx
:缺少必需的选项:[-h ...、-p ...、-s ...、-U ...、-P ...]
-d oracle -h yyy
:缺少必需的选项:[-j ...]
但我想要的是以下内容:如果提供了 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 生成的帮助要好得多。
我正在构建一个命令行 Java 应用程序,但我在使用 Apache Commons CLI 解析命令行参数时遇到问题。
我正在尝试涵盖我的场景,我需要有两个排他的命令行参数组,它们还有长 (--abc
) 和短 (-a
) 参数。
用例 1
- 短参数:
-d oracle -j jdbc:oracle:thin:@//host:port/databa
- 相同但参数较长:
-dialect oracle -jdbcUrl jdbc:oracle:thin:@//host:port/databa
用例 2:
- 短参数:
-d oracle -h host -p 1521 -s database -U user -P pwd
- 相同但参数较长:
-dialect oracle -host host -port 1521 -sid database -user user -password pwd
所以我用正确的 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)
结果:
-d oracle
:缺少必需的选项:[-j ...]、[-h ...、-p ...、-s ...、-U ...、-P ...]-d oracle -jdbcUrl xxx
:缺少必需的选项:[-h ...、-p ...、-s ...、-U ...、-P ...]-d oracle -h yyy
:缺少必需的选项:[-j ...]
但我想要的是以下内容:如果提供了 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 生成的帮助要好得多。