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