Better handling of enums by the command-line argument system.

git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@2647 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
hanna 2010-01-20 21:36:46 +00:00
parent 9c7b281b4f
commit d25a2fe120
9 changed files with 67 additions and 26 deletions

View File

@ -116,7 +116,7 @@ public class GATKArgumentCollection {
public Integer downsampleCoverage = null;
@Element(required = false)
@Argument(fullName = "validation_strictness", shortName = "S", doc = "How strict should we be with validation (LENIENT|SILENT|STRICT)", required = false)
@Argument(fullName = "validation_strictness", shortName = "S", doc = "How strict should we be with validation", required = false)
public SAMFileReader.ValidationStringency strictnessLevel = SAMFileReader.ValidationStringency.SILENT;
@Element(required = false)
@ -138,7 +138,7 @@ public class GATKArgumentCollection {
/** What rule should we use when merging intervals */
@Element(required = false)
@Argument(fullName = "interval_merging", shortName = "im", doc = "What interval merging rule should we use {ALL [DEFAULT],OVERLAPPING_ONLY,NONE}.", required = false)
@Argument(fullName = "interval_merging", shortName = "im", doc = "What interval merging rule should we use.", required = false)
public IntervalMergingRule intervalMerging = IntervalMergingRule.ALL;
/** Should we enable rodWalkers? This is currently unsafe */

View File

@ -159,7 +159,8 @@ public class GenotypeWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
false,
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source) );
getValidationRegex(source),
null );
}
/**
@ -175,6 +176,7 @@ public class GenotypeWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
false,
false,
null,
null,
null );
}

View File

@ -118,7 +118,8 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
false,
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source) );
getValidationRegex(source),
null );
}
/**
@ -134,6 +135,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
false,
false,
null,
null,
null );
}
}

View File

@ -34,7 +34,7 @@ public class TextFormattingUtils {
* @return A list of word-wrapped lines.
*/
public static List<String> wordWrap( String text, int width ) {
Pattern wrapper = Pattern.compile( String.format(".{0,%d}(?:\\S(?: |$)|$)", width-1) );
Pattern wrapper = Pattern.compile( String.format(".{0,%d}(?:\\S(?:[\\s|]|$)|$)", width-1) );
Matcher matcher = wrapper.matcher( text );
List<String> wrapped = new ArrayList<String>();

View File

@ -27,6 +27,9 @@ package org.broadinstitute.sting.utils.cmdLine;
import org.broadinstitute.sting.utils.Utils;
import java.util.List;
import java.util.Collections;
/**
* A specific argument definition. Maps one-to-one with a field in some class.
*/
@ -71,6 +74,11 @@ public class ArgumentDefinition {
*/
public final String validation;
/**
* A list of valid options for this argument, if there is a compelling subset.
*/
public final List<String> validOptions;
/**
* Creates a new argument definition.
* @param fullName Full name for this argument definition.
@ -81,6 +89,7 @@ public class ArgumentDefinition {
* @param isMultiValued Whether or not this argument supports multiple values.
* @param exclusiveOf Whether this command line argument is mutually exclusive of other arguments.
* @param validation A regular expression for command-line argument validation.
* @param validOptions is there a particular list of options that's valid for this argument definition? List them if so, otherwise set this to null.
*/
public ArgumentDefinition( String fullName,
String shortName,
@ -89,7 +98,8 @@ public class ArgumentDefinition {
boolean isFlag,
boolean isMultiValued,
String exclusiveOf,
String validation ) {
String validation,
List<String> validOptions) {
this.fullName = fullName;
this.shortName = shortName;
this.doc = doc;
@ -98,16 +108,13 @@ public class ArgumentDefinition {
this.isMultiValued = isMultiValued;
this.exclusiveOf = exclusiveOf;
this.validation = validation;
this.validOptions = validOptions;
}
@Override
public int hashCode() {
int hashCode = fullName.hashCode();
if(shortName != null) hashCode ^= shortName.hashCode();
if(doc != null) hashCode ^= doc.hashCode();
hashCode ^= Boolean.valueOf(required).hashCode();
if(exclusiveOf != null) hashCode ^= exclusiveOf.hashCode();
if(validation != null) hashCode ^= validation.hashCode();
return hashCode;
}
@ -120,12 +127,6 @@ public class ArgumentDefinition {
ArgumentDefinition other = (ArgumentDefinition)o;
return Utils.equals(fullName,other.fullName) &&
Utils.equals(shortName,other.shortName) &&
Utils.equals(doc,other.doc) &&
required == other.required &&
isFlag == other.isFlag &&
isMultiValued == other.isMultiValued &&
Utils.equals(exclusiveOf,other.exclusiveOf) &&
Utils.equals(validation,other.validation);
Utils.equals(shortName,other.shortName);
}
}

View File

@ -129,7 +129,8 @@ public abstract class ArgumentTypeDescriptor {
source.isFlag(),
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source) );
getValidationRegex(source),
getValidOptions(source) );
}
protected abstract Object parse( ArgumentSource source, Class type, ArgumentMatches matches );
@ -196,6 +197,21 @@ public abstract class ArgumentTypeDescriptor {
return description.validation().trim().length() > 0 ? description.validation().trim() : null;
}
/**
* If the argument source only accepts a small set of options, populate the returned list with
* those options. Otherwise, leave the list empty.
* @param source
* @return
*/
protected List<String> getValidOptions( ArgumentSource source ) {
if(!source.field.getType().isEnum())
return null;
List<String> validOptions = new ArrayList<String>();
for(Object constant: source.field.getType().getEnumConstants())
validOptions.add(constant.toString());
return validOptions;
}
/**
* Gets the value of an argument with the given full name, from the collection of ArgumentMatches.
* If the argument matches multiple values, an exception will be thrown.
@ -284,7 +300,7 @@ class SimpleArgumentTypeDescriptor extends ArgumentTypeDescriptor {
// TODO: Clean this up so that null values never make it to this point. To fix this, we'll have to clean up the implementation of -U.
if (value == null)
throw new MissingArgumentValueException(Collections.singleton(createDefaultArgumentDefinition(source)));
throw new UnknownEnumeratedValueException(value, type.getName());
throw new UnknownEnumeratedValueException(createDefaultArgumentDefinition(source),value);
} else {
Constructor ctor = type.getConstructor(String.class);
return ctor.newInstance(value);

View File

@ -40,7 +40,7 @@ public abstract class CommandLineProgram {
/** the default log level */
@Argument(fullName = "logging_level",
shortName = "l",
doc = "Set the minimum level of logging, i.e. setting INFO get's you INFO up to FATAL, setting ERROR gets you ERROR and FATAL level logging. (DEBUG, INFO, WARN, ERROR, FATAL, OFF). ",
doc = "Set the minimum level of logging, i.e. setting INFO get's you INFO up to FATAL, setting ERROR gets you ERROR and FATAL level logging.",
required = false)
protected String logging_level = "WARN";

