2010-04-20 07:00:08 +08:00
/ *
* Copyright ( c ) 2010 The Broad Institute
2010-04-20 23:26:32 +08:00
*
2010-04-20 07:00:08 +08:00
* Permission is hereby granted , free of charge , to any person
* obtaining a copy of this software and associated documentation
2010-04-20 23:26:32 +08:00
* files ( the "Software" ) , to deal in the Software without
2010-04-20 07:00:08 +08:00
* restriction , including without limitation the rights to use ,
* copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following
* conditions :
2010-04-20 23:26:32 +08:00
*
2010-04-20 07:00:08 +08:00
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
2010-04-20 23:26:32 +08:00
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND ,
2010-04-20 07:00:08 +08:00
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY ,
* WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE .
* /
package org.broadinstitute.sting.commandline ;
2009-05-04 08:11:42 +08:00
import org.broadinstitute.sting.utils.StingException ;
2010-04-20 07:00:08 +08:00
import org.broadinstitute.sting.utils.collections.Pair ;
import org.broadinstitute.sting.utils.classloader.JVMUtils ;
2010-01-21 05:36:46 +08:00
import org.broadinstitute.sting.utils.Utils ;
2009-12-08 03:23:12 +08:00
import org.broadinstitute.sting.utils.help.ApplicationDetails ;
import org.broadinstitute.sting.utils.help.HelpFormatter ;
2009-05-05 06:41:23 +08:00
import org.apache.log4j.Logger ;
2009-05-04 08:11:42 +08:00
2009-07-13 09:42:13 +08:00
import java.lang.reflect.* ;
import java.util.* ;
2009-05-04 08:11:42 +08:00
/ * *
* A parser for Sting command - line arguments .
* /
public class ParsingEngine {
2009-07-30 00:11:45 +08:00
/ * *
* The command - line program at the heart of this parsing engine .
* /
CommandLineProgram clp = null ;
2009-05-04 08:11:42 +08:00
/ * *
* A list of defined arguments against which command lines are matched .
2009-05-06 06:08:00 +08:00
* Package protected for testing access .
2009-05-04 08:11:42 +08:00
* /
2009-05-06 06:08:00 +08:00
ArgumentDefinitions argumentDefinitions = new ArgumentDefinitions ( ) ;
2009-05-04 08:11:42 +08:00
2009-05-07 03:38:05 +08:00
/ * *
* A list of matches from defined arguments to command - line text .
* Indicates as best as possible where command - line text remains unmatched
* to existing arguments .
* /
ArgumentMatches argumentMatches = null ;
2009-05-05 06:41:23 +08:00
/ * *
* Techniques for parsing and for argument lookup .
* /
private List < ParsingMethod > parsingMethods = new ArrayList < ParsingMethod > ( ) ;
/ * *
* our log , which we want to capture anything from org . broadinstitute . sting
* /
2009-05-07 02:37:51 +08:00
protected static Logger logger = Logger . getLogger ( ParsingEngine . class ) ;
2009-05-05 06:41:23 +08:00
2009-07-30 00:11:45 +08:00
public ParsingEngine ( CommandLineProgram clp ) {
this . clp = clp ;
2009-08-23 08:56:02 +08:00
2009-05-18 00:09:32 +08:00
parsingMethods . add ( ParsingMethod . FullNameParsingMethod ) ;
parsingMethods . add ( ParsingMethod . ShortNameParsingMethod ) ;
2009-08-23 08:56:02 +08:00
// Null check for unit tests. Perhaps we should mock up an empty CLP?
if ( clp ! = null )
ArgumentTypeDescriptor . addDescriptors ( clp . getArgumentTypeDescriptors ( ) ) ;
2009-05-05 06:41:23 +08:00
}
2009-05-04 08:11:42 +08:00
/ * *
2009-05-07 05:16:01 +08:00
* Add a main argument source . Argument sources are expected to have
2009-05-04 08:11:42 +08:00
* any number of fields with an @Argument annotation attached .
2009-05-07 05:16:01 +08:00
* @param source An argument source from which to extract command - line arguments .
2009-05-04 08:11:42 +08:00
* /
2009-05-07 03:38:05 +08:00
public void addArgumentSource ( Class source ) {
2009-05-07 05:16:01 +08:00
addArgumentSource ( null , source ) ;
}
/ * *
* Add an argument source . Argument sources are expected to have
* any number of fields with an @Argument annotation attached .
* @param sourceName name for this argument source . ' Null ' indicates that this source should be treated
* as the main module .
2009-07-13 09:42:13 +08:00
* @param sourceClass A class containing argument sources from which to extract command - line arguments .
2009-05-07 05:16:01 +08:00
* /
2009-07-13 09:42:13 +08:00
public void addArgumentSource ( String sourceName , Class sourceClass ) {
2009-05-21 03:01:25 +08:00
List < ArgumentDefinition > argumentsFromSource = new ArrayList < ArgumentDefinition > ( ) ;
2009-09-30 06:23:19 +08:00
for ( ArgumentSource argumentSource : extractArgumentSources ( sourceClass ) )
2009-07-25 03:44:04 +08:00
argumentsFromSource . addAll ( argumentSource . createArgumentDefinitions ( ) ) ;
2009-05-07 05:16:01 +08:00
argumentDefinitions . add ( new ArgumentDefinitionGroup ( sourceName , argumentsFromSource ) ) ;
2009-05-04 08:11:42 +08:00
}
2009-05-18 08:42:00 +08:00
/ * *
* Do a cursory search to see if an argument with the given name is present .
* @param argumentFullName full name of the argument .
* @return True if the argument is present . False otherwise .
* /
public boolean isArgumentPresent ( String argumentFullName ) {
ArgumentDefinition definition =
argumentDefinitions . findArgumentDefinition ( argumentFullName , ArgumentDefinitions . FullNameDefinitionMatcher ) ;
return argumentMatches . hasMatch ( definition ) ;
}
2009-05-04 08:11:42 +08:00
/ * *
* Parse the given set of command - line arguments , returning
* an ArgumentMatches object describing the best fit of these
* command - line arguments to the arguments that are actually
* required .
2009-05-05 06:41:23 +08:00
* @param tokens Tokens passed on the command line .
2009-05-04 08:11:42 +08:00
* /
2009-05-07 03:38:05 +08:00
public void parse ( String [ ] tokens ) {
2009-07-13 09:42:13 +08:00
argumentMatches = new ArgumentMatches ( ) ;
int lastArgumentMatchSite = - 1 ;
for ( int i = 0 ; i < tokens . length ; i + + ) {
String token = tokens [ i ] ;
// If the token is of argument form, parse it into its own argument match.
// Otherwise, pair it with the most recently used argument discovered.
if ( isArgumentForm ( token ) ) {
ArgumentMatch argumentMatch = parseArgument ( token , i ) ;
if ( argumentMatch ! = null ) {
argumentMatches . mergeInto ( argumentMatch ) ;
lastArgumentMatchSite = i ;
}
}
else {
if ( argumentMatches . hasMatch ( lastArgumentMatchSite ) & &
! argumentMatches . getMatch ( lastArgumentMatchSite ) . hasValueAtSite ( lastArgumentMatchSite ) )
argumentMatches . getMatch ( lastArgumentMatchSite ) . addValue ( lastArgumentMatchSite , token ) ;
else
argumentMatches . MissingArgument . addValue ( i , token ) ;
}
}
2009-05-04 08:11:42 +08:00
}
2009-05-06 21:38:46 +08:00
public enum ValidationType { MissingRequiredArgument ,
InvalidArgument ,
2009-05-08 04:28:56 +08:00
InvalidArgumentValue ,
2009-05-06 21:38:46 +08:00
ValueMissingArgument ,
2009-05-07 21:27:48 +08:00
TooManyValuesForArgument ,
2009-07-13 09:42:13 +08:00
MutuallyExclusive }
2009-05-06 21:38:46 +08:00
2009-05-04 08:11:42 +08:00
/ * *
2009-05-06 21:38:46 +08:00
* Validates the list of command - line argument matches .
2009-05-04 08:11:42 +08:00
* /
2009-05-07 03:38:05 +08:00
public void validate ( ) {
validate ( EnumSet . noneOf ( ValidationType . class ) ) ;
2009-05-06 21:38:46 +08:00
}
/ * *
* Validates the list of command - line argument matches . On failure throws an exception with detailed info about the
* particular failures . Takes an EnumSet indicating which validation checks to skip .
* @param skipValidationOf List of validation checks to skip .
* /
2009-05-07 03:38:05 +08:00
public void validate ( EnumSet < ValidationType > skipValidationOf ) {
2009-05-06 06:08:00 +08:00
// Find missing required arguments.
2009-05-06 21:38:46 +08:00
if ( ! skipValidationOf . contains ( ValidationType . MissingRequiredArgument ) ) {
Collection < ArgumentDefinition > requiredArguments =
argumentDefinitions . findArgumentDefinitions ( true , ArgumentDefinitions . RequiredDefinitionMatcher ) ;
Collection < ArgumentDefinition > missingArguments = new ArrayList < ArgumentDefinition > ( ) ;
for ( ArgumentDefinition requiredArgument : requiredArguments ) {
if ( ! argumentMatches . hasMatch ( requiredArgument ) )
missingArguments . add ( requiredArgument ) ;
}
2009-05-06 06:08:00 +08:00
2009-05-06 21:38:46 +08:00
if ( missingArguments . size ( ) > 0 )
throw new MissingArgumentException ( missingArguments ) ;
}
2009-05-06 06:08:00 +08:00
// Find invalid arguments. Invalid arguments will have a null argument definition.
2009-05-06 21:38:46 +08:00
if ( ! skipValidationOf . contains ( ValidationType . InvalidArgument ) ) {
2009-08-23 08:56:02 +08:00
ArgumentMatches invalidArguments = argumentMatches . findUnmatched ( ) ;
2009-05-06 21:38:46 +08:00
if ( invalidArguments . size ( ) > 0 )
throw new InvalidArgumentException ( invalidArguments ) ;
}
2009-05-06 06:08:00 +08:00
2009-05-08 04:28:56 +08:00
// 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 ) {
2009-08-23 08:56:02 +08:00
ArgumentMatches verifiableMatches = argumentMatches . findMatches ( verifiableArgument ) ;
2009-05-08 04:28:56 +08:00
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 ) ;
}
2009-05-06 06:08:00 +08:00
// Find values without an associated mate.
2009-05-06 21:38:46 +08:00
if ( ! skipValidationOf . contains ( ValidationType . ValueMissingArgument ) ) {
if ( argumentMatches . MissingArgument . values ( ) . size ( ) > 0 )
2009-05-08 04:28:56 +08:00
throw new UnmatchedArgumentException ( argumentMatches . MissingArgument ) ;
2009-05-06 21:38:46 +08:00
}
2009-05-06 06:08:00 +08:00
// Find arguments with too many values.
2009-05-06 21:38:46 +08:00
if ( ! skipValidationOf . contains ( ValidationType . TooManyValuesForArgument ) ) {
Collection < ArgumentMatch > overvaluedArguments = new ArrayList < ArgumentMatch > ( ) ;
2009-05-07 21:27:48 +08:00
for ( ArgumentMatch argumentMatch : argumentMatches . findSuccessfulMatches ( ) ) {
2009-05-06 21:38:46 +08:00
// Warning: assumes that definition is not null (asserted by checks above).
2009-12-21 08:39:36 +08:00
if ( ! argumentMatch . definition . isMultiValued & & argumentMatch . values ( ) . size ( ) > 1 )
2009-05-06 21:38:46 +08:00
overvaluedArguments . add ( argumentMatch ) ;
}
2009-05-06 06:08:00 +08:00
2009-05-06 21:38:46 +08:00
if ( ! overvaluedArguments . isEmpty ( ) )
throw new TooManyValuesForArgumentException ( overvaluedArguments ) ;
}
2009-05-07 21:27:48 +08:00
// Find sets of options that are supposed to be mutually exclusive.
if ( ! skipValidationOf . contains ( ValidationType . MutuallyExclusive ) ) {
Collection < Pair < ArgumentMatch , ArgumentMatch > > invalidPairs = new ArrayList < Pair < ArgumentMatch , ArgumentMatch > > ( ) ;
for ( ArgumentMatch argumentMatch : argumentMatches . findSuccessfulMatches ( ) ) {
if ( argumentMatch . definition . exclusiveOf ! = null ) {
for ( ArgumentMatch conflictingMatch : argumentMatches . findSuccessfulMatches ( ) ) {
// Skip over the current element.
if ( argumentMatch = = conflictingMatch )
continue ;
if ( argumentMatch . definition . exclusiveOf . equals ( conflictingMatch . definition . fullName ) | |
argumentMatch . definition . exclusiveOf . equals ( conflictingMatch . definition . shortName ) )
invalidPairs . add ( new Pair < ArgumentMatch , ArgumentMatch > ( argumentMatch , conflictingMatch ) ) ;
}
}
}
if ( ! invalidPairs . isEmpty ( ) )
throw new ArgumentsAreMutuallyExclusiveException ( invalidPairs ) ;
}
2009-05-04 08:11:42 +08:00
}
/ * *
* Loads a set of matched command - line arguments into the given object .
* @param object Object into which to add arguments .
* /
2009-05-07 03:38:05 +08:00
public void loadArgumentsIntoObject ( Object object ) {
2009-09-30 06:23:19 +08:00
List < ArgumentSource > argumentSources = extractArgumentSources ( object . getClass ( ) ) ;
2009-07-30 00:11:45 +08:00
for ( ArgumentSource argumentSource : argumentSources )
2009-12-30 00:46:24 +08:00
loadValueIntoObject ( argumentSource , object , argumentMatches . findMatches ( argumentSource ) ) ;
2009-05-18 08:42:00 +08:00
}
/ * *
2009-09-30 06:23:19 +08:00
* Loads a single argument into the object and that objects children .
2009-07-13 09:42:13 +08:00
* @param argumentMatches Argument matches to load into the object .
2009-09-30 06:23:19 +08:00
* @param source Argument source to load into the object .
* @param instance Object into which to inject the value . The target might be in a container within the instance .
2009-05-18 08:42:00 +08:00
* /
2009-12-30 00:46:24 +08:00
private void loadValueIntoObject ( ArgumentSource source , Object instance , ArgumentMatches argumentMatches ) {
2009-07-30 00:11:45 +08:00
// Nothing to load
2009-12-30 00:46:24 +08:00
if ( argumentMatches . size ( ) = = 0 & & ! source . overridesDefault ( ) )
2009-05-18 08:42:00 +08:00
return ;
2009-09-30 06:23:19 +08:00
// Target instance into which to inject the value.
List < Object > targets = new ArrayList < Object > ( ) ;
// Check to see whether the instance itself can be the target.
if ( source . clazz . isAssignableFrom ( instance . getClass ( ) ) ) {
targets . add ( instance ) ;
}
// Check to see whether a contained class can be the target.
targets . addAll ( getContainersMatching ( instance , source . clazz ) ) ;
// Abort if no home is found for the object.
if ( targets . size ( ) = = 0 )
throw new StingException ( "Internal command-line parser error: unable to find a home for argument matches " + argumentMatches ) ;
for ( Object target : targets ) {
2009-12-30 00:46:24 +08:00
Object value = ( argumentMatches . size ( ) ! = 0 ) ? source . parse ( source , argumentMatches ) : source . getDefault ( ) ;
JVMUtils . setFieldValue ( source . field , target , value ) ;
2009-05-04 08:11:42 +08:00
}
}
2009-05-05 06:41:23 +08:00
2009-05-07 02:16:11 +08:00
/ * *
* Prints out the help associated with these command - line argument definitions .
2009-09-30 06:23:19 +08:00
* @param applicationDetails Details about the specific GATK - based application being run .
2009-05-07 02:16:11 +08:00
* /
2009-07-22 06:23:28 +08:00
public void printHelp ( ApplicationDetails applicationDetails ) {
new HelpFormatter ( ) . printHelp ( applicationDetails , argumentDefinitions ) ;
2009-05-07 02:16:11 +08:00
}
2009-05-06 06:08:00 +08:00
/ * *
2009-07-13 09:42:13 +08:00
* Extract all the argument sources from a given object .
* @param sourceClass class to act as sources for other arguments .
* @return A list of sources associated with this object and its aggregated objects .
2009-05-06 06:08:00 +08:00
* /
2009-12-11 02:57:54 +08:00
protected static List < ArgumentSource > extractArgumentSources ( Class sourceClass ) {
2009-07-13 09:42:13 +08:00
List < ArgumentSource > argumentSources = new ArrayList < ArgumentSource > ( ) ;
while ( sourceClass ! = null ) {
Field [ ] fields = sourceClass . getDeclaredFields ( ) ;
for ( Field field : fields ) {
2010-06-26 04:51:13 +08:00
if ( ArgumentTypeDescriptor . isArgumentDescriptionPresent ( field ) )
2009-07-13 09:42:13 +08:00
argumentSources . add ( new ArgumentSource ( sourceClass , field ) ) ;
2009-09-30 06:23:19 +08:00
if ( field . isAnnotationPresent ( ArgumentCollection . class ) )
argumentSources . addAll ( extractArgumentSources ( field . getType ( ) ) ) ;
2009-07-13 09:42:13 +08:00
}
sourceClass = sourceClass . getSuperclass ( ) ;
}
return argumentSources ;
}
2009-05-05 06:41:23 +08:00
/ * *
* Determines whether a token looks like the name of an argument .
* @param token Token to inspect . Can be surrounded by whitespace .
* @return True if token is of short name form .
* /
private boolean isArgumentForm ( String token ) {
for ( ParsingMethod parsingMethod : parsingMethods ) {
2009-05-08 00:21:17 +08:00
if ( parsingMethod . matches ( token ) )
2009-05-05 06:41:23 +08:00
return true ;
}
return false ;
}
/ * *
* Parse a short name into an ArgumentMatch .
* @param token The token to parse . The token should pass the isLongArgumentForm test .
2009-09-30 06:23:19 +08:00
* @param position The position of the token in question .
2009-05-05 06:41:23 +08:00
* @return ArgumentMatch associated with this token , or null if no match exists .
* /
private ArgumentMatch parseArgument ( String token , int position ) {
if ( ! isArgumentForm ( token ) )
throw new IllegalArgumentException ( "Token is not recognizable as an argument: " + token ) ;
for ( ParsingMethod parsingMethod : parsingMethods ) {
2009-05-08 00:21:17 +08:00
if ( parsingMethod . matches ( token ) )
2009-05-06 06:08:00 +08:00
return parsingMethod . match ( argumentDefinitions , token , position ) ;
2009-05-05 06:41:23 +08:00
}
// No parse results found.
return null ;
}
2009-09-30 06:23:19 +08:00
/ * *
* Gets a list of the container instances of the given type stored within the given target .
* @param target Class holding the container .
* @param type Container type .
* @return A list of containers matching the given type .
* /
private List < Object > getContainersMatching ( Object target , Class < ? > type ) {
List < Object > containers = new ArrayList < Object > ( ) ;
Field [ ] fields = target . getClass ( ) . getDeclaredFields ( ) ;
for ( Field field : fields ) {
if ( field . isAnnotationPresent ( ArgumentCollection . class ) & & type . isAssignableFrom ( field . getType ( ) ) )
containers . add ( JVMUtils . getFieldValue ( field , target ) ) ;
}
return containers ;
}
2009-05-04 08:11:42 +08:00
}
2009-05-06 06:08:00 +08:00
/ * *
* An exception indicating that some required arguments are missing .
* /
2009-05-20 07:26:17 +08:00
class MissingArgumentException extends ArgumentException {
2009-05-06 06:08:00 +08:00
public MissingArgumentException ( Collection < ArgumentDefinition > missingArguments ) {
super ( formatArguments ( missingArguments ) ) ;
}
private static String formatArguments ( Collection < ArgumentDefinition > missingArguments ) {
StringBuilder sb = new StringBuilder ( ) ;
2009-05-08 03:31:32 +08:00
for ( ArgumentDefinition missingArgument : missingArguments ) {
if ( missingArgument . shortName ! = null )
sb . append ( String . format ( "%nArgument with name '--%s' (-%s) is missing." , missingArgument . fullName , missingArgument . shortName ) ) ;
else
sb . append ( String . format ( "%nArgument with name '--%s' is missing." , missingArgument . fullName ) ) ;
}
2009-05-06 06:08:00 +08:00
return sb . toString ( ) ;
}
}
2009-08-23 08:56:02 +08:00
class MissingArgumentValueException extends ArgumentException {
public MissingArgumentValueException ( Collection < ArgumentDefinition > missingArguments ) {
super ( formatArguments ( missingArguments ) ) ;
}
private static String formatArguments ( Collection < ArgumentDefinition > missingArguments ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( ArgumentDefinition missingArgument : missingArguments ) {
if ( missingArgument . shortName ! = null )
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 ) ) ;
2010-01-21 05:36:46 +08:00
if ( missingArgument . validOptions ! = null )
sb . append ( String . format ( " Valid options are (%s)." , Utils . join ( "," , missingArgument . validOptions ) ) ) ;
2009-08-23 08:56:02 +08:00
}
return sb . toString ( ) ;
}
}
2009-05-06 06:08:00 +08:00
/ * *
* An exception for undefined arguments .
* /
2009-05-20 07:26:17 +08:00
class InvalidArgumentException extends ArgumentException {
2009-08-23 08:56:02 +08:00
public InvalidArgumentException ( ArgumentMatches invalidArguments ) {
2009-05-06 06:08:00 +08:00
super ( formatArguments ( invalidArguments ) ) ;
}
2009-08-23 08:56:02 +08:00
private static String formatArguments ( ArgumentMatches invalidArguments ) {
2009-05-06 06:08:00 +08:00
StringBuilder sb = new StringBuilder ( ) ;
for ( ArgumentMatch invalidArgument : invalidArguments )
2009-05-08 03:31:32 +08:00
sb . append ( String . format ( "%nArgument with name '%s' isn't defined." , invalidArgument . label ) ) ;
2009-05-06 06:08:00 +08:00
return sb . toString ( ) ;
}
}
/ * *
2009-05-08 04:28:56 +08:00
* An exception for values whose format is invalid .
2009-05-06 06:08:00 +08:00
* /
2009-05-20 07:26:17 +08:00
class InvalidArgumentValueException extends ArgumentException {
2009-05-08 04:28:56 +08:00
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 .
* /
2009-05-20 07:26:17 +08:00
class UnmatchedArgumentException extends ArgumentException {
2009-05-08 04:28:56 +08:00
public UnmatchedArgumentException ( ArgumentMatch invalidValues ) {
2009-05-06 06:08:00 +08:00
super ( formatArguments ( invalidValues ) ) ;
}
private static String formatArguments ( ArgumentMatch invalidValues ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( int index : invalidValues . indices . keySet ( ) )
for ( String value : invalidValues . indices . get ( index ) )
2009-05-08 03:31:32 +08:00
sb . append ( String . format ( "%nInvalid argument value '%s' at position %d." , value , index ) ) ;
2009-05-06 06:08:00 +08:00
return sb . toString ( ) ;
}
}
/ * *
* An exception indicating that too many values have been provided for the given argument .
* /
2009-05-20 07:26:17 +08:00
class TooManyValuesForArgumentException extends ArgumentException {
2009-05-06 06:08:00 +08:00
public TooManyValuesForArgumentException ( Collection < ArgumentMatch > arguments ) {
super ( formatArguments ( arguments ) ) ;
}
private static String formatArguments ( Collection < ArgumentMatch > arguments ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( ArgumentMatch argument : arguments )
2009-05-08 03:31:32 +08:00
sb . append ( String . format ( "%nArgument '%s' has to many values: %s." , argument . label , Arrays . deepToString ( argument . values ( ) . toArray ( ) ) ) ) ;
2009-05-06 06:08:00 +08:00
return sb . toString ( ) ;
}
2009-05-07 21:27:48 +08:00
}
/ * *
* An exception indicating that mutually exclusive options have been passed in the same command line .
* /
2009-05-20 07:26:17 +08:00
class ArgumentsAreMutuallyExclusiveException extends ArgumentException {
2009-05-07 21:27:48 +08:00
public ArgumentsAreMutuallyExclusiveException ( Collection < Pair < ArgumentMatch , ArgumentMatch > > arguments ) {
super ( formatArguments ( arguments ) ) ;
}
private static String formatArguments ( Collection < Pair < ArgumentMatch , ArgumentMatch > > arguments ) {
StringBuilder sb = new StringBuilder ( ) ;
for ( Pair < ArgumentMatch , ArgumentMatch > argument : arguments )
2009-05-08 03:31:32 +08:00
sb . append ( String . format ( "%nArguments '%s' and '%s' are mutually exclusive." , argument . first . definition . fullName , argument . second . definition . fullName ) ) ;
2009-05-07 21:27:48 +08:00
return sb . toString ( ) ;
}
2009-10-10 02:11:32 +08:00
}
/ * *
* An exception for when an argument doesn ' t match an of the enumerated options for that var type
* /
class UnknownEnumeratedValueException extends ArgumentException {
2010-01-21 05:36:46 +08:00
public UnknownEnumeratedValueException ( ArgumentDefinition definition , String argumentPassed ) {
super ( formatArguments ( definition , argumentPassed ) ) ;
2009-10-10 02:11:32 +08:00
}
2010-01-21 05:36:46 +08:00
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 ) ) ;
2009-10-10 02:11:32 +08:00
}
2009-05-06 06:08:00 +08:00
}