Refactored ArgumentDefinition to absorb functionality from ArgumentDefinition and ArgumentTypeDescriptor.

git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3688 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
kshakir 2010-06-30 18:37:58 +00:00
parent 569456850d
commit 178cf64a0c
7 changed files with 181 additions and 239 deletions

View File

@ -25,8 +25,10 @@
package org.broadinstitute.sting.commandline;
import org.broadinstitute.sting.utils.StingException;
import org.broadinstitute.sting.utils.Utils;
import java.lang.annotation.Annotation;
import java.util.List;
/**
@ -118,6 +120,75 @@ public class ArgumentDefinition {
this.validOptions = validOptions;
}
/**
* Creates a new argument definition.
* @param annotation The annotation on the field.
* @param defaultFullName Default full name for this argument definition.
* @param defaultShortName Default short name for this argument definition.
* @param isFlag Whether or not this argument should be treated as a flag.
* @param isMultiValued Whether or not this argument supports multiple values.
* @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( Annotation annotation,
String defaultFullName,
String defaultShortName,
boolean isFlag,
boolean isMultiValued,
List<String> validOptions) {
String fullName = (String)getValue(annotation, "fullName");
String shortName = (String)getValue(annotation, "shortName");
boolean isFullNameProvided = fullName.trim().length() > 0;
boolean isShortNameProvided = shortName.trim().length() > 0;
fullName = isFullNameProvided ? fullName.trim() : defaultFullName;
// If the short name is provided, use that. If the user hasn't provided any names at all, use
// the default. If somewhere in the middle, leave the short name blank.
if( isShortNameProvided )
shortName = shortName.trim();
else if( !isFullNameProvided )
shortName = defaultShortName;
else
shortName = null;
this.ioType = getIOType(annotation);
this.fullName = fullName;
this.shortName = shortName;
this.doc = getDoc(annotation);
this.required = isRequired(annotation, isFlag);
this.isFlag = isFlag;
this.isMultiValued = isMultiValued;
this.exclusiveOf = getExclusiveOf(annotation);
this.validation = getValidationRegex(annotation);
this.validOptions = validOptions;
}
/**
* Creates a new argument definition.
* @param annotation The annotation on the field.
* @param fieldName Default full name for this argument definition.
* @param isFlag Whether or not this argument should be treated as a flag.
* @param isMultiValued Whether or not this argument supports multiple values.
* @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( Annotation annotation,
String fieldName,
boolean isFlag,
boolean isMultiValued,
List<String> validOptions) {
this.ioType = getIOType(annotation);
this.fullName = getFullName(annotation, fieldName);
this.shortName = getShortName(annotation);
this.doc = getDoc(annotation);
this.required = isRequired(annotation, isFlag);
this.isFlag = isFlag;
this.isMultiValued = isMultiValued;
this.exclusiveOf = getExclusiveOf(annotation);
this.validation = getValidationRegex(annotation);
this.validOptions = validOptions;
}
@Override
public int hashCode() {
int hashCode = fullName.hashCode();
@ -136,4 +207,92 @@ public class ArgumentDefinition {
return Utils.equals(fullName,other.fullName) &&
Utils.equals(shortName,other.shortName);
}
/**
* Returns the ArgumentIOType for the annotation.
* @param annotation @Input or @Output
* @return ArgumentIOType.Input, Output, or Unknown
*/
public static ArgumentIOType getIOType(Annotation annotation) {
if (annotation instanceof Input) return ArgumentIOType.INPUT;
if (annotation instanceof Output) return ArgumentIOType.OUTPUT;
return ArgumentIOType.UNKNOWN;
}
/**
* A hack to get around the fact that Java doesn't like inheritance in Annotations.
* @param annotation to run the method on
* @param method the method to invoke
* @return the return value of the method
*/
private static Object getValue(Annotation annotation, String method) {
try {
return annotation.getClass().getMethod(method).invoke(annotation);
} catch (Exception e) {
throw new StingException("Unable to access method " + method + " on annotation " + annotation.getClass(), e);
}
}
/**
* Retrieves the full name of the argument, specifiable with the '--' prefix. The full name can be
* either specified explicitly with the fullName annotation parameter or implied by the field name.
* @param annotation Original field annotation.
* @param fieldName Original field name.
* @return full name of the argument. Never null.
*/
private static String getFullName( Annotation annotation, String fieldName ) {
String fullName = (String)getValue(annotation, "fullName");
return fullName.trim().length() > 0 ? fullName.trim() : fieldName.toLowerCase();
}
/**
* Retrieves the short name of the argument, specifiable with the '-' prefix. The short name can
* be specified or not; if left unspecified, no short name will be present.
* @param annotation Original field annotation.
* @return short name of the argument. Null if no short name exists.
*/
private static String getShortName( Annotation annotation ) {
String shortName = (String)getValue(annotation, "shortName");
return shortName.trim().length() > 0 ? shortName.trim() : null;
}
/**
* Documentation for this argument. Mandatory field.
* @param annotation Original field annotation.
* @return Documentation for this argument.
*/
private static String getDoc( Annotation annotation ) {
return (String)getValue(annotation, "doc");
}
/**
* Returns whether this field is required. Note that flag fields are always forced to 'not required'.
* @param annotation Original field annotation.
* @param isFlag True if the field is a flag.
* @return True if the field is mandatory and not a boolean flag. False otherwise.
*/
private static boolean isRequired( Annotation annotation, boolean isFlag ) {
boolean required = (Boolean)getValue(annotation, "required");
return required && !isFlag;
}
/**
* Specifies other arguments which cannot be used in conjunction with this argument. Comma-separated list.
* @param annotation Original field annotation.
* @return A comma-separated list of exclusive arguments, or null if none are present.
*/
private static String getExclusiveOf( Annotation annotation ) {
String exclusiveOf = (String)getValue(annotation, "exclusiveOf");
return exclusiveOf.trim().length() > 0 ? exclusiveOf.trim() : null;
}
/**
* A regular expression which can be used for validation.
* @param annotation Original field annotation.
* @return a JVM regex-compatible regular expression, or null to permit any possible value.
*/
private static String getValidationRegex( Annotation annotation ) {
String validation = (String)getValue(annotation, "validation");
return validation.trim().length() > 0 ? validation.trim() : null;
}
}