View File

@ -3,6 +3,7 @@ package org.broadinstitute.sting.utils.cmdLine;
import org.broadinstitute.sting.utils.StingException;
import org.broadinstitute.sting.utils.Pair;
import org.broadinstitute.sting.utils.JVMUtils;
import org.broadinstitute.sting.utils.Utils;
import org.broadinstitute.sting.utils.help.ApplicationDetails;
import org.broadinstitute.sting.utils.help.HelpFormatter;
import org.apache.log4j.Logger;
@ -397,6 +398,8 @@ class MissingArgumentValueException extends ArgumentException {
sb.append( String.format("%nValue for argument with name '--%s' (-%s) is missing.", missingArgument.fullName, missingArgument.shortName) );
else
sb.append( String.format("%nValue for argument with name '--%s' is missing.", missingArgument.fullName) );
if(missingArgument.validOptions != null)
sb.append( String.format(" Valid options are (%s).", Utils.join(",",missingArgument.validOptions)));
}
return sb.toString();
}
@ -494,11 +497,11 @@ class ArgumentsAreMutuallyExclusiveException extends ArgumentException {
* An exception for when an argument doesn't match an of the enumerated options for that var type
*/
class UnknownEnumeratedValueException extends ArgumentException {
public UnknownEnumeratedValueException(String argumentPassed, String typeName ) {
super( formatArguments(argumentPassed, typeName) );
public UnknownEnumeratedValueException(ArgumentDefinition definition, String argumentPassed) {
super( formatArguments(definition,argumentPassed) );
}
private static String formatArguments(String argumentPassed, String typeName ) {
return new String("Enumerated constant " + argumentPassed + " Not found in type " + typeName);
private static String formatArguments(ArgumentDefinition definition, String argumentPassed) {
return String.format("Invalid value %s specified for argument %s; valid options are (%s).", argumentPassed, definition.fullName, Utils.join(",",definition.validOptions));
}
}

View File

@ -4,6 +4,7 @@ import org.broadinstitute.sting.utils.cmdLine.ArgumentDefinition;
import org.broadinstitute.sting.utils.cmdLine.ArgumentDefinitionGroup;
import org.broadinstitute.sting.utils.cmdLine.ArgumentDefinitions;
import org.broadinstitute.sting.utils.TextFormattingUtils;
import org.broadinstitute.sting.utils.Utils;
import org.apache.log4j.Logger;
import java.util.Formatter;
@ -83,7 +84,7 @@ public class HelpFormatter {
else
lineFormatter.format("--%s", argumentDefinition.fullName);
if( !argumentDefinition.isFlag )
lineFormatter.format(" <%s>", argumentDefinition.fullName);
lineFormatter.format(" <%s>", argumentDefinition.fullName);
if( !argumentDefinition.required ) lineFormatter.format("]");
}
}
@ -137,7 +138,7 @@ public class HelpFormatter {
for( ArgumentDefinition argumentDefinition: argumentDefinitions ) {
Iterator<String> wordWrappedArgs = TextFormattingUtils.wordWrap( getArgumentCallingInfo(argumentDefinition), argWidth ).iterator();
Iterator<String> wordWrappedDoc = TextFormattingUtils.wordWrap( argumentDefinition.doc, docWidth ).iterator();
Iterator<String> wordWrappedDoc = TextFormattingUtils.wordWrap( getArgumentDoc(argumentDefinition), docWidth ).iterator();
while( wordWrappedArgs.hasNext() || wordWrappedDoc.hasNext() ) {
String arg = wordWrappedArgs.hasNext() ? wordWrappedArgs.next() : "";
@ -170,6 +171,22 @@ public class HelpFormatter {
return builder.toString();
}
/**
* Gets a string of argument documentation.
* @param argumentDefinition Argument definition for which help should be printed.
* @return Brief description for this argument.
*/
private String getArgumentDoc( ArgumentDefinition argumentDefinition ) {
StringBuilder builder = new StringBuilder();
builder.append(argumentDefinition.doc);
if( argumentDefinition.validOptions != null ) {
builder.append(" (");
builder.append(Utils.join("|",argumentDefinition.validOptions));
builder.append(")");
}
return builder.toString();
}
/**
* Crude implementation which finds the longest argument portion
* given a set of arguments.