总结这些选项需要具备的关系:
-
-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 互相允许)。
像[-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(" "));
}
}