diff --git a/public/java/src/org/broadinstitute/sting/commandline/ArgumentTypeDescriptor.java b/public/java/src/org/broadinstitute/sting/commandline/ArgumentTypeDescriptor.java index dc32fcc16..7353305f1 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/ArgumentTypeDescriptor.java +++ b/public/java/src/org/broadinstitute/sting/commandline/ArgumentTypeDescriptor.java @@ -325,7 +325,7 @@ class RodBindingArgumentTypeDescriptor extends ArgumentTypeDescriptor { @Override public Object createTypeDefault(ParsingEngine parsingEngine, ArgumentSource source, Type type) { - Class parameterType = getParameterizedTypeClass(type); + Class parameterType = JVMUtils.getParameterizedTypeClass(type); return RodBinding.makeUnbound((Class)parameterType); } @@ -338,7 +338,7 @@ class RodBindingArgumentTypeDescriptor extends ArgumentTypeDescriptor { public Object parse(ParsingEngine parsingEngine, ArgumentSource source, Type type, ArgumentMatches matches) { ArgumentDefinition defaultDefinition = createDefaultArgumentDefinition(source); String value = getArgumentValue( defaultDefinition, matches ); - Class parameterType = getParameterizedTypeClass(type); + Class parameterType = JVMUtils.getParameterizedTypeClass(type); try { String name = defaultDefinition.fullName; @@ -400,16 +400,6 @@ class RodBindingArgumentTypeDescriptor extends ArgumentTypeDescriptor { value, source.field.getName(), e.getMessage())); } } - - private Class getParameterizedTypeClass(Type t) { - if ( t instanceof ParameterizedType ) { - ParameterizedType parameterizedType = (ParameterizedType)t; - if ( parameterizedType.getActualTypeArguments().length != 1 ) - throw new ReviewedStingException("BUG: more than 1 generic type found on class" + t); - return (Class)parameterizedType.getActualTypeArguments()[0]; - } else - throw new ReviewedStingException("BUG: could not find generic type on class " + t); - } } /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/FeatureManager.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/FeatureManager.java index c7dd6ef14..c99aea254 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/FeatureManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/tracks/FeatureManager.java @@ -123,7 +123,7 @@ public class FeatureManager { */ @Requires("featureClass != null") public Collection getByFeature(Class featureClass) { - Set consistentDescriptors = new HashSet(); + Set consistentDescriptors = new TreeSet(); if (featureClass == null) throw new IllegalArgumentException("trackRecordType value is null, please pass in an actual class object"); diff --git a/public/java/src/org/broadinstitute/sting/utils/classloader/JVMUtils.java b/public/java/src/org/broadinstitute/sting/utils/classloader/JVMUtils.java index e65b8f921..fa154fca3 100755 --- a/public/java/src/org/broadinstitute/sting/utils/classloader/JVMUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/classloader/JVMUtils.java @@ -224,4 +224,14 @@ public class JVMUtils { throw new StingException("Unknown type: " + type + " (" + type.getClass().getName() + ")"); } } + + public static Class getParameterizedTypeClass(Type t) { + if ( t instanceof ParameterizedType ) { + ParameterizedType parameterizedType = (ParameterizedType)t; + if ( parameterizedType.getActualTypeArguments().length != 1 ) + throw new ReviewedStingException("BUG: more than 1 generic type found on class" + t); + return (Class)parameterizedType.getActualTypeArguments()[0]; + } else + throw new ReviewedStingException("BUG: could not find generic type on class " + t); + } } diff --git a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java index 5b358519e..86f72428a 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java @@ -30,14 +30,18 @@ import com.sun.javadoc.FieldDoc; import com.sun.javadoc.RootDoc; import com.sun.javadoc.Tag; import org.apache.log4j.Logger; +import org.broad.tribble.Feature; import org.broadinstitute.sting.commandline.*; import org.broadinstitute.sting.gatk.CommandLineGATK; +import org.broadinstitute.sting.gatk.refdata.tracks.FeatureManager; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.classloader.JVMUtils; +import org.broadinstitute.sting.utils.collections.Pair; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.exceptions.StingException; import java.io.*; -import java.lang.reflect.Field; +import java.lang.reflect.*; import java.util.*; /** @@ -295,6 +299,8 @@ public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler { return fieldDoc; Field field = HelpUtils.getFieldForFieldDoc(fieldDoc); + if ( field == null ) + throw new RuntimeException("Could not find the field corresponding to " + fieldDoc + ", presumably because the field is inaccessible"); if ( field.isAnnotationPresent(ArgumentCollection.class) ) { ClassDoc typeDoc = getRootDoc().classNamed(fieldDoc.type().qualifiedTypeName()); if ( typeDoc == null ) @@ -319,15 +325,82 @@ public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler { return null; } + private static final int MAX_DISPLAY_NAME = 30; + Pair displayNames(String s1, String s2) { + if ( s1 == null ) return new Pair(s2, null); + if ( s2 == null ) return new Pair(s1, null); + + String l = s1.length() > s2.length() ? s1 : s2; + String s = s1.length() > s2.length() ? s2 : s1; + + if ( l.length() > MAX_DISPLAY_NAME ) + return new Pair(s, l); + else + return new Pair(l, s); + } + + protected String argumentTypeString(Type type) { + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType)type; + List subs = new ArrayList(); + for (Type actualType: parameterizedType.getActualTypeArguments()) + subs.add(argumentTypeString(actualType)); + return argumentTypeString(((ParameterizedType)type).getRawType()) + "[" + Utils.join(",", subs) + "]"; + } else if (type instanceof GenericArrayType) { + return argumentTypeString(((GenericArrayType)type).getGenericComponentType()) + "[]"; + } else if (type instanceof WildcardType) { + throw new RuntimeException("We don't support wildcards in arguments: " + type); + } else if (type instanceof Class) { + return ((Class) type).getSimpleName(); + } else { + throw new StingException("Unknown type: " + type); + } + } + + protected Class getFeatureTypeIfPossible(Type type) { + if ( type instanceof ParameterizedType) { + ParameterizedType paramType = (ParameterizedType)type; + if ( RodBinding.class.isAssignableFrom((Class)paramType.getRawType()) ) { + return (Class)JVMUtils.getParameterizedTypeClass(type); + } else { + for ( Type paramtype : paramType.getActualTypeArguments() ) { + Class x = getFeatureTypeIfPossible(paramtype); + if ( x != null ) + return x; + } + } + } + + return null; + } + protected Map docForArgument(FieldDoc fieldDoc, ArgumentSource source, ArgumentDefinition def) { Map root = new HashMap(); - root.put("name", def.shortName != null ? "-" + def.shortName : "--" + def.fullName ); + Pair names = displayNames("-" + def.shortName, "--" + def.fullName); - if ( def.shortName != null && def.fullName != null ) - root.put("synonyms", "--" + def.fullName); + root.put("name", names.getFirst() ); + + if ( names.getSecond() != null ) + root.put("synonyms", names.getSecond()); root.put("required", def.required ? "yes" : "no"); - root.put("type", def.argumentType.getSimpleName()); + + // type of the field + root.put("type", argumentTypeString(source.field.getGenericType())); + + Class featureClass = getFeatureTypeIfPossible(source.field.getGenericType()); + if ( featureClass != null ) { + // deal with the allowable types + FeatureManager manager = new FeatureManager(); + List rodTypes = new ArrayList(); + for (FeatureManager.FeatureDescriptor descriptor : manager.getByFeature(featureClass) ) { + rodTypes.add(String.format("%s", + GATKDocUtils.htmlFilenameForClass(descriptor.getCodecClass()), + descriptor.getName())); + } + + root.put("rodTypes", Utils.join(", ", rodTypes)); + } // summary and fulltext root.put("summary", def.doc != null ? def.doc : "");