总结这些选项需要具备的关系:
-B
, -A1
,-A2
并且-A3
都需要该-A
选项
-B
不允许任何-A1
,-A2
和-A3
选项
- ,
-A1
和选项确实允许-A2
彼此-A3
- 该
-A
选项允许(但不要求)-B
、-A1
和选项-A2
-A3
仅 picocli 注释不足以以声明方式表达所有这些关系,需要一些自定义验证。
所以我们不妨简化并创建一个单独的参数组,因为我们不能同时表达要求 2(-B 与 -A1、-A2、-A3 互斥)和要求 1 和 3(-B、-A1、 -A2 和 -A3 都要求 -A 和 -A1,-A2,-A3 互相允许)。
单个组 like[-A [-B] [-A1] [-A2] [-A3]]
将负责一些验证:除要求 2 之外的所有内容(-B 与 -A1、-A2、-A3 互斥)。对于需求 2,我们需要在应用程序中编写一些自定义验证(示例如下)。
对于您的用例,拥有一个准确反映选项之间关系的自定义概要可能很有用。像这样的东西:
Usage: app [-hV] [-A [-B]]
app [-hV] [-A [-A1] [-A2] [-A3]]
实现此目的的示例代码:
import picocli.CommandLine;
import picocli.CommandLine.*;
import picocli.CommandLine.Model.CommandSpec;
@Command(name = "app", mixinStandardHelpOptions = true,
synopsisHeading = "",
customSynopsis = {
"Usage: app [-hV] [-A [-B]]",
" app [-hV] [-A [-A1] [-A2] [-A3]]",
})
public class App implements Runnable {
static class MyGroup {
@Option(names = "-A", required = true) boolean a;
@Option(names = "-B") boolean b;
@Option(names = "-A1") boolean a1;
@Option(names = "-A2") boolean a2;
@Option(names = "-A3") boolean a3;
boolean isInvalid() {
return b && (a1 || a2 || a3);
}
}
@ArgGroup(exclusive = false)
MyGroup myGroup;
@Spec CommandSpec spec;
public void run() {
if (myGroup != null && myGroup.isInvalid()) {
String msg = "Option -B is mutually exclusive with -A1, -A2 and -A3";
throw new ParameterException(spec.commandLine(), msg);
}
System.out.printf("OK: %s%n", spec.commandLine().getParseResult().originalArgs());
}
public static void main(String[] args) {
//new CommandLine(new App()).usage(System.out);
//test: these are all valid
new CommandLine(new App()).execute();
new CommandLine(new App()).execute("-A -B".split(" "));
// requires validation in the application to disallow
new CommandLine(new App()).execute("-A -B -A1".split(" "));
// picocli validates this, gives: "Error: Missing required argument(s): -A"
new CommandLine(new App()).execute("-B -A1".split(" "));
}
}