1
2
3
4
5
6 package gov.nist.secauto.metaschema.cli.processor.command;
7
8 import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
9 import gov.nist.secauto.metaschema.cli.processor.InvalidArgumentException;
10 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
11
12 import org.apache.commons.cli.CommandLine;
13 import org.apache.commons.cli.Option;
14
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.stream.Collectors;
18
19 import edu.umd.cs.findbugs.annotations.NonNull;
20 import edu.umd.cs.findbugs.annotations.Nullable;
21
22
23
24
25 public interface ICommand {
26
27
28
29
30
31
32
33 @NonNull
34 String getName();
35
36
37
38
39
40
41
42
43 @NonNull
44 String getDescription();
45
46
47
48
49
50
51 @NonNull
52 default List<ExtraArgument> getExtraArguments() {
53 return CollectionUtil.emptyList();
54 }
55
56
57
58
59
60
61 @NonNull
62 default Collection<? extends Option> gatherOptions() {
63
64 return CollectionUtil.emptyList();
65 }
66
67
68
69
70
71
72 @NonNull
73 default Collection<ICommand> getSubCommands() {
74
75 return CollectionUtil.emptyList();
76 }
77
78
79
80
81
82
83
84
85 @Nullable
86 default ICommand getSubCommandByName(@NonNull String name) {
87
88 return null;
89 }
90
91
92
93
94
95
96 default boolean isSubCommandRequired() {
97
98 return false;
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112 default void validateOptions(
113 @NonNull CallingContext callingContext,
114 @NonNull CommandLine commandLine) throws InvalidArgumentException {
115
116 }
117
118
119
120
121
122
123
124
125
126
127 @NonNull
128 ICommandExecutor newExecutor(
129 @NonNull CallingContext callingContext,
130 @NonNull CommandLine commandLine);
131
132
133
134
135
136
137
138
139
140
141
142 default void validateExtraArguments(
143 @NonNull CallingContext callingContext,
144 @NonNull CommandLine commandLine)
145 throws InvalidArgumentException {
146
147 validateSubCommandRequirement();
148 validateArgumentCount(commandLine);
149 validateRequiredArguments(commandLine);
150 }
151
152 private void validateSubCommandRequirement() throws InvalidArgumentException {
153 if (isSubCommandRequired()) {
154 throw new InvalidArgumentException("Please choose a valid sub-command.");
155 }
156 }
157
158 private void validateArgumentCount(@NonNull CommandLine commandLine) throws InvalidArgumentException {
159 List<ExtraArgument> extraArguments = getExtraArguments();
160 int maxArguments = extraArguments.size();
161 List<String> actualArgs = commandLine.getArgList();
162
163 if (actualArgs.size() > maxArguments) {
164 throw new InvalidArgumentException(
165 String.format("Too many extra arguments provided. Expected at most %d, but got %d.",
166 maxArguments, actualArgs.size()));
167 }
168
169 }
170
171 private void validateRequiredArguments(@NonNull CommandLine commandLine) throws InvalidArgumentException {
172 List<String> actualArgs = commandLine.getArgList();
173 List<ExtraArgument> requiredExtraArguments = getExtraArguments().stream()
174 .filter(ExtraArgument::isRequired)
175 .collect(Collectors.toUnmodifiableList());
176
177 if (actualArgs.size() < requiredExtraArguments.size()) {
178 throw new InvalidArgumentException(
179 String.format("Missing required arguments: %s. Expected %d required arguments, but got %d.",
180 requiredExtraArguments.stream()
181 .map(arg -> "<" + arg.getName() + ">")
182 .collect(Collectors.joining(" ")),
183 requiredExtraArguments.size(),
184 actualArgs.size()));
185 }
186 }
187 }