Skip to content

Commit f436985

Browse files
committed
New unified parser (CLI-181, also fixes CLI-160, CLI-161, CLI-167, CLI-184)
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/cli/trunk@780264 13f79535-47bb-0310-9956-ffa450edef68
1 parent 135281e commit f436985

9 files changed

Lines changed: 910 additions & 3 deletions

File tree

src/java/org/apache/commons/cli/DefaultParser.java

Lines changed: 590 additions & 0 deletions
Large diffs are not rendered by default.

src/java/org/apache/commons/cli/Option.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ private void processValue(String value)
465465
*/
466466
private void add(String value)
467467
{
468-
if ((numberOfArgs > 0) && (values.size() > (numberOfArgs - 1)))
468+
if (!acceptsArg())
469469
{
470470
throw new RuntimeException("Cannot add value, list full.");
471471
}
@@ -671,4 +671,36 @@ public boolean addValue(String value)
671671
+ "Subclasses should use the addValueForProcessing method instead. ");
672672
}
673673

674+
/**
675+
* Tells if the option can accept more arguments.
676+
*
677+
* @return false if the maximum number of arguments is reached
678+
* @since 1.3
679+
*/
680+
boolean acceptsArg()
681+
{
682+
return (hasArg() || hasArgs() || hasOptionalArg()) && (numberOfArgs <= 0 || values.size() < numberOfArgs);
683+
}
684+
685+
/**
686+
* Tells if the option requires more arguments to be valid.
687+
*
688+
* @return false if the option doesn't require more arguments
689+
* @since 1.3
690+
*/
691+
boolean requiresArg()
692+
{
693+
if (optionalArg)
694+
{
695+
return false;
696+
}
697+
if (numberOfArgs == UNLIMITED_VALUES)
698+
{
699+
return values.size() < 1;
700+
}
701+
else
702+
{
703+
return acceptsArg();
704+
}
705+
}
674706
}

src/java/org/apache/commons/cli/Options.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,7 @@ public List getMatchingOptions(String opt)
243243
* Returns whether the named {@link Option} is a member of this {@link Options}.
244244
*
245245
* @param opt short or long name of the {@link Option}
246-
* @return true if the named {@link Option} is a member
247-
* of this {@link Options}
246+
* @return true if the named {@link Option} is a member of this {@link Options}
248247
*/
249248
public boolean hasOption(String opt)
250249
{
@@ -253,6 +252,34 @@ public boolean hasOption(String opt)
253252
return shortOpts.containsKey(opt) || longOpts.containsKey(opt);
254253
}
255254

255+
/**
256+
* Returns whether the named {@link Option} is a member of this {@link Options}.
257+
*
258+
* @param opt long name of the {@link Option}
259+
* @return true if the named {@link Option} is a member of this {@link Options}
260+
* @since 1.3
261+
*/
262+
public boolean hasLongOption(String opt)
263+
{
264+
opt = Util.stripLeadingHyphens(opt);
265+
266+
return longOpts.containsKey(opt);
267+
}
268+
269+
/**
270+
* Returns whether the named {@link Option} is a member of this {@link Options}.
271+
*
272+
* @param opt short name of the {@link Option}
273+
* @return true if the named {@link Option} is a member of this {@link Options}
274+
* @since 1.3
275+
*/
276+
public boolean hasShortOption(String opt)
277+
{
278+
opt = Util.stripLeadingHyphens(opt);
279+
280+
return shortOpts.containsKey(opt);
281+
}
282+
256283
/**
257284
* Returns the OptionGroup the <code>opt</code> belongs to.
258285
* @param opt the option whose OptionGroup is being queried.

src/test/org/apache/commons/cli/BasicParserTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ public void setUp()
2929
parser = new BasicParser();
3030
}
3131

32+
public void testDoubleDash2() throws Exception
33+
{
34+
// not supported by the BasicParser
35+
}
36+
37+
public void testLongWithoutEqualSingleDash() throws Exception
38+
{
39+
// not supported by the BasicParser
40+
}
41+
42+
public void testAmbiguousLongWithoutEqualSingleDash() throws Exception
43+
{
44+
// not supported by the basicParser
45+
}
46+
47+
public void testNegativeOption() throws Exception
48+
{
49+
// not supported by the BasicParser (CLI-184)
50+
}
51+
3252
public void testPropertiesOption1() throws Exception
3353
{
3454
// not supported by the BasicParser
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.commons.cli;
19+
20+
/**
21+
* @author Emmanuel Bourg
22+
* @version $Revision$, $Date$
23+
*/
24+
public class DefaultParserTest extends ParserTestCase {
25+
26+
public void setUp() {
27+
super.setUp();
28+
parser = new DefaultParser();
29+
}
30+
}