View File

@ -1,107 +0,0 @@
/*
* Copyright (c) 2010, The Broad Institute
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* 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:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* 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;
import org.broadinstitute.sting.utils.StingException;
import java.lang.annotation.Annotation;
/**
* Should be an interface, but java doesn't like inheritance in Annotations.
*/
public class ArgumentDescription {
private Annotation annotation;
public ArgumentDescription(Annotation annotation) {
this.annotation = annotation;
}
/**
* A hack to get around the fact that Java doesn't like inheritance in Annotations.
* @param method the method to invoke
* @return the return value of the method
*/
private Object invoke(String method) {
try {
return this.annotation.getClass().getMethod(method).invoke(this.annotation);
} catch (Exception e) {
throw new StingException("Unable to access method " + method + " on annotation " + annotation.getClass(), e);
}
}
/**
* The directionality of the command-line argument.
* @return INPUT, OUTPUT, or UNKNOWN
*/
public ArgumentIOType getIOType() {
if (annotation instanceof Input) return ArgumentIOType.INPUT;
if (annotation instanceof Output) return ArgumentIOType.OUTPUT;
return ArgumentIOType.UNKNOWN;
}
/**
* The full name of the command-line argument. Full names should be
* prefixed on the command-line with a double dash (--).
* @return Selected full name, or "" to use the default.
*/
public String fullName() { return (String)invoke("fullName"); }
/**
* Specified short name of the command. Short names should be prefixed
* with a single dash. Argument values can directly abut single-char
* short names or be separated from them by a space.
* @return Selected short name, or "" for none.
*/
public String shortName() { return (String)invoke("shortName"); }
/**
* Documentation for the command-line argument. Should appear when the
* --help argument is specified.
* @return Doc string associated with this command-line argument.
*/
public String doc() { return (String)invoke("doc"); }
/**
* Is this command-line argument required. The application should exit
* printing help if this command-line argument is not specified.
* @return True if the argument is required. False otherwise.
*/
public boolean required() { return (Boolean)invoke("required"); }
/**
* Should this command-line argument be exclusive of others. Should be
* a comma-separated list of names of arguments of which this should be
* independent.
* @return A comma-separated string listing other arguments of which this
* argument should be independent.
*/
public String exclusiveOf() { return (String)invoke("exclusiveOf"); }
/**
* Provide a regexp-based validation string.
* @return Non-empty regexp for validation, blank otherwise.
*/
public String validation() { return (String)invoke("validation"); }
}

View File

