-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathCommand.java
253 lines (223 loc) · 9.02 KB
/
Command.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.matter.controller.commands.common;
import java.util.ArrayList;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nullable;
/**
* @brief Matter Controller command
* @details The base class of all the commands the Matter Controller supports, which are actions
* that may be performed. Commands are verb-like, such as pair a Matter device or discover
* Matter devices from the environment.
*/
public abstract class Command {
private static final String OPTIONAL_ARGUMENT_PREFIX = "--";
private static final int OPTIONAL_ARGUMENT_PREFIX_LENGTH = 2;
private final String mName;
private final ArrayList<Argument> mArgs = new ArrayList<Argument>();
private final Optional<String> mHelpText;
public Command(String commandName) {
this.mName = commandName;
this.mHelpText = Optional.empty();
}
public Command(String commandName, @Nullable String helpText) {
this.mName = commandName;
this.mHelpText = Optional.ofNullable(helpText);
}
public final String getName() {
return mName;
}
public final Optional<String> getHelpText() {
return mHelpText;
}
/**
* @brief Get attribute argument if it exists, there is at most one Attribute argument per command
* @return A pointer to an Optional where the Attribute argument will be stored
*/
public final Optional<String> getAttribute() {
return mArgs
.stream()
.filter(arg -> arg.getType() == ArgumentType.ATTRIBUTE)
.findFirst()
.map(arg -> (String) arg.getValue());
}
public final String getArgumentName(int index) {
return mArgs.get(index).getName();
}
public final int getArgumentsCount() {
return mArgs.size();
}
public final boolean getArgumentIsOptional(int index) {
return mArgs.get(index).isOptional();
}
/**
* @brief Get argument description if it exists
* @return A pointer to an Optional where the argument description will be stored
*/
public final Optional<String> getArgumentDescription(int index) {
return mArgs.get(index).getDesc();
}
public final void addArgumentToList(Argument arg, boolean optional) {
if (arg.isOptional() || mArgs.isEmpty()) {
// Safe to just append to the end of a list.
mArgs.add(arg);
return;
}
// mandatory arg needs to be inserted before the optional arguments.
int index = 0;
while (index < mArgs.size() && !mArgs.get(index).isOptional()) {
index++;
}
// Insert before the first optional arg.
mArgs.add(index, arg);
}
/**
* @brief Add a bool command argument
* @param name The name that will be displayed in the command help
* @param out A pointer to a MutableInteger where the argv value will be stored
* @param desc The description of the argument that will be displayed in the command help
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(
String name, AtomicBoolean out, @Nullable String desc, boolean optional) {
Argument arg = new Argument(name, out, desc, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Add a short command argument
* @param name The name that will be displayed in the command help
* @param min The minimum value of the argv value
* @param max The minimum value of the argv value
* @param out A pointer to a MutableInteger where the argv value will be stored
* @param desc The description of the argument that will be displayed in the command help
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(
String name,
short min,
short max,
AtomicInteger out,
@Nullable String desc,
boolean optional) {
Argument arg = new Argument(name, min, max, out, desc, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Add an int command argument
* @param name The name that will be displayed in the command help
* @param min The minimum value of the argv value
* @param max The minimum value of the argv value
* @param out A pointer to a MutableInteger where the argv value will be stored
* @param desc The description of the argument that will be displayed in the command help
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(
String name, int min, int max, AtomicInteger out, @Nullable String desc, boolean optional) {
Argument arg = new Argument(name, min, max, out, desc, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Add a long Integer command argument
* @param name The name that will be displayed in the command help
* @param min The minimum value of the argv value
* @param max The minimum value of the argv value
* @param out A pointer to a MutableInteger where the argv value will be stored
* @param desc The description of the argument that will be displayed in the command help
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(
String name, long min, long max, AtomicLong out, @Nullable String desc, boolean optional) {
Argument arg = new Argument(name, min, max, out, desc, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Add an IP address command argument
* @param name The name that will be displayed in the command help
* @param out A pointer to a IPAddress where the argv value will be stored
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(String name, IPAddress out, boolean optional) {
Argument arg = new Argument(name, out, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Add a String command argument
* @param name The name that will be displayed in the command help
* @param out A pointer to a StringBuffer where the argv value will be stored
* @param desc The description of the argument that will be displayed in the command help
* @param optional Indicate if an optional argument
* @return The number of arguments currently added to the command
*/
public final void addArgument(
String name, StringBuffer out, @Nullable String desc, boolean optional) {
Argument arg = new Argument(name, out, desc, optional);
addArgumentToList(arg, optional);
}
/**
* @brief Initialize command arguments
* @param argc The number of arguments to a command (Does not include command itself)
* @param args Supplied command-line arguments as an array of String objects.
*/
public final void initArguments(int argc, String[] args) {
int mandatoryArgsCount = 0;
int currentIndex = 0;
for (Argument arg : mArgs) {
if (!arg.isOptional()) {
mandatoryArgsCount++;
}
}
if (argc < mandatoryArgsCount) {
throw new IllegalArgumentException(
"initArguments: Wrong arguments number: " + argc + " instead of " + mandatoryArgsCount);
}
// Initialize mandatory arguments
for (int i = 0; i < mandatoryArgsCount; i++) {
initArgument(currentIndex++, args[i]);
}
// Initialize optional arguments
// Optional arguments expect a name and a value, so i is increased by 2 on every step.
for (int i = mandatoryArgsCount; i < argc; i += 2) {
// optional arguments starts with OPTIONAL_ARGUMENT_PREFIX
if (args[i].length() <= OPTIONAL_ARGUMENT_PREFIX_LENGTH
&& !args[i].startsWith(OPTIONAL_ARGUMENT_PREFIX)) {
throw new IllegalArgumentException("initArguments: Invalid optional argument: " + args[i]);
}
if (args[i]
.substring(OPTIONAL_ARGUMENT_PREFIX_LENGTH)
.equals(mArgs.get(currentIndex).getName())) {
if (i + 1 >= argc) {
throw new IllegalArgumentException(
"initArguments: Optional argument " + args[i] + " missing value");
}
initArgument(currentIndex++, args[i + 1]);
}
}
}
public void initArgument(int argIndex, String argValue) {
mArgs.get(argIndex).setValue(argValue);
}
public abstract void run() throws Exception;
}