src/test/org/apache/commons/cli/GnuParserTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,41 @@ public void setUp()
2525
parser = new GnuParser();
2626
}
2727

28+
public void testDoubleDash2() throws Exception
29+
{
30+
// not supported by the GnuParser
31+
}
32+
33+
public void testLongWithoutEqualSingleDash() throws Exception
34+
{
35+
// not supported by the GnuParser
36+
}
37+
38+
public void testAmbiguousLongWithoutEqualSingleDash() throws Exception
39+
{
40+
// not supported by the GnuParser
41+
}
42+
43+
public void testNegativeOption() throws Exception
44+
{
45+
// not supported by the GnuParser (CLI-184)
46+
}
47+
48+
public void testLongWithUnexpectedArgument1() throws Exception
49+
{
50+
// not supported by the GnuParser
51+
}
52+
53+
public void testLongWithUnexpectedArgument2() throws Exception
54+
{
55+
// not supported by the GnuParser
56+
}
57+
58+
public void testShortWithUnexpectedArgument() throws Exception
59+
{
60+
// not supported by the GnuParser
61+
}
62+
2863
public void testUnambiguousPartialLongOption1() throws Exception
2964
{
3065
// not supported by the GnuParser

src/test/org/apache/commons/cli/ParserTestCase.java

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,24 @@ public void testDoubleDash1() throws Exception
157157
assertTrue("Confirm 2 extra args: " + cl.getArgList().size(), cl.getArgList().size() == 2);
158158
}
159159

160+
public void testDoubleDash2() throws Exception
161+
{
162+
Options options = new Options();
163+
options.addOption(OptionBuilder.hasArg().create('n'));
164+
options.addOption(OptionBuilder.create('m'));
165+
166+
try
167+
{
168+
parser.parse(options, new String[]{"-n", "--", "-m"});
169+
fail("MissingArgumentException not thrown for option -n");
170+
}
171+
catch (MissingArgumentException e)
172+
{
173+
assertNotNull("option null", e.getOption());
174+
assertEquals("n", e.getOption().getOpt());
175+
}
176+
}
177+
160178
public void testSingleDash() throws Exception
161179
{
162180
String[] args = new String[] { "--copt",
@@ -228,6 +246,16 @@ public void testNegativeArgument() throws Exception
228246
assertEquals("-1", cl.getOptionValue("b"));
229247
}
230248

249+
public void testNegativeOption() throws Exception
250+
{
251+
String[] args = new String[] { "-b", "-1"} ;
252+
253+
options.addOption("1", false, null);
254+
255+
CommandLine cl = parser.parse(options, args);
256+
assertEquals("-1", cl.getOptionValue("b"));
257+
}
258+
231259
public void testArgumentStartingWithHyphen() throws Exception
232260
{
233261
String[] args = new String[]{"-b", "-foo"};
@@ -284,6 +312,105 @@ public void testLongWithEqualSingleDash() throws Exception
284312
assertEquals("bar", cl.getOptionValue("foo"));
285313
}
286314

315+
public void testLongWithoutEqualSingleDash() throws Exception
316+
{
317+
String[] args = new String[] { "-foobar" };
318+
319+
Options options = new Options();
320+
options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
321+
322+
CommandLine cl = parser.parse(options, args);
323+
324+
assertEquals("bar", cl.getOptionValue("foo"));
325+
}
326+
327+
public void testAmbiguousLongWithoutEqualSingleDash() throws Exception
328+
{
329+
String[] args = new String[] { "-b", "-foobar" };
330+
331+
Options options = new Options();
332+
options.addOption(OptionBuilder.withLongOpt("foo").hasOptionalArg().create('f'));
333+
options.addOption(OptionBuilder.withLongOpt("bar").hasOptionalArg().create('b'));
334+
335+
CommandLine cl = parser.parse(options, args);
336+
337+
assertTrue(cl.hasOption("b"));
338+
assertTrue(cl.hasOption("f"));
339+
assertEquals("bar", cl.getOptionValue("foo"));
340+
}
341+
342+
public void testLongWithoutEqualDoubleDash() throws Exception
343+
{
344+
String[] args = new String[] { "--foobar" };
345+
346+
Options options = new Options();
347+
options.addOption(OptionBuilder.withLongOpt("foo").hasArg().create('f'));
348+
349+
CommandLine cl = parser.parse(options, args, true);
350+
351+
assertFalse(cl.hasOption("foo")); // foo isn't expected to be recognized with a double dash
352+
}
353+
354+
public void testLongWithUnexpectedArgument1() throws Exception
355+
{
356+
String[] args = new String[] { "--foo=bar" };
357+
358+
Options options = new Options();
359+
options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
360+
361+
try
362+
{
363+
parser.parse(options, args);
364+
}
365+
catch (UnrecognizedOptionException e)
366+
{
367+
assertEquals("--foo=bar", e.getOption());
368+
return;
369+
}
370+
371+
fail("UnrecognizedOptionException not thrown");
372+
}
373+
374+
public void testLongWithUnexpectedArgument2() throws Exception
375+
{
376+
String[] args = new String[] { "-foobar" };
377+
378+
Options options = new Options();
379+
options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
380+
381+
try
382+
{
383+
parser.parse(options, args);
384+
}
385+
catch (UnrecognizedOptionException e)
386+
{
387+
assertEquals("-foobar", e.getOption());
388+
return;
389+
}
390+
391+
fail("UnrecognizedOptionException not thrown");
392+
}
393+
394+
public void testShortWithUnexpectedArgument() throws Exception
395+
{
396+
String[] args = new String[] { "-f=bar" };
397+
398+
Options options = new Options();
399+
options.addOption(OptionBuilder.withLongOpt("foo").create('f'));
400+
401+
try
402+
{
403+
parser.parse(options, args);
404+
}
405+
catch (UnrecognizedOptionException e)
406+
{
407+
assertEquals("-f=bar", e.getOption());
408+
return;
409+
}
410+
411+
fail("UnrecognizedOptionException not thrown");
412+
}
413+
287414
public void testPropertiesOption1() throws Exception
288415
{
289416
String[] args = new String[] { "-Jsource=1.5", "-J", "target", "1.5", "foo" };
@@ -726,4 +853,20 @@ public void testStopBursting2() throws Exception
726853
assertTrue("Confirm 1 extra arg: " + cl.getArgList().size(), cl.getArgList().size() == 1);
727854
assertTrue("Confirm value of extra arg: " + cl.getArgList().get(0), cl.getArgList().get(0).equals("foobar"));
728855
}
856+
857+
public void testUnlimitedArgs() throws Exception
858+
{
859+
String[] args = new String[]{"-e", "one", "two", "-f", "alpha"};
860+
861+
Options options = new Options();
862+
options.addOption(OptionBuilder.hasArgs().create("e"));
863+
options.addOption(OptionBuilder.hasArgs().create("f"));
864+
865+
CommandLine cl = parser.parse(options, args);
866+
867+
assertTrue("Confirm -e is set", cl.hasOption("e"));
868+
assertEquals("number of arg for -e", 2, cl.getOptionValues("e").length);
869+
assertTrue("Confirm -f is set", cl.hasOption("f"));
870+
assertEquals("number of arg for -f", 1, cl.getOptionValues("f").length);
871+
}
729872
}

src/test/org/apache/commons/cli/PosixParserTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@ public void setUp()
3030
parser = new PosixParser();
3131
}
3232

33+
public void testDoubleDash2() throws Exception
34+
{
35+
// not supported by the PosixParser
36+
}
37+
38+
public void testLongWithoutEqualSingleDash() throws Exception
39+
{
40+
// not supported by the PosixParser
41+
}
42+
43+
public void testAmbiguousLongWithoutEqualSingleDash() throws Exception
44+
{
45+
// not supported by the PosixParser
46+
}
47+
48+
public void testNegativeOption() throws Exception
49+
{
50+
// not supported by the PosixParser (CLI-184)
51+
}
52+
53+
public void testLongWithUnexpectedArgument1() throws Exception
54+
{
55+
// not supported by the PosixParser
56+
}
57+
3358
public void testLongWithEqualSingleDash() throws Exception
3459
{
3560
// not supported by the PosixParser

0 commit comments

Comments
 (0)