Interface skeleton for a new command line argument parser. Nowhere near the point of being a drop-in replacement for apache cli yet.

git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@588 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
hanna 2009-05-04 00:11:42 +00:00
parent 6e38966349
commit 4f2ccda56a
5 changed files with 311 additions and 1 deletions

View File

@ -0,0 +1,81 @@
package org.broadinstitute.sting.utils.cmdLine;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
* User: mhanna
* Date: May 3, 2009
* Time: 6:02:04 PM
* <p/>
* The Broad Institute
* SOFTWARE COPYRIGHT NOTICE AGREEMENT
* This software and its documentation are copyright 2009 by the
* Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
* <p/>
* This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/
/**
* A collection of argument definitions.
*/
class ArgumentDefinitions {
/**
* Backing data set of argument stored by short name.
*/
private Map<String,ArgumentDefinition> argumentsByShortName = new HashMap<String,ArgumentDefinition>();
/**
* Does this set of argument definitions specify an argument with the given short name?
* @param shortName The short name.
* @return True if it contains the definition. False otherwise.
*/
public boolean hasArgumentWithShortName( String shortName ) {
return argumentsByShortName.containsKey( shortName );
}
/**
* Returns the argument with the given short name.
* @param shortName Argument short name.
* @return The argument definition, or null if nothing matches.
*/
public ArgumentDefinition getArgumentWithShortName( String shortName ) {
return argumentsByShortName.get( shortName );
}
/**
* Adds an argument to the this argument definition list.
* @param argument The argument to add.
* @param sourceClass Class where the argument was defined.
* @param sourceField Field in which the argument was defined.
*/
public void add( Argument argument, Class sourceClass, Field sourceField ) {
argumentsByShortName.put( argument.shortName(),
new ArgumentDefinition( argument, sourceClass, sourceField ) );
}
}
/**
* A specific argument definition. Maps one-to-one with a field in some class.
*/
class ArgumentDefinition {
public final Argument argument;
public final Class sourceClass;
public final Field sourceField;
/**
* Creates a new argument definition.
* @param argument Attributes of the argument, read from the source field.
* @param sourceClass Source class for the argument, provided to the ParsingEngine.
* @param sourceField Source field for the argument, extracted from the sourceClass.
*/
public ArgumentDefinition( Argument argument, Class sourceClass, Field sourceField ) {
this.argument = argument;
this.sourceClass = sourceClass;
this.sourceField = sourceField;
}
}

View File

@ -0,0 +1,55 @@
package org.broadinstitute.sting.utils.cmdLine;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator; /**
* Created by IntelliJ IDEA.
* User: mhanna
* Date: May 3, 2009
* Time: 6:36:43 PM
* <p/>
* The Broad Institute
* SOFTWARE COPYRIGHT NOTICE AGREEMENT
* This software and its documentation are copyright 2009 by the
* Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
* <p/>
* This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/
/**
* Represents a list of potential matches between the arguments defined
* by the argument sources and the arguments passed in via the command line.
*/
public class ArgumentMatches implements Iterable<ArgumentMatch> {
/**
* Collection matches from argument definition to argument value.
* Package protected access is deliberate.
*/
Set<ArgumentMatch> argumentMatches = new HashSet<ArgumentMatch>();
void add( ArgumentDefinition definition, String value ) {
argumentMatches.add( new ArgumentMatch( definition, value ) );
}
/**
* Get an iterator cycling through command-line argument <-> definition matches.
* @return Iterator over all argument matches.
*/
public Iterator<ArgumentMatch> iterator() {
return argumentMatches.iterator();
}
}
/**
* An individual match from argument definition to argument value.
*/
class ArgumentMatch {
public final ArgumentDefinition definition;
public final String value;
public ArgumentMatch( ArgumentDefinition definition, String value ) {
this.definition = definition;
this.value = value;
}
}

View File

@ -283,7 +283,7 @@ public class ArgumentParser {
parser.parse(m_options, args, false);
}
catch( ParseException e ) {
boolean isIncomplete = e instanceof MissingArgumentException ||
boolean isIncomplete = e instanceof org.apache.commons.cli.MissingArgumentException ||
e instanceof MissingOptionException ||
e instanceof UnrecognizedOptionException;

View File

@ -0,0 +1,100 @@
package org.broadinstitute.sting.utils.cmdLine;
import org.broadinstitute.sting.utils.StingException;
import java.lang.reflect.Field;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: mhanna
* Date: May 3, 2009
* Time: 4:35:25 PM
* BROAD INSTITUTE SOFTWARE COPYRIGHT NOTICE AND AGREEMENT
* Software and documentation are copyright 2005 by the Broad Institute.
* All rights are reserved.
*
* Users acknowledge that this software is supplied without any warranty or support.
* The Broad Institute is not responsible for its use, misuse, or
* functionality.
*/
/**
* A parser for Sting command-line arguments.
*/
public class ParsingEngine {
/**
* A list of defined arguments against which command lines are matched.
*/
private ArgumentDefinitions argumentDefinitions = new ArgumentDefinitions();
/**
* Add an argument source. Argument sources are expected to have
* any number of fields with an @Argument annotation attached.
* @param sources A list of argument sources from which to extract
* command-line arguments.
*/
public void addArgumentSources( Class... sources ) {
for( Class source: sources ) {
Field[] fields = source.getFields();
for( Field field: fields ) {
Argument argument = field.getAnnotation(Argument.class);
if(argument != null)
argumentDefinitions.add( argument, source, field );
}
}
}
/**
* 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.
* @param arguments Command-line arguments.
* @return A object indicating which matches are best. Might return
* an empty object, but will never return null.
*/
public ArgumentMatches parse( String[] arguments ) {
ArgumentMatches argumentMatches = new ArgumentMatches();
for( int i = 0; i < arguments.length; i++ ) {
String argument = arguments[i].trim();
if( argument.startsWith("-") ) {
String shortName = argument.substring(1);
if( argumentDefinitions.hasArgumentWithShortName(shortName) ) {
ArgumentDefinition definition = argumentDefinitions.getArgumentWithShortName(shortName);
argumentMatches.add( definition, arguments[i+1].trim() );
}
}
}
return argumentMatches;
}
/**
* Validates the list of command-line argument matches. On
* failure ...TBD...
*/
public void validate( ArgumentMatches argumentMatches ) {
}
/**
* Loads a set of matched command-line arguments into the given object.
* @param object Object into which to add arguments.
* @param argumentMatches List of matches.
*/
public void loadArgumentsIntoObject( Object object, ArgumentMatches matches ) {
for( ArgumentMatch match: matches ) {
if( object.getClass().equals(match.definition.sourceClass) ) {
try {
match.definition.sourceField.set( object, match.value );
}
catch( IllegalAccessException ex ) {
//logger.fatal("processArgs: cannot convert field " + field.toString());
throw new StingException("processArgs: Failed conversion " + ex.getMessage(), ex);
}
}
}
}
}

View File

@ -0,0 +1,74 @@
package org.broadinstitute.sting.utils.cmdLine;
import org.broadinstitute.sting.BaseTest;
import org.junit.Test;
import org.junit.Before;
import org.junit.Assert;
/**
* Created by IntelliJ IDEA.
* User: mhanna
* Date: May 3, 2009
* Time: 6:05:33 PM
* <p/>
* The Broad Institute
* SOFTWARE COPYRIGHT NOTICE AGREEMENT
* This software and its documentation are copyright 2009 by the
* Broad Institute/Massachusetts Institute of Technology. All rights are reserved.
* <p/>
* This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/
/**
* Test suite for the parsing engine.
*/
public class ParsingEngineTest extends BaseTest {
private ParsingEngine parsingEngine;
@Before
public void setUp() {
parsingEngine = new ParsingEngine();
}
private class InputFileArgProvider {
@Argument(fullName="input_file",shortName="I")
public String inputFile;
}
@Test
public void shortNameArgumentTest() {
final String[] commandLine = new String[] {"-I","na12878.bam"};
parsingEngine.addArgumentSources( InputFileArgProvider.class );
ArgumentMatches argumentMatches = parsingEngine.parse( commandLine );
parsingEngine.validate(argumentMatches);
InputFileArgProvider argProvider = new InputFileArgProvider();
parsingEngine.loadArgumentsIntoObject( argProvider, argumentMatches);
Assert.assertEquals("Argument is not correctly initialized", "na12878.bam", argProvider.inputFile );
}
// To test
// 'Composite' short names
// long names
// flags
// flags with arguments at every point on the line
// flags with arguments at the end of the line
/*
@Test
public void shortNameCompositeArgumentTest() {
final String[] commandLine = new String[] {"-I na12878.bam"};
parsingEngine.addArgumentSources( InputFileArgProvider.class );
ArgumentMatches argumentMatches = parsingEngine.parse( commandLine );
parsingEngine.validate(argumentMatches);
InputFileArgProvider argProvider = new InputFileArgProvider();
parsingEngine.loadArgumentsIntoObject( argProvider, argumentMatches);
Assert.assertEquals("Argument is not correctly initialized", "na12878.bam" );
}
*/
}