Permalink
Browse files

added the possibility to mark options as required

  • Loading branch information...
1 parent 12c0e63 commit ea7ab994021b9b13b7a42c1d4e263278debf8b32 @emilssolmanis committed Apr 23, 2011
@@ -76,6 +76,8 @@ abstract void handleOption( OptionParser parser, ArgumentList arguments, OptionS
abstract boolean acceptsArguments();
abstract boolean requiresArgument();
+
+ abstract boolean isRequired();
abstract void accept( OptionSpecVisitor visitor );
@@ -58,7 +58,8 @@ a copy of this software and associated documentation files (the
*/
public abstract class ArgumentAcceptingOptionSpec<V> extends AbstractOptionSpec<V> {
private static final char NIL_VALUE_SEPARATOR = '\u0000';
-
+
+ private boolean optionRequired = false;
private final boolean argumentRequired;
private ValueConverter<V> converter;
private String argumentDescription = "";
@@ -195,6 +196,22 @@ a copy of this software and associated documentation files (the
return this;
}
+
+ /**
+ * <p>Marks this option as required. An {@link OptionRequiredException} will be thrown when
+ * {@link OptionParser.parse()} is called, if an option is marked as required and not specified
+ * on the command line.</p>
+ *
+ * @return self, so that the caller can add clauses to the fluent interface sentence
+ */
+ public ArgumentAcceptingOptionSpec<V> required() {
+ optionRequired = true;
+ return this;
+ }
+
+ protected boolean isRequired() {
+ return this.optionRequired;
+ }
private void addDefaultValue( V value ) {
ensureNotNull( value );
@@ -57,6 +57,11 @@ boolean acceptsArguments() {
}
@Override
+ boolean isRequired() {
+ return false; //don't see any use to ever require a flag-type option...
+ }
+
+ @Override
boolean requiresArgument() {
return false;
}
@@ -70,7 +75,7 @@ void accept( OptionSpecVisitor visitor ) {
protected Void convert( String argument ) {
return null;
}
-
+
@Override
List<Void> defaultValues() {
return emptyList();
@@ -25,23 +25,29 @@ a copy of this software and associated documentation files (the
package joptsimple;
+import static java.util.Collections.singletonList;
+import static joptsimple.OptionException.illegalOptionCluster;
+import static joptsimple.OptionException.unrecognizedOption;
+import static joptsimple.OptionParserState.moreOptions;
+import static joptsimple.ParserRules.RESERVED_FOR_EXTENSIONS;
+import static joptsimple.ParserRules.ensureLegalOptions;
+import static joptsimple.ParserRules.isLongOptionToken;
+import static joptsimple.ParserRules.isShortOptionToken;
+
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import joptsimple.internal.AbbreviationMap;
import joptsimple.util.KeyValuePair;
-import static java.util.Collections.*;
-import static joptsimple.OptionException.*;
-import static joptsimple.OptionParserState.*;
-import static joptsimple.ParserRules.*;
-
/**
* <p>Parses command line arguments, using a syntax that attempts to take from the best of POSIX {@code getopt()}
* and GNU {@code getopt_long()}.</p>
@@ -362,8 +368,27 @@ public OptionSet parse( String... arguments ) {
state.handleArgument( this, argumentList, detected );
reset();
+
+ ensureRequiredOptions(detected);
+
return detected;
}
+
+ private void ensureRequiredOptions(OptionSet options) {
+ Collection<AbstractOptionSpec<?>> recognizedSpecs = recognizedOptions.toJavaUtilMap().values();
+ Iterator<AbstractOptionSpec<?>> itRecognizedSpecs = recognizedSpecs.iterator();
+ Collection<String> notFoundOptionsSet = new HashSet<String>();
+
+ while (itRecognizedSpecs.hasNext()) {
+ AbstractOptionSpec<?> curr = itRecognizedSpecs.next();
+ if (curr.isRequired() && !options.has(curr)) {
+ notFoundOptionsSet.addAll(curr.options());
+ }
+ }
+ if (!notFoundOptionsSet.isEmpty()) {
+ throw new OptionRequiredException(notFoundOptionsSet);
+ }
+ }
void handleLongOptionToken( String candidate, ArgumentList arguments, OptionSet detected ) {
KeyValuePair optionAndArgument = parseLongOptionWithArgument( candidate );
@@ -0,0 +1,23 @@
+package joptsimple;
+
+import java.util.Collection;
+
+
+/**
+ * <p>Thrown when an option is marked as required, but not specified in the parser's input</p>
+ *
+ * @author <a href="https://github.com/TC1">Emils Solmanis</a>
+ */
+class OptionRequiredException extends OptionException {
+
+ private static final long serialVersionUID = -84650363723336432L;
+
+ protected OptionRequiredException(Collection<String> options) {
+ super(options);
+ }
+
+ @Override
+ public String getMessage() {
+ return "Option " + multipleOptionMessage() + " is required";
+ }
+}
@@ -251,4 +251,11 @@ public void shouldAllowEmbeddedWhitespaceInArgumentOfOption() {
assertOptionDetected( options, "j" );
assertEquals( embeddedWhitespace, optionJ.value( options ) );
}
+
+ @Test(expected = OptionRequiredException.class)
+ public void requiredOptionWithArgMissing() {
+ OptionSpec<String> option = parser.accepts("t").withOptionalArg().required();
+ OptionSet options = parser.parse("");
+ }
+
}

0 comments on commit ea7ab99

Please sign in to comment.