1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.cli2.option;
18
19 import java.util.Collections;
20 import java.util.Comparator;
21 import java.util.List;
22 import java.util.ListIterator;
23 import java.util.Set;
24 import java.util.StringTokenizer;
25
26 import org.apache.commons.cli2.Argument;
27 import org.apache.commons.cli2.DisplaySetting;
28 import org.apache.commons.cli2.HelpLine;
29 import org.apache.commons.cli2.Option;
30 import org.apache.commons.cli2.OptionException;
31 import org.apache.commons.cli2.WriteableCommandLine;
32 import org.apache.commons.cli2.resource.ResourceConstants;
33 import org.apache.commons.cli2.resource.ResourceHelper;
34 import org.apache.commons.cli2.validation.InvalidArgumentException;
35 import org.apache.commons.cli2.validation.Validator;
36
37
38
39
40 public class ArgumentImpl
41 extends OptionImpl implements Argument {
42 private static final char NUL = '\0';
43
44
45
46
47 public static final char DEFAULT_INITIAL_SEPARATOR = NUL;
48
49
50
51
52 public static final char DEFAULT_SUBSEQUENT_SEPARATOR = NUL;
53
54
55
56
57
58 public static final String DEFAULT_CONSUME_REMAINING = "--";
59 private final String name;
60 private final String description;
61 private final int minimum;
62 private final int maximum;
63 private final char initialSeparator;
64 private final char subsequentSeparator;
65 private final boolean subsequentSplit;
66 private final Validator validator;
67 private final String consumeRemaining;
68 private final List defaultValues;
69 private final ResourceHelper resources = ResourceHelper.getResourceHelper();
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 public ArgumentImpl(final String name,
98 final String description,
99 final int minimum,
100 final int maximum,
101 final char initialSeparator,
102 final char subsequentSeparator,
103 final Validator validator,
104 final String consumeRemaining,
105 final List valueDefaults,
106 final int id) {
107 super(id, false);
108
109 this.name = (name == null) ? "arg" : name;
110 this.description = description;
111 this.minimum = minimum;
112 this.maximum = maximum;
113 this.initialSeparator = initialSeparator;
114 this.subsequentSeparator = subsequentSeparator;
115 this.subsequentSplit = subsequentSeparator != NUL;
116 this.validator = validator;
117 this.consumeRemaining = consumeRemaining;
118 this.defaultValues = valueDefaults;
119
120 if (minimum > maximum) {
121 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_MIN_EXCEEDS_MAX));
122 }
123
124 if ((valueDefaults != null) && (valueDefaults.size() > 0)) {
125 if (valueDefaults.size() < minimum) {
126 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_TOO_FEW_DEFAULTS));
127 }
128
129 if (valueDefaults.size() > maximum) {
130 throw new IllegalArgumentException(resources.getMessage(ResourceConstants.ARGUMENT_TOO_MANY_DEFAULTS));
131 }
132 }
133 }
134
135 public String getPreferredName() {
136 return name;
137 }
138
139 public void processValues(final WriteableCommandLine commandLine,
140 final ListIterator arguments,
141 final Option option)
142 throws OptionException {
143
144 int argumentCount = commandLine.getUndefaultedValues(option).size();
145
146 while (arguments.hasNext() && (argumentCount < maximum)) {
147 final String allValuesQuoted = (String) arguments.next();
148 final String allValues = stripBoundaryQuotes(allValuesQuoted);
149
150
151 if (allValuesQuoted.equals(consumeRemaining)) {
152 while (arguments.hasNext() && (argumentCount < maximum)) {
153 ++argumentCount;
154 commandLine.addValue(option, arguments.next());
155 }
156 }
157
158 else if (commandLine.looksLikeOption(allValuesQuoted)) {
159 arguments.previous();
160
161 break;
162 }
163
164 else if (subsequentSplit) {
165 final StringTokenizer values =
166 new StringTokenizer(allValues, String.valueOf(subsequentSeparator));
167
168 arguments.remove();
169
170 while (values.hasMoreTokens() && (argumentCount < maximum)) {
171 ++argumentCount;
172
173 final String token = values.nextToken();
174 commandLine.addValue(option, token);
175 arguments.add(token);
176 }
177
178 if (values.hasMoreTokens()) {
179 throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
180 values.nextToken());
181 }
182 }
183
184 else {
185 ++argumentCount;
186 commandLine.addValue(option, allValues);
187 }
188 }
189 }
190
191 public boolean canProcess(final WriteableCommandLine commandLine,
192 final String arg) {
193 return true;
194 }
195
196 public Set getPrefixes() {
197 return Collections.EMPTY_SET;
198 }
199
200 public void process(WriteableCommandLine commandLine,
201 ListIterator args)
202 throws OptionException {
203 processValues(commandLine, args, this);
204 }
205
206 public char getInitialSeparator() {
207 return this.initialSeparator;
208 }
209
210 public char getSubsequentSeparator() {
211 return this.subsequentSeparator;
212 }
213
214 public Set getTriggers() {
215 return Collections.EMPTY_SET;
216 }
217
218 public String getConsumeRemaining() {
219 return this.consumeRemaining;
220 }
221
222 public List getDefaultValues() {
223 return this.defaultValues;
224 }
225
226 public Validator getValidator() {
227 return this.validator;
228 }
229
230 public void validate(final WriteableCommandLine commandLine)
231 throws OptionException {
232 validate(commandLine, this);
233 }
234
235 public void validate(final WriteableCommandLine commandLine,
236 final Option option)
237 throws OptionException {
238 final List values = commandLine.getValues(option);
239
240 if (values.size() < minimum) {
241 throw new OptionException(option, ResourceConstants.ARGUMENT_MISSING_VALUES);
242 }
243
244 if (values.size() > maximum) {
245 throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
246 (String) values.get(maximum));
247 }
248
249 if (validator != null) {
250 try {
251 validator.validate(values);
252 } catch (InvalidArgumentException ive) {
253 throw new OptionException(option, ResourceConstants.ARGUMENT_UNEXPECTED_VALUE,
254 ive.getMessage());
255 }
256 }
257 }
258
259 public void appendUsage(final StringBuffer buffer,
260 final Set helpSettings,
261 final Comparator comp) {
262
263 final boolean optional = helpSettings.contains(DisplaySetting.DISPLAY_OPTIONAL);
264
265
266 final boolean numbered =
267 (maximum > 1) && helpSettings.contains(DisplaySetting.DISPLAY_ARGUMENT_NUMBERED);
268
269 final boolean bracketed = helpSettings.contains(DisplaySetting.DISPLAY_ARGUMENT_BRACKETED);
270
271
272 final int max = (maximum == Integer.MAX_VALUE) ? 2 : maximum;
273
274 int i = 0;
275
276
277 while (i < max) {
278
279 if (i > 0) {
280 buffer.append(' ');
281 }
282
283
284 if ((i >= minimum) && (optional || (i > 0))) {
285 buffer.append('[');
286 }
287
288 if (bracketed) {
289 buffer.append('<');
290 }
291
292
293 buffer.append(name);
294 ++i;
295
296
297 if (numbered) {
298 buffer.append(i);
299 }
300
301 if (bracketed) {
302 buffer.append('>');
303 }
304 }
305
306
307 if (maximum == Integer.MAX_VALUE) {
308
309 buffer.append(" ...");
310 }
311
312
313 while (i > 0) {
314 --i;
315
316
317 if ((i >= minimum) && (optional || (i > 0))) {
318 buffer.append(']');
319 }
320 }
321 }
322
323 public String getDescription() {
324 return description;
325 }
326
327 public List helpLines(final int depth,
328 final Set helpSettings,
329 final Comparator comp) {
330 final HelpLine helpLine = new HelpLineImpl(this, depth);
331
332 return Collections.singletonList(helpLine);
333 }
334
335 public int getMaximum() {
336 return maximum;
337 }
338
339 public int getMinimum() {
340 return minimum;
341 }
342
343
344
345
346
347
348
349
350
351
352 public String stripBoundaryQuotes(String token) {
353 if (!token.startsWith("\"") || !token.endsWith("\"")) {
354 return token;
355 }
356
357 token = token.substring(1, token.length() - 1);
358
359 return token;
360 }
361
362 public boolean isRequired() {
363 return getMinimum() > 0;
364 }
365
366 public void defaults(final WriteableCommandLine commandLine) {
367 super.defaults(commandLine);
368 defaultValues(commandLine, this);
369 }
370
371 public void defaultValues(final WriteableCommandLine commandLine,
372 final Option option) {
373 commandLine.setDefaultValues(option, defaultValues);
374 }
375 }