diff --git a/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java b/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java index 2e12a61f2..8babc3267 100755 --- a/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java +++ b/java/src/org/broadinstitute/sting/gatk/arguments/GATKArgumentCollection.java @@ -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 */ diff --git a/java/src/org/broadinstitute/sting/gatk/io/stubs/GenotypeWriterArgumentTypeDescriptor.java b/java/src/org/broadinstitute/sting/gatk/io/stubs/GenotypeWriterArgumentTypeDescriptor.java index 4b03394e8..67c15dec5 100644 --- a/java/src/org/broadinstitute/sting/gatk/io/stubs/GenotypeWriterArgumentTypeDescriptor.java +++ b/java/src/org/broadinstitute/sting/gatk/io/stubs/GenotypeWriterArgumentTypeDescriptor.java @@ -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 ); } diff --git a/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java b/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java index ced17f06e..d3baeed6f 100644 --- a/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java +++ b/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java @@ -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 ); } } diff --git a/java/src/org/broadinstitute/sting/utils/TextFormattingUtils.java b/java/src/org/broadinstitute/sting/utils/TextFormattingUtils.java index d8eb7c5d7..458626cbc 100644 --- a/java/src/org/broadinstitute/sting/utils/TextFormattingUtils.java +++ b/java/src/org/broadinstitute/sting/utils/TextFormattingUtils.java @@ -34,7 +34,7 @@ public class TextFormattingUtils { * @return A list of word-wrapped lines. */ public static List 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 wrapped = new ArrayList(); diff --git a/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentDefinition.java b/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentDefinition.java index f9151459d..5de20f7d9 100644 --- a/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentDefinition.java +++ b/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentDefinition.java @@ -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 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 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); } } diff --git a/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentTypeDescriptor.java b/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentTypeDescriptor.java index d2ee0e057..0ebf632ee 100644 --- a/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentTypeDescriptor.java +++ b/java/src/org/broadinstitute/sting/utils/cmdLine/ArgumentTypeDescriptor.java @@ -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 getValidOptions( ArgumentSource source ) { + if(!source.field.getType().isEnum()) + return null; + List validOptions = new ArrayList(); + 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); diff --git a/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java b/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java index eb56e63aa..d3b885253 100644 --- a/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java +++ b/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java @@ -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"; diff --git a/java/src/org/broadinstitute/sting/utils/cmdLine/ParsingEngine.java b/java/src/org/broadinstitute/sting/utils/cmdLine/ParsingEngine.java index bfd86f8e9..83408f8aa 100755 --- a/java/src/org/broadinstitute/sting/utils/cmdLine/ParsingEngine.java +++ b/java/src/org/broadinstitute/sting/utils/cmdLine/ParsingEngine.java @@ -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)); } } \ No newline at end of file diff --git a/java/src/org/broadinstitute/sting/utils/help/HelpFormatter.java b/java/src/org/broadinstitute/sting/utils/help/HelpFormatter.java index e7fd4983f..a57c9afe5 100755 --- a/java/src/org/broadinstitute/sting/utils/help/HelpFormatter.java +++ b/java/src/org/broadinstitute/sting/utils/help/HelpFormatter.java @@ -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 wordWrappedArgs = TextFormattingUtils.wordWrap( getArgumentCallingInfo(argumentDefinition), argWidth ).iterator(); - Iterator wordWrappedDoc = TextFormattingUtils.wordWrap( argumentDefinition.doc, docWidth ).iterator(); + Iterator 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.