Better division of responsibilities between sources and type descriptors.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@1314 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
64221907a2
commit
2024fb3e32
|
|
@ -153,9 +153,9 @@ public abstract class CommandLineExecutable extends CommandLineProgram {
|
|||
@Override
|
||||
protected ArgumentFactory getCustomArgumentFactory() {
|
||||
return new ArgumentFactory() {
|
||||
public Object createArgument( Class type, List<String> repr ) {
|
||||
if (type == SAMFileReader.class && repr.size() == 1) {
|
||||
SAMFileReader samFileReader = new SAMFileReader(new File(repr.get(0)),true);
|
||||
public Object createArgument( Class type, String... repr ) {
|
||||
if (type == SAMFileReader.class && repr.length == 1) {
|
||||
SAMFileReader samFileReader = new SAMFileReader(new File(repr[0]),true);
|
||||
samFileReader.setValidationStringency(getArgumentCollection().strictnessLevel);
|
||||
return samFileReader;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,5 +38,5 @@ public abstract class ArgumentFactory {
|
|||
* @param repr A String representation of the argument.
|
||||
* @return
|
||||
*/
|
||||
public abstract Object createArgument(Class type, List<String> repr);
|
||||
public abstract Object createArgument(Class type, String... repr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,11 +119,26 @@ public class ArgumentSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the value of the field in the passed object to <code>value</code>
|
||||
* @param targetInstance Instance in which to find the field.
|
||||
* @param value Value to which to set the field.
|
||||
* Injects the specified value into the selected field of the instance.
|
||||
* @param targetInstance Instance into which to inject the parsed value.
|
||||
* @param values String representation of all values passed.
|
||||
*/
|
||||
public void setValue( Object targetInstance, Object value ) {
|
||||
public void inject( ArgumentFactory customArgumentFactory, Object targetInstance, String... values ) {
|
||||
Object value = null;
|
||||
|
||||
if( customArgumentFactory != null ) {
|
||||
value = customArgumentFactory.createArgument(field.getType(), values);
|
||||
}
|
||||
|
||||
if( value == null ) {
|
||||
if( !isFlag() ) {
|
||||
ArgumentTypeDescriptor typeDescriptor = ArgumentTypeDescriptor.create( field.getType() );
|
||||
value = typeDescriptor.parse( field, field.getType(), values );
|
||||
}
|
||||
else
|
||||
value = true;
|
||||
}
|
||||
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
field.set(targetInstance, value);
|
||||
|
|
@ -132,7 +147,6 @@ public class ArgumentSource {
|
|||
//logger.fatal("processArgs: cannot convert field " + field.toString());
|
||||
throw new StingException("processArgs: Failed conversion " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -151,6 +165,4 @@ public class ArgumentSource {
|
|||
Class argumentType = field.getType();
|
||||
return Collection.class.isAssignableFrom(argumentType) || field.getType().isArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,53 +44,46 @@ public abstract class ArgumentTypeDescriptor {
|
|||
* our log, which we want to capture anything from org.broadinstitute.sting
|
||||
*/
|
||||
protected static Logger logger = Logger.getLogger(ArgumentTypeDescriptor.class);
|
||||
|
||||
/**
|
||||
* Name of the field which should be parsed by this argument.
|
||||
*/
|
||||
protected final String fieldName;
|
||||
|
||||
public static ArgumentTypeDescriptor create( Field field ) {
|
||||
Class type = field.getType();
|
||||
|
||||
if( Collection.class.isAssignableFrom(type) || type.isArray() )
|
||||
return new CompoundArgumentTypeDescriptor( field );
|
||||
else
|
||||
return new SimpleArgumentTypeDescriptor( field );
|
||||
}
|
||||
|
||||
static ArgumentTypeDescriptor create( String fieldName, Class type ) {
|
||||
if( Collection.class.isAssignableFrom(type) || type.isArray() )
|
||||
return new CompoundArgumentTypeDescriptor( fieldName, type );
|
||||
else
|
||||
return new SimpleArgumentTypeDescriptor( fieldName, type );
|
||||
}
|
||||
|
||||
protected ArgumentTypeDescriptor( Field field ) {
|
||||
fieldName = field.toString();
|
||||
}
|
||||
|
||||
protected ArgumentTypeDescriptor( String fieldName ) {
|
||||
this.fieldName = fieldName;
|
||||
}
|
||||
|
||||
public abstract Object parse( String... values );
|
||||
/**
|
||||
* Class reference to the different types of descriptors that the create method can create.
|
||||
*/
|
||||
private static List<ArgumentTypeDescriptor> descriptors = Arrays.asList( new SimpleArgumentTypeDescriptor(),
|
||||
new CompoundArgumentTypeDescriptor() );
|
||||
|
||||
public static ArgumentTypeDescriptor create( Class type ) {
|
||||
for( ArgumentTypeDescriptor descriptor: descriptors ) {
|
||||
if( descriptor.supports(type) )
|
||||
return descriptor;
|
||||
}
|
||||
throw new StingException("Can't process command-line arguments of type: " + type.getName());
|
||||
}
|
||||
|
||||
public abstract boolean supports( Class type );
|
||||
|
||||
public abstract Object parse( Field field, Class type, String... values );
|
||||
}
|
||||
|
||||
class SimpleArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
||||
private final Class type;
|
||||
@Override
|
||||
public boolean supports( Class type ) {
|
||||
if( type.isPrimitive() ) return true;
|
||||
if( type.isEnum() ) return true;
|
||||
if( primitiveToWrapperMap.containsValue(type) ) return true;
|
||||
|
||||
public SimpleArgumentTypeDescriptor( Field field ) {
|
||||
super( field );
|
||||
this.type = field.getType();
|
||||
try {
|
||||
type.getConstructor(String.class);
|
||||
return true;
|
||||
}
|
||||
catch( Exception ex ) {
|
||||
// An exception thrown above means that the String constructor either doesn't
|
||||
// exist or can't be accessed. In either case, this descriptor doesn't support this type.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SimpleArgumentTypeDescriptor( String fieldName, Class type ) {
|
||||
super( fieldName );
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Object parse( String... values ) {
|
||||
@Override
|
||||
public Object parse( Field field, Class type, String... values ) {
|
||||
if( values.length > 1 )
|
||||
throw new StingException("Simple argument parser is unable to parse multiple arguments.");
|
||||
|
||||
|
|
@ -109,16 +102,12 @@ class SimpleArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
|||
}
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
logger.fatal("ArgumentParser: NoSuchMethodException: cannot convert field " + fieldName);
|
||||
throw new StingException("constructFromString:NoSuchMethodException: Failed conversion " + e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
logger.fatal("ArgumentParser: IllegalAccessException: cannot convert field " + fieldName);
|
||||
throw new StingException("constructFromString:IllegalAccessException: Failed conversion " + e.getMessage());
|
||||
} catch (InvocationTargetException e) {
|
||||
logger.fatal("ArgumentParser: InvocationTargetException: cannot convert field " + fieldName);
|
||||
throw new StingException("constructFromString:InvocationTargetException: Failed conversion " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
logger.fatal("ArgumentParser: InstantiationException: cannot convert field " + fieldName);
|
||||
throw new StingException("constructFromString:InstantiationException: Failed conversion " + e.getMessage());
|
||||
}
|
||||
|
||||
|
|
@ -143,27 +132,28 @@ class SimpleArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
|||
}
|
||||
|
||||
class CompoundArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
||||
private final Class type;
|
||||
private final Class componentType;
|
||||
private final ArgumentTypeDescriptor componentArgumentParser;
|
||||
@Override
|
||||
public boolean supports( Class type ) {
|
||||
return ( Collection.class.isAssignableFrom(type) || type.isArray() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parse( Field field, Class type, String... values )
|
||||
{
|
||||
Class componentType = null;
|
||||
ArgumentTypeDescriptor componentArgumentParser;
|
||||
|
||||
public CompoundArgumentTypeDescriptor( Field field ) {
|
||||
super( field );
|
||||
Class candidateType = field.getType();
|
||||
|
||||
if( Collection.class.isAssignableFrom(candidateType) ) {
|
||||
if( Collection.class.isAssignableFrom(type) ) {
|
||||
|
||||
// If this is a generic interface, pick a concrete implementation to create and pass back.
|
||||
// Because of type erasure, don't worry about creating one of exactly the correct type.
|
||||
if( Modifier.isInterface(candidateType.getModifiers()) || Modifier.isAbstract(candidateType.getModifiers()) )
|
||||
if( Modifier.isInterface(type.getModifiers()) || Modifier.isAbstract(type.getModifiers()) )
|
||||
{
|
||||
if( java.util.List.class.isAssignableFrom(candidateType) ) candidateType = ArrayList.class;
|
||||
else if( java.util.Queue.class.isAssignableFrom(candidateType) ) candidateType = java.util.ArrayDeque.class;
|
||||
else if( java.util.Set.class.isAssignableFrom(candidateType) ) candidateType = java.util.TreeSet.class;
|
||||
if( java.util.List.class.isAssignableFrom(type) ) type = ArrayList.class;
|
||||
else if( java.util.Queue.class.isAssignableFrom(type) ) type = java.util.ArrayDeque.class;
|
||||
else if( java.util.Set.class.isAssignableFrom(type) ) type = java.util.TreeSet.class;
|
||||
}
|
||||
|
||||
this.type = candidateType;
|
||||
|
||||
// If this is a parameterized collection, find the contained type. If blow up if only one type exists.
|
||||
if( field.getGenericType() instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType)field.getGenericType();
|
||||
|
|
@ -174,52 +164,30 @@ class CompoundArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
|||
else
|
||||
componentType = String.class;
|
||||
}
|
||||
else if( candidateType.isArray() ) {
|
||||
this.type = candidateType;
|
||||
this.componentType = candidateType.getComponentType();
|
||||
}
|
||||
else
|
||||
throw new StingException("Unsupported compound argument type: " + candidateType);
|
||||
|
||||
componentArgumentParser = ArgumentTypeDescriptor.create( fieldName, componentType );
|
||||
}
|
||||
|
||||
public CompoundArgumentTypeDescriptor( String fieldName, Class type ) {
|
||||
super(fieldName);
|
||||
|
||||
this.type = type;
|
||||
|
||||
if( Collection.class.isAssignableFrom(type) ) {
|
||||
this.componentType = String.class;
|
||||
}
|
||||
else if( type.isArray() ) {
|
||||
this.componentType = type.getComponentType();
|
||||
componentType = type.getComponentType();
|
||||
}
|
||||
else
|
||||
throw new StingException("Unsupported compound argument type: " + type);
|
||||
|
||||
componentArgumentParser = ArgumentTypeDescriptor.create( fieldName, componentType );
|
||||
}
|
||||
componentArgumentParser = ArgumentTypeDescriptor.create( componentType );
|
||||
|
||||
@Override
|
||||
public Object parse( String... values )
|
||||
{
|
||||
if( Collection.class.isAssignableFrom(type) ) {
|
||||
Collection collection = null;
|
||||
try {
|
||||
collection = (Collection)type.newInstance();
|
||||
}
|
||||
catch (InstantiationException e) {
|
||||
logger.fatal("ArgumentParser: InstantiationException: cannot convert field " + fieldName);
|
||||
logger.fatal("ArgumentParser: InstantiationException: cannot convert field " + field.getName());
|
||||
throw new StingException("constructFromString:InstantiationException: Failed conversion " + e.getMessage());
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
logger.fatal("ArgumentParser: IllegalAccessException: cannot convert field " + fieldName);
|
||||
logger.fatal("ArgumentParser: IllegalAccessException: cannot convert field " + field.getName());
|
||||
throw new StingException("constructFromString:IllegalAccessException: Failed conversion " + e.getMessage());
|
||||
}
|
||||
|
||||
for( String value: values )
|
||||
collection.add( componentArgumentParser.parse(value) );
|
||||
collection.add( componentArgumentParser.parse(field,componentType,value) );
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
|
@ -227,7 +195,7 @@ class CompoundArgumentTypeDescriptor extends ArgumentTypeDescriptor {
|
|||
Object arr = Array.newInstance(componentType,values.length);
|
||||
|
||||
for( int i = 0; i < values.length; i++ )
|
||||
Array.set( arr,i,componentArgumentParser.parse(values[i]));
|
||||
Array.set( arr,i,componentArgumentParser.parse(field,componentType,values[i]));
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,21 +270,8 @@ public class ParsingEngine {
|
|||
return;
|
||||
|
||||
if( definition.source.clazz.isAssignableFrom(object.getClass()) ) {
|
||||
if( customArgumentFactory != null ) {
|
||||
Object instance = customArgumentFactory.createArgument(definition.source.field.getType(), match.values());
|
||||
if( instance != null ) {
|
||||
definition.source.setValue( object, instance );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( !definition.source.isFlag() ) {
|
||||
String[] tokens = match.values().toArray(new String[0]);
|
||||
ArgumentTypeDescriptor fieldParser = ArgumentTypeDescriptor.create(definition.source.field);
|
||||
definition.source.setValue( object, fieldParser.parse(tokens) );
|
||||
}
|
||||
else
|
||||
definition.source.setValue( object, true );
|
||||
String[] tokens = match.values().toArray(new String[0]);
|
||||
definition.source.inject( customArgumentFactory, object, tokens );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,17 +334,6 @@ public class ParsingEngine {
|
|||
// No parse results found.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a command-line argument given a string and field.
|
||||
* @param f Field type from which to infer the type.
|
||||
* @param strs Collection of parameter strings to parse.
|
||||
* @return Parsed object of the inferred type.
|
||||
*/
|
||||
private Object constructFromString(Field f, List<String> strs) {
|
||||
ArgumentTypeDescriptor fieldParser = ArgumentTypeDescriptor.create(f);
|
||||
return fieldParser.parse( strs.toArray(new String[0]) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue