Skip to content

Commit 7f90b98

Browse files
author
John Keyes
committed
OptionBuilder first cut
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/cli/trunk@129791 13f79535-47bb-0310-9956-ffa450edef68
1 parent 70a7b5f commit 7f90b98

4 files changed

Lines changed: 303 additions & 5 deletions

File tree

project.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,12 @@
5454

5555
</dependencies>
5656

57+
<build>
58+
<!-- Unit test classes -->
59+
<unitTest>
60+
<includes>
61+
<include>**/*Test*.java</include>
62+
</includes>
63+
</unitTest>
64+
</build>
5765
</project>

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

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,53 @@ public class Option {
116116
private ArrayList values = new ArrayList();
117117

118118

119+
private void validateOption( String opt )
120+
throws IllegalArgumentException
121+
{
122+
if( opt == null ) {
123+
throw new IllegalArgumentException( "opt is null" );
124+
}
125+
else if( opt.length() == 1 ) {
126+
if ( !isValidOpt( opt.charAt( 0 ) ) ) {
127+
throw new IllegalArgumentException( "illegal option value '"
128+
+ opt.charAt( 0 ) + "'" );
129+
}
130+
}
131+
else {
132+
char[] chars = opt.toCharArray();
133+
for( int i = 0; i < chars.length; i++ ) {
134+
if( !isValidChar( chars[i] ) ) {
135+
throw new IllegalArgumentException( "opt contains illegal character value '" + chars[i] + "'" );
136+
}
137+
}
138+
}
139+
}
140+
141+
private boolean isValidOpt( char c )
142+
{
143+
if ( ! ( isValidChar( c ) || c == '?' || c == '@') ) {
144+
return false;
145+
}
146+
return true;
147+
}
148+
149+
private boolean isValidChar( char c )
150+
{
151+
if ( ! ( Character.isLetter( c ) ) ) {
152+
return false;
153+
}
154+
return true;
155+
}
119156
/**
120157
* Creates an Option using the specified parameters.
121158
*
122159
* @param opt short representation of the option
123160
* @param hasArg specifies whether the Option takes an argument or not
124161
* @param description describes the function of the option
125162
*/
126-
public Option(String opt, boolean hasArg, String description) {
163+
public Option(String opt, boolean hasArg, String description)
164+
throws IllegalArgumentException
165+
{
127166
this(opt, null, hasArg, description, false, false);
128167
}
129168

@@ -135,7 +174,9 @@ public Option(String opt, boolean hasArg, String description) {
135174
* @param hasArg specifies whether the Option takes an argument or not
136175
* @param description describes the function of the option
137176
*/
138-
public Option(String opt, String longOpt, boolean hasArg, String description) {
177+
public Option(String opt, String longOpt, boolean hasArg, String description)
178+
throws IllegalArgumentException
179+
{
139180
this(opt, longOpt, hasArg, description, false, false );
140181
}
141182

@@ -149,7 +190,9 @@ public Option(String opt, String longOpt, boolean hasArg, String description) {
149190
* @param required specifies whether the option is required or not
150191
*/
151192
public Option(String opt, String longOpt, boolean hasArg, String description,
152-
boolean required ) {
193+
boolean required )
194+
throws IllegalArgumentException
195+
{
153196
this(opt, longOpt, hasArg, description, required, false );
154197
}
155198

@@ -165,7 +208,9 @@ public Option(String opt, String longOpt, boolean hasArg, String description,
165208
* values
166209
*/
167210
public Option(String opt, String longOpt, boolean hasArg, String description,
168-
boolean required, boolean multipleArgs ) {
211+
boolean required, boolean multipleArgs )
212+
throws IllegalArgumentException
213+
{
169214
this(opt, longOpt, hasArg, description, required, multipleArgs, null );
170215
}
171216

@@ -182,7 +227,11 @@ public Option(String opt, String longOpt, boolean hasArg, String description,
182227
* @param type specifies the type of the option
183228
*/
184229
public Option(String opt, String longOpt, boolean hasArg, String description,
185-
boolean required, boolean multipleArgs, Object type ) {
230+
boolean required, boolean multipleArgs, Object type )
231+
throws IllegalArgumentException
232+
{
233+
validateOption( opt );
234+
186235
this.opt = opt;
187236
this.longOpt = longOpt;
188237
this.hasArg = hasArg;
@@ -213,6 +262,10 @@ public String getOpt() {
213262
public Object getType() {
214263
return this.type;
215264
}
265+
266+
public void setType( Object type ) {
267+
this.type = type;
268+
}
216269

217270
/** <p>Retrieve the long name of this Option</p>
218271
*
@@ -221,6 +274,10 @@ public Object getType() {
221274
public String getLongOpt() {
222275
return this.longOpt;
223276
}
277+
278+
public void setLongOpt( String longOpt ) {
279+
this.longOpt = longOpt;
280+
}
224281

225282
/** <p>Query to see if this Option has a long name</p>
226283
*
@@ -254,6 +311,10 @@ public boolean isRequired() {
254311
return this.required;
255312
}
256313

314+
public void setRequired( boolean required ) {
315+
this.required = required;
316+
}
317+
257318
/** <p>Query to see if this Option can take multiple values</p>
258319
*
259320
* @return boolean flag indicating if multiple values are allowed
@@ -262,6 +323,10 @@ public boolean hasMultipleArgs() {
262323
return this.multipleArgs;
263324
}
264325

326+
public void setMultipleArgs( boolean multipleArgs ) {
327+
this.multipleArgs = multipleArgs;
328+
}
329+
265330
/** <p>Dump state, suitable for debugging.</p>
266331
*
267332
* @return Stringified form of this object
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.apache.commons.cli;
2+
3+
public class OptionBuilder {
4+
5+
private static String longopt;
6+
private static String description;
7+
private static boolean arg;
8+
private static boolean required;
9+
private static boolean multipleArgs;
10+
private static Object type;
11+
12+
private static OptionBuilder instance = new OptionBuilder();
13+
14+
// private constructor
15+
private OptionBuilder() {
16+
}
17+
18+
private static void reset() {
19+
description = null;
20+
longopt = null;
21+
type = null;
22+
arg = false;
23+
required = false;
24+
multipleArgs = false;
25+
}
26+
27+
public static OptionBuilder withLongOpt( String longopt ) {
28+
instance.longopt = longopt;
29+
return instance;
30+
}
31+
32+
public static OptionBuilder hasArg( ) {
33+
instance.arg = true;
34+
return instance;
35+
}
36+
37+
public static OptionBuilder isRequired( ) {
38+
instance.required = true;
39+
return instance;
40+
}
41+
42+
public static OptionBuilder hasMultipleArgs( ) {
43+
instance.multipleArgs = true;
44+
return instance;
45+
}
46+
47+
public static OptionBuilder withType( Object type ) {
48+
instance.type = type;
49+
return instance;
50+
}
51+
52+
public static OptionBuilder withDescription( String description ) {
53+
instance.description = description;
54+
return instance;
55+
}
56+
57+
public static Option create( char opt )
58+
throws IllegalArgumentException
59+
{
60+
return create( String.valueOf( opt ) );
61+
}
62+
63+
public static Option create( String opt )
64+
throws IllegalArgumentException
65+
{
66+
Option option = new Option( opt, arg, description );
67+
option.setLongOpt( longopt );
68+
option.setRequired( required );
69+
option.setMultipleArgs( multipleArgs );
70+
option.setType( type );
71+
instance.reset();
72+
return option;
73+
}
74+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package org.apache.commons.cli;
2+
3+
import junit.framework.Test;
4+
import junit.framework.TestCase;
5+
import junit.framework.TestSuite;
6+
7+
import junit.textui.TestRunner;
8+
9+
public class OptionBuilderTest extends TestCase {
10+
11+
public OptionBuilderTest( String name ) {
12+
super( name );
13+
}
14+
15+
public static Test suite() {
16+
return new TestSuite( OptionBuilderTest.class );
17+
}
18+
19+
public static void main( String args[] ) {
20+
TestRunner.run( suite() );
21+
}
22+
23+
public void testCompleteOption( ) {
24+
Option simple = OptionBuilder.withLongOpt( "simple option")
25+
.hasArg( )
26+
.isRequired( )
27+
.hasMultipleArgs( )
28+
.withType( new Float( 10 ) )
29+
.withDescription( "this is a simple option" )
30+
.create( 's' );
31+
32+
assertEquals( "s", simple.getOpt() );
33+
assertEquals( "simple option", simple.getLongOpt() );
34+
assertEquals( "this is a simple option", simple.getDescription() );
35+
assertEquals( simple.getType().getClass(), Float.class );
36+
assertTrue( simple.hasArg() );
37+
assertTrue( simple.isRequired() );
38+
assertTrue( simple.hasMultipleArgs() );
39+
}
40+
41+
public void testTwoCompleteOptions( ) {
42+
Option simple = OptionBuilder.withLongOpt( "simple option")
43+
.hasArg( )
44+
.isRequired( )
45+
.hasMultipleArgs( )
46+
.withType( new Float( 10 ) )
47+
.withDescription( "this is a simple option" )
48+
.create( 's' );
49+
50+
assertEquals( "s", simple.getOpt() );
51+
assertEquals( "simple option", simple.getLongOpt() );
52+
assertEquals( "this is a simple option", simple.getDescription() );
53+
assertEquals( simple.getType().getClass(), Float.class );
54+
assertTrue( simple.hasArg() );
55+
assertTrue( simple.isRequired() );
56+
assertTrue( simple.hasMultipleArgs() );
57+
58+
simple = OptionBuilder.withLongOpt( "dimple option")
59+
.hasArg( )
60+
.withDescription( "this is a dimple option" )
61+
.create( 'd' );
62+
63+
assertEquals( "d", simple.getOpt() );
64+
assertEquals( "dimple option", simple.getLongOpt() );
65+
assertEquals( "this is a dimple option", simple.getDescription() );
66+
assertNull( simple.getType() );
67+
assertTrue( simple.hasArg() );
68+
assertTrue( !simple.isRequired() );
69+
assertTrue( !simple.hasMultipleArgs() );
70+
}
71+
72+
public void testBaseOptionCharOpt() {
73+
Option base = OptionBuilder.withDescription( "option description")
74+
.create( 'o' );
75+
76+
assertEquals( "o", base.getOpt() );
77+
assertEquals( "option description", base.getDescription() );
78+
assertTrue( !base.hasArg() );
79+
}
80+
81+
public void testBaseOptionStringOpt() {
82+
Option base = OptionBuilder.withDescription( "option description")
83+
.create( "o" );
84+
85+
assertEquals( "o", base.getOpt() );
86+
assertEquals( "option description", base.getDescription() );
87+
assertTrue( !base.hasArg() );
88+
}
89+
90+
public void testSpecialOptChars() {
91+
92+
// '?'
93+
try {
94+
Option opt = OptionBuilder.withDescription( "help options" )
95+
.create( '?' );
96+
assertEquals( "?", opt.getOpt() );
97+
}
98+
catch( IllegalArgumentException arg ) {
99+
fail( "IllegalArgumentException caught" );
100+
}
101+
102+
// '@'
103+
try {
104+
Option opt = OptionBuilder.withDescription( "read from stdin" )
105+
.create( '@' );
106+
assertEquals( "@", opt.getOpt() );
107+
}
108+
catch( IllegalArgumentException arg ) {
109+
fail( "IllegalArgumentException caught" );
110+
}
111+
}
112+
113+
public void testIllegalOptions() {
114+
// bad single character option
115+
try {
116+
Option opt = OptionBuilder.withDescription( "option description" )
117+
.create( '"' );
118+
fail( "IllegalArgumentException not caught" );
119+
}
120+
catch( IllegalArgumentException exp ) {
121+
// success
122+
}
123+
124+
// bad character in option string
125+
try {
126+
Option opt = OptionBuilder.create( "opt`" );
127+
fail( "IllegalArgumentException not caught" );
128+
}
129+
catch( IllegalArgumentException exp ) {
130+
// success
131+
}
132+
133+
// null option
134+
try {
135+
Option opt = OptionBuilder.create( null );
136+
fail( "IllegalArgumentException not caught" );
137+
}
138+
catch( IllegalArgumentException exp ) {
139+
// success
140+
}
141+
142+
// valid option
143+
try {
144+
Option opt = OptionBuilder.create( "opt" );
145+
// success
146+
}
147+
catch( IllegalArgumentException exp ) {
148+
fail( "IllegalArgumentException caught" );
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)