@ -28,6 +28,7 @@ package org.broadinstitute.sting.commandline;
import org.broadinstitute.sting.utils.StingException;
import org.apache.log4j.Logger;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
@ -122,91 +123,15 @@ public abstract class ArgumentTypeDescriptor {
* @return The default definition for this argument source.
*/
protected ArgumentDefinition createDefaultArgumentDefinition( ArgumentSource source ) {
return new ArgumentDefinition( getIOType(source),
getFullName(source),
getShortName(source),
getDoc(source),
isRequired(source),
return new ArgumentDefinition( getArgumentAnnotation(source),
source.field.getName(),
source.isFlag(),
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source),
getValidOptions(source) );
}
public abstract Object parse( ArgumentSource source, Class type, ArgumentMatches matches );
/**
* Specifies other arguments which cannot be used in conjunction with tihs argument. Comma-separated list.
* @param source Original field specifying command-line arguments.
* @return A comma-separated list of exclusive arguments, or null if none are present.
*/
protected ArgumentIOType getIOType( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.getIOType();
}
/**
* Retrieves the full name of the argument, specifiable with the '--' prefix. The full name can be
* either specified explicitly with the fullName annotation parameter or implied by the field name.
* @param source Original field specifying command-line arguments.
* @return full name of the argument. Never null.
*/
protected String getFullName( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.fullName().trim().length() > 0 ? description.fullName().trim() : source.field.getName().toLowerCase();
}
/**
* Retrieves the short name of the argument, specifiable with the '-' prefix. The short name can
* be specified or not; if left unspecified, no short name will be present.
* @param source Original field specifying command-line arguments.
* @return short name of the argument. Null if no short name exists.
*/
protected String getShortName( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.shortName().trim().length() > 0 ? description.shortName().trim() : null;
}
/**
* Documentation for this argument. Mandatory field.
* @param source Original field specifying command-line arguments.
* @return Documentation for this argument.
*/
protected String getDoc( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.doc();
}
/**
* Returns whether this field is required. Note that flag fields are always forced to 'not required'.
* @param source Original field specifying command-line arguments.
* @return True if the field is mandatory and not a boolean flag. False otherwise.
*/
protected boolean isRequired( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.required() && !source.isFlag();
}
/**
* Specifies other arguments which cannot be used in conjunction with tihs argument. Comma-separated list.
* @param source Original field specifying command-line arguments.
* @return A comma-separated list of exclusive arguments, or null if none are present.
*/
protected String getExclusiveOf( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
return description.exclusiveOf().trim().length() > 0 ? description.exclusiveOf().trim() : null;
}
/**
* A regular expression which can be used for validation.
* @param source Original field specifying command-line arguments.
* @return a JVM regex-compatible regular expression, or null to permit any possible value.
*/
protected String getValidationRegex( ArgumentSource source ) {
ArgumentDescription description = getArgumentDescription(source);
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
@ -259,15 +184,15 @@ public abstract class ArgumentTypeDescriptor {
* @return Argument description annotation associated with the given field.
*/
@SuppressWarnings("unchecked")
protected ArgumentDescription getArgumentDescription( ArgumentSource source ) {
protected Annotation getArgumentAnnotation( ArgumentSource source ) {
for (Class annotation: ARGUMENT_ANNOTATIONS)
if (source.field.isAnnotationPresent(annotation))
return new ArgumentDescription(source.field.getAnnotation(annotation));
return source.field.getAnnotation(annotation);
throw new StingException("ArgumentAnnotation is not present for the argument field: " + source.field.getName());
}
@SuppressWarnings("unchecked")
public static boolean isArgumentDescriptionPresent(Field field) {
public static boolean isArgumentAnnotationPresent(Field field) {
for (Class annotation: ARGUMENT_ANNOTATIONS)
if (field.isAnnotationPresent(annotation))
return true;

View File

@ -308,7 +308,7 @@ public class ParsingEngine {
while( sourceClass != null ) {
Field[] fields = sourceClass.getDeclaredFields();
for( Field field: fields ) {
if( ArgumentTypeDescriptor.isArgumentDescriptionPresent(field) )
if( ArgumentTypeDescriptor.isArgumentAnnotationPresent(field) )
argumentSources.add( new ArgumentSource(sourceClass,field) );
if( field.isAnnotationPresent(ArgumentCollection.class) )
argumentSources.addAll( extractArgumentSources(field.getType()) );

View File

@ -32,6 +32,7 @@ import org.broadinstitute.sting.utils.genotype.GenotypeWriterFactory;
import org.broadinstitute.sting.gatk.GenomeAnalysisEngine;
import java.io.File;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Arrays;
@ -154,32 +155,13 @@ public class GenotypeWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
* @return Argument definition for the BAM file itself. Will not be null.
*/
private ArgumentDefinition createGenotypeFileArgumentDefinition(ArgumentSource source) {
ArgumentDescription description = this.getArgumentDescription(source);
Annotation annotation = this.getArgumentAnnotation(source);
boolean isFullNameProvided = description.fullName().trim().length() > 0;
boolean isShortNameProvided = description.shortName().trim().length() > 0;
String fullName = isFullNameProvided ? description.fullName().trim() : "variants_out";
// If the short name is provided, use that. If the user hasn't provided any names at all, use
// the default. If somewhere in the middle, leave the short name blank.
String shortName;
if( isShortNameProvided )
shortName = description.shortName().trim();
else if( !isFullNameProvided )
shortName = "varout";
else
shortName = null;
return new ArgumentDefinition( getIOType(source),
fullName,
shortName,
getDoc(source),
isRequired(source),
return new ArgumentDefinition( annotation,
"variants_out",
"varout",
false,
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source),
null );
}
@ -189,7 +171,8 @@ public class GenotypeWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
* @return Argument definition for the BAM file itself. Will not be null.
*/
private ArgumentDefinition createGenotypeFormatArgumentDefinition(ArgumentSource source) {
return new ArgumentDefinition( getIOType(source),
Annotation annotation = this.getArgumentAnnotation(source);
return new ArgumentDefinition( ArgumentDefinition.getIOType(annotation),
"variant_output_format",
"vf",
"Format to be used to represent variants; default is VCF",

View File

@ -31,6 +31,7 @@ import org.broadinstitute.sting.gatk.GenomeAnalysisEngine;
import org.broadinstitute.sting.gatk.io.StingSAMFileWriter;
import net.sf.samtools.SAMFileWriter;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Arrays;
import java.io.File;
@ -94,32 +95,12 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
* @return Argument definition for the BAM file itself. Will not be null.
*/
private ArgumentDefinition createBAMArgumentDefinition(ArgumentSource source) {
ArgumentDescription description = this.getArgumentDescription(source);
boolean isFullNameProvided = description.fullName().trim().length() > 0;
boolean isShortNameProvided = description.shortName().trim().length() > 0;
String fullName = isFullNameProvided ? description.fullName().trim() : DEFAULT_ARGUMENT_FULLNAME;
// If the short name is provided, use that. If the user hasn't provided any names at all, use
// the default. If somewhere in the middle, leave the short name blank.
String shortName;
if( isShortNameProvided )
shortName = description.shortName().trim();
else if( !isFullNameProvided )
shortName = DEFAULT_ARGUMENT_SHORTNAME;
else
shortName = null;
return new ArgumentDefinition( getIOType(source),
fullName,
shortName,
getDoc(source),
isRequired(source),
Annotation annotation = this.getArgumentAnnotation(source);
return new ArgumentDefinition( annotation,
DEFAULT_ARGUMENT_FULLNAME,
DEFAULT_ARGUMENT_SHORTNAME,
false,
source.isMultiValued(),
getExclusiveOf(source),
getValidationRegex(source),
null );
}
@ -129,7 +110,8 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor
* @return Argument definition for the BAM file itself. Will not be null.
*/
private ArgumentDefinition createBAMCompressionArgumentDefinition(ArgumentSource source) {
return new ArgumentDefinition( getIOType(source),
Annotation annotation = this.getArgumentAnnotation(source);
return new ArgumentDefinition( ArgumentDefinition.getIOType(annotation),
COMPRESSION_FULLNAME,
COMPRESSION_SHORTNAME,
"Compression level to use for writing BAM files",

View File

@ -6,7 +6,7 @@ import collection.mutable.ListBuffer
import org.broadinstitute.sting.queue.util.Logging
object QCommandLine extends Application with Logging {
var usage = """usage: java -jar Queue.jar [ -P name=value ] [ -P file.properties ] [ -I input.file ] [ -I input_files.list ] [ -bsub ] [ -dry ] [ -debug ] -S pipeline.scala"""
var usage = """usage: java -jar Queue.jar [-P name=value] [-P file.properties] [-I input.file] [-I input_files.list] [-bsub] [-bsubWait] [-dry] [-debug] -S pipeline.scala"""
override def main(args: Array[String]) = {
val qArgs: QArguments = try {