Argument validation.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@631 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
a3d8febbf2
commit
7f8850a8a2
|
|
@ -35,7 +35,6 @@ public abstract class Walker<MapType, ReduceType> {
|
|||
protected Walker() {
|
||||
if( GenomeAnalysisTK.Instance != null ) {
|
||||
GenomeAnalysisTK gatk = GenomeAnalysisTK.Instance;
|
||||
gatk.loadArgumentsIntoObject(this);
|
||||
out = new PrintStream( gatk.getOutputTracker().getOutStream() );
|
||||
err = new PrintStream( gatk.getOutputTracker().getErrStream() );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,4 +59,10 @@ public @interface Argument {
|
|||
* argument should be independent.
|
||||
*/
|
||||
String exclusiveOf() default "";
|
||||
|
||||
/**
|
||||
* Provide a regexp-based validation string.
|
||||
* @return Non-empty regexp for validation, blank otherwise.
|
||||
*/
|
||||
String validation() default "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,6 +152,12 @@ class ArgumentDefinitions implements Iterable<ArgumentDefinition> {
|
|||
return definition.required == (Boolean)key;
|
||||
}
|
||||
};
|
||||
|
||||
static DefinitionMatcher VerifiableDefinitionMatcher = new DefinitionMatcher() {
|
||||
public boolean matches( ArgumentDefinition definition, Object key ) {
|
||||
return definition.validation != null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -211,6 +217,11 @@ class ArgumentDefinition {
|
|||
*/
|
||||
public final String exclusiveOf;
|
||||
|
||||
/**
|
||||
* Can we validate this regular expression?
|
||||
*/
|
||||
public final String validation;
|
||||
|
||||
public final Class sourceClass;
|
||||
public final Field sourceField;
|
||||
|
||||
|
|
@ -229,6 +240,7 @@ class ArgumentDefinition {
|
|||
doc = argument.doc();
|
||||
required = argument.required() && !isFlag();
|
||||
exclusiveOf = argument.exclusiveOf().trim().length() > 0 ? argument.exclusiveOf().trim() : null;
|
||||
validation = argument.validation().trim().length() > 0 ? argument.validation().trim() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ public class ParsingEngine {
|
|||
|
||||
public enum ValidationType { MissingRequiredArgument,
|
||||
InvalidArgument,
|
||||
InvalidArgumentValue,
|
||||
ValueMissingArgument,
|
||||
TooManyValuesForArgument,
|
||||
MutuallyExclusive };
|
||||
|
|
@ -146,10 +147,29 @@ public class ParsingEngine {
|
|||
throw new InvalidArgumentException( invalidArguments );
|
||||
}
|
||||
|
||||
// Find invalid argument values (arguments that fail the regexp test.
|
||||
if( !skipValidationOf.contains(ValidationType.InvalidArgumentValue) ) {
|
||||
Collection<ArgumentDefinition> verifiableArguments =
|
||||
argumentDefinitions.findArgumentDefinitions( null, ArgumentDefinitions.VerifiableDefinitionMatcher );
|
||||
Collection<Pair<ArgumentDefinition,String>> invalidValues = new ArrayList<Pair<ArgumentDefinition,String>>();
|
||||
for( ArgumentDefinition verifiableArgument: verifiableArguments ) {
|
||||
Collection<ArgumentMatch> verifiableMatches = argumentMatches.findMatches( verifiableArgument );
|
||||
for( ArgumentMatch verifiableMatch: verifiableMatches ) {
|
||||
for( String value: verifiableMatch.values() ) {
|
||||
if( !value.matches(verifiableArgument.validation) )
|
||||
invalidValues.add( new Pair<ArgumentDefinition,String>(verifiableArgument, value) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( invalidValues.size() > 0 )
|
||||
throw new InvalidArgumentValueException( invalidValues );
|
||||
}
|
||||
|
||||
// Find values without an associated mate.
|
||||
if( !skipValidationOf.contains(ValidationType.ValueMissingArgument) ) {
|
||||
if( argumentMatches.MissingArgument.values().size() > 0 )
|
||||
throw new InvalidArgumentValueException( argumentMatches.MissingArgument );
|
||||
throw new UnmatchedArgumentException( argumentMatches.MissingArgument );
|
||||
}
|
||||
|
||||
// Find arguments with too many values.
|
||||
|
|
@ -457,10 +477,31 @@ class InvalidArgumentException extends ParseException {
|
|||
}
|
||||
|
||||
/**
|
||||
* An exception for values that can't be mated with any argument.
|
||||
* An exception for values whose format is invalid.
|
||||
*/
|
||||
class InvalidArgumentValueException extends ParseException {
|
||||
public InvalidArgumentValueException( ArgumentMatch invalidValues ) {
|
||||
public InvalidArgumentValueException( Collection<Pair<ArgumentDefinition,String>> invalidArgumentValues ) {
|
||||
super( formatArguments(invalidArgumentValues) );
|
||||
}
|
||||
|
||||
private static String formatArguments( Collection<Pair<ArgumentDefinition,String>> invalidArgumentValues ) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for( Pair<ArgumentDefinition,String> invalidValue: invalidArgumentValues ) {
|
||||
sb.append( String.format("%nArgument '--%s' has value of incorrect format: %s (should match %s)",
|
||||
invalidValue.first.fullName,
|
||||
invalidValue.second,
|
||||
invalidValue.first.validation) );
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An exception for values that can't be mated with any argument.
|
||||
*/
|
||||
class UnmatchedArgumentException extends ParseException {
|
||||
public UnmatchedArgumentException( ArgumentMatch invalidValues ) {
|
||||
super( formatArguments(invalidValues) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
public Integer bar;
|
||||
}
|
||||
|
||||
@Test(expected=InvalidArgumentValueException.class)
|
||||
@Test(expected=UnmatchedArgumentException.class)
|
||||
public void missingArgumentNameTest() {
|
||||
final String[] commandLine = new String[] {"foo.txt"};
|
||||
|
||||
|
|
@ -363,7 +363,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
|
||||
}
|
||||
|
||||
@Test(expected=InvalidArgumentValueException.class)
|
||||
@Test(expected=UnmatchedArgumentException.class)
|
||||
public void extraValueTest() {
|
||||
final String[] commandLine = new String[] {"-Ifoo.txt", "bar.txt"};
|
||||
|
||||
|
|
@ -446,7 +446,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
Integer myArg;
|
||||
}
|
||||
|
||||
@Test(expected=InvalidArgumentValueException.class)
|
||||
@Test(expected=UnmatchedArgumentException.class)
|
||||
public void booleanWithParameterTest() {
|
||||
final String[] commandLine = new String[] {"--mybool", "true"};
|
||||
|
||||
|
|
@ -461,7 +461,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testValidParseForAnalysisType() {
|
||||
public void validParseForAnalysisTypeTest() {
|
||||
final String[] commandLine = new String[] {"--analysis_type", "Pileup" };
|
||||
|
||||
parsingEngine.addArgumentSource( AnalysisTypeArgProvider.class );
|
||||
|
|
@ -480,7 +480,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
}
|
||||
|
||||
@Test(expected=TooManyValuesForArgumentException.class)
|
||||
public void testInvalidParseForAnalysisType() {
|
||||
public void invalidParseForAnalysisTypeTest() {
|
||||
final String[] commandLine = new String[] {"--analysis_type", "Pileup", "-TCountReads" };
|
||||
|
||||
parsingEngine.addArgumentSource( AnalysisTypeArgProvider.class );
|
||||
|
|
@ -489,7 +489,7 @@ public class ParsingEngineTest extends BaseTest {
|
|||
}
|
||||
|
||||
@Test(expected=ArgumentsAreMutuallyExclusiveException.class)
|
||||
public void testMutuallyExclusiveArguments() {
|
||||
public void mutuallyExclusiveArgumentsTest() {
|
||||
// Passing only foo should work fine...
|
||||
String[] commandLine = new String[] {"--foo","5"};
|
||||
|
||||
|
|
@ -516,4 +516,29 @@ public class ParsingEngineTest extends BaseTest {
|
|||
@Argument(doc="bar",required=false)
|
||||
Integer bar;
|
||||
}
|
||||
|
||||
@Test(expected=InvalidArgumentValueException.class)
|
||||
public void argumentValidationTest() {
|
||||
// Passing only foo should work fine...
|
||||
String[] commandLine = new String[] {"--value","521"};
|
||||
|
||||
parsingEngine.addArgumentSource( ValidatingArgProvider.class );
|
||||
parsingEngine.parse( commandLine );
|
||||
parsingEngine.validate();
|
||||
|
||||
ValidatingArgProvider argProvider = new ValidatingArgProvider();
|
||||
parsingEngine.loadArgumentsIntoObject( argProvider );
|
||||
|
||||
Assert.assertEquals("Argument is not correctly initialized", 521, argProvider.value.intValue() );
|
||||
|
||||
// Try some invalid arguments
|
||||
commandLine = new String[] {"--value","foo"};
|
||||
parsingEngine.parse( commandLine );
|
||||
parsingEngine.validate();
|
||||
}
|
||||
|
||||
private class ValidatingArgProvider {
|
||||
@Argument(doc="value",validation="\\d+")
|
||||
Integer value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue