From 7420ed098e722610dbf9dcac00320a30ca1ba073 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Sat, 23 Jul 2011 22:07:30 -0400 Subject: [PATCH] Semi-working version of extraDocs tag in annotation to refer to one capability being accessible in another Required a significant refactoring of the GATKDoclet, which now has a unified place where the ClassDoc, class, annotation, and handler are all stored together. --- build.xml | 2 +- .../sting/gatk/CommandLineGATK.java | 11 +- .../sting/gatk/walkers/Walker.java | 4 +- .../utils/help/DocumentedGATKFeature.java | 9 +- .../help/DocumentedGATKFeatureHandler.java | 21 +-- .../sting/utils/help/GATKDoclet.java | 144 +++++++++++------- .../help/GenericDocumentationHandler.java | 32 ++-- settings/helpTemplates/generic.template.html | 61 +++++--- 8 files changed, 163 insertions(+), 121 deletions(-) diff --git a/build.xml b/build.xml index b43f3421e..ed7802b1d 100644 --- a/build.xml +++ b/build.xml @@ -468,7 +468,7 @@ - diff --git a/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java b/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java index f8a2de316..905e75584 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java +++ b/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java @@ -30,6 +30,7 @@ import org.broadinstitute.sting.commandline.Argument; import org.broadinstitute.sting.commandline.ArgumentCollection; import org.broadinstitute.sting.commandline.CommandLineProgram; import org.broadinstitute.sting.gatk.arguments.GATKArgumentCollection; +import org.broadinstitute.sting.gatk.filters.ReadFilter; import org.broadinstitute.sting.gatk.walkers.Attribution; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -40,12 +41,8 @@ import org.broadinstitute.sting.utils.text.TextFormattingUtils; import java.util.*; /** - * @author aaron - * @version 1.0 - * @date May 8, 2009 - *

- * Class CommandLineGATK - *

+ * The GATK engine itself. Manages map/reduce data access and runs walkers. + * * We run command line GATK programs using this class. It gets the command line args, parses them, and hands the * gatk all the parsed out information. Pretty much anything dealing with the underlying system should go here, * the gatk engine should deal with any data related information. @@ -53,6 +50,8 @@ import java.util.*; @DocumentedGATKFeature( groupName = "GATK Engine", summary = "Features and arguments for the GATK engine itself, available to all walkers." ) +//, +// extraDocs = { ReadFilter.class, UserException.class }) public class CommandLineGATK extends CommandLineExecutable { @Argument(fullName = "analysis_type", shortName = "T", doc = "Type of analysis to run") private String analysisName = null; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java index a5d2cd5b3..9e261a0b1 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java @@ -26,6 +26,7 @@ package org.broadinstitute.sting.gatk.walkers; import org.apache.log4j.Logger; +import org.broadinstitute.sting.gatk.CommandLineGATK; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.filters.MalformedReadFilter; import org.broadinstitute.sting.utils.GenomeLoc; @@ -48,7 +49,8 @@ import java.util.List; @BAQMode(QualityMode = BAQ.QualityMode.OVERWRITE_QUALS, ApplicationTime = BAQ.ApplicationTime.ON_INPUT) @DocumentedGATKFeature( groupName = "GATK walkers", - summary = "General tools available for running on the command line as part of the GATK package" ) + summary = "General tools available for running on the command line as part of the GATK package", + extraDocs = {CommandLineGATK.class}) public abstract class Walker { final protected static Logger logger = Logger.getLogger(Walker.class); private GenomeAnalysisEngine toolkit; diff --git a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java index 689d1b7ad..710503ca8 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java @@ -36,8 +36,9 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface DocumentedGATKFeature { - boolean enable() default true; - String groupName(); - String summary() default ""; - Class handler() default GenericDocumentationHandler.class; + public boolean enable() default true; + public String groupName(); + public String summary() default ""; + public Class handler() default GenericDocumentationHandler.class; + public Class[] extraDocs() default {}; } diff --git a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java index ddcc12ab3..42bd41905 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java @@ -28,14 +28,13 @@ import com.sun.javadoc.ClassDoc; import com.sun.javadoc.RootDoc; import java.io.*; +import java.util.Map; /** * */ public abstract class DocumentedGATKFeatureHandler { private GATKDoclet doclet; - private String groupName; - private DocumentedGATKFeature annotation; protected RootDoc getRootDoc() { return this.doclet.rootDoc; @@ -45,28 +44,12 @@ public abstract class DocumentedGATKFeatureHandler { this.doclet = doclet; } - public DocumentedGATKFeature getAnnotation() { - return annotation; - } - - public void setAnnotation(DocumentedGATKFeature annotation) { - this.annotation = annotation; - } - public boolean shouldBeProcessed(ClassDoc doc) { return true; } public String getDestinationFilename(ClassDoc doc) { return HelpUtils.getClassName(doc).replace(".", "_") + ".html"; } - final public String getGroupName() { - return groupName; - } - - final public void setGroupName(String groupName) { - this.groupName = groupName; - } - public abstract String getTemplateName(ClassDoc doc) throws IOException; - public abstract GATKDoclet.DocumentationData processOne(ClassDoc doc); + public abstract void processOne(GATKDoclet.DocWorkUnit toProcess, Map all); } diff --git a/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java b/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java index ae8ab2c06..70d455794 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java @@ -42,25 +42,34 @@ import java.util.*; public class GATKDoclet extends ResourceBundleExtractorDoclet { final protected static Logger logger = Logger.getLogger(GATKDoclet.class); - public static class DocumentationData implements Comparable { - String name, summary, filename; - Map forTemplate; - String group; + public static class DocWorkUnit implements Comparable { + // known at the start + String name, filename, group; + DocumentedGATKFeatureHandler handler; + ClassDoc classDoc; + Class clazz; + DocumentedGATKFeature annotation; - public DocumentationData(String name, String summary, Map forTemplate) { + // set by the handler + String summary; + Map forTemplate; + + public DocWorkUnit(DocumentedGATKFeature annotation, String name, String filename, String group, + DocumentedGATKFeatureHandler handler, ClassDoc classDoc, Class clazz) { + this.annotation = annotation; this.name = name; + this.filename = filename; + this.group = group; + this.handler = handler; + this.classDoc = classDoc; + this.clazz = clazz; + } + + public void setHandlerContent(String summary, Map forTemplate) { this.summary = summary; this.forTemplate = forTemplate; } - public void setGroup(String group) { - this.group = group; - } - - public void setFilename(String filename) { - this.filename = filename; - } - public Map toMap() { Map data = new HashMap(); data.put("name", name); @@ -70,7 +79,7 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { return data; } - public int compareTo(DocumentationData other) { + public int compareTo(DocWorkUnit other) { return this.name.compareTo(other.name); } } @@ -93,6 +102,26 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { return ResourceBundleExtractorDoclet.optionLength(option); } + public Map workUnits() { + Map m = new HashMap(); + + for ( ClassDoc doc : rootDoc.classes() ) { + System.out.printf("Considering %s%n", doc); + Class clazz = getClassForClassDoc(doc); + DocumentedGATKFeature feature = getFeatureForClassDoc(doc); + DocumentedGATKFeatureHandler handler = createHandler(doc, feature); + if ( handler != null && handler.shouldBeProcessed(doc) ) { + String filename = handler.getDestinationFilename(doc); + DocWorkUnit unit = new DocWorkUnit(feature, + doc.name(), filename, feature.groupName(), + handler, doc, clazz ); + m.put(clazz, unit); + } + } + + return m; + } + @Override protected void processDocs(RootDoc rootDoc, PrintStream ignore) { // setup the global access to the root @@ -108,19 +137,12 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { // Specify how templates will see the data-model. This is an advanced topic... cfg.setObjectWrapper(new DefaultObjectWrapper()); - List indexData = new ArrayList(); - Set docFeatures = new HashSet(); - for ( ClassDoc doc : rootDoc.classes() ) { - System.out.printf("Considering %s%n", doc); - DocumentedGATKFeatureHandler handler = getHandlerForClassDoc(doc); - if ( handler != null && handler.shouldBeProcessed(doc) ) { - DocumentationData docData = processDocumentationWithHandler(cfg, handler, doc); - docFeatures.add(handler.getAnnotation()); - indexData.add(docData); - } + Map workUnitMap = workUnits(); + for ( DocWorkUnit workUnit : workUnitMap.values() ) { + processDocWorkUnit(cfg, workUnit, workUnitMap); } - processIndex(cfg, indexData, new ArrayList(docFeatures)); + processIndex(cfg, new ArrayList(workUnitMap.values())); } catch ( FileNotFoundException e ) { throw new RuntimeException(e); } catch ( IOException e ) { @@ -128,53 +150,66 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { } } - private DocumentedGATKFeatureHandler getHandlerForClassDoc(ClassDoc doc) { + private DocumentedGATKFeatureHandler createHandler(ClassDoc doc, DocumentedGATKFeature feature) { try { - // todo -- what do I need the ? extends Object to pass the compiler? - Class docClass = HelpUtils.getClassForDoc(doc); - if ( docClass.isAnnotationPresent(DocumentedGATKFeature.class) ) { - DocumentedGATKFeature feature = docClass.getAnnotation(DocumentedGATKFeature.class); + if ( feature != null ) { if ( feature.enable() ) { DocumentedGATKFeatureHandler handler = feature.handler().newInstance(); - handler.setGroupName(feature.groupName()); handler.setDoclet(this); - handler.setAnnotation(feature); return handler; } else { logger.info("Skipping disabled Documentation for " + doc); - return null; } - } else { - return null; // not annotated so it shouldn't be documented } - } catch ( ClassNotFoundException e) { - //logger.warn("Couldn't find class for ClassDoc " + doc); - // we got a classdoc for a class we can't find. Maybe in a library or something - return null; } catch ( IllegalAccessException e) { throw new RuntimeException(e); // the constructor is now private -- this is an error } catch ( InstantiationException e) { throw new RuntimeException(e); // the constructor is now private -- this is an error + } + + return null; + } + + private DocumentedGATKFeature getFeatureForClassDoc(ClassDoc doc) { + // todo -- what do I need the ? extends Object to pass the compiler? + Class docClass = getClassForClassDoc(doc); + if ( docClass != null && docClass.isAnnotationPresent(DocumentedGATKFeature.class) ) { + return docClass.getAnnotation(DocumentedGATKFeature.class); + } else { + return null; // not annotated so it shouldn't be documented + } + } + + private Class getClassForClassDoc(ClassDoc doc) { + try { + // todo -- what do I need the ? extends Object to pass the compiler? + return (Class)HelpUtils.getClassForDoc(doc); + } catch ( ClassNotFoundException e) { + //logger.warn("Couldn't find class for ClassDoc " + doc); + // we got a classdoc for a class we can't find. Maybe in a library or something + return null; + } catch ( NoClassDefFoundError e ) { + return null; } catch ( UnsatisfiedLinkError e) { return null; // naughty BWA bindings } } - private void processIndex(Configuration cfg, List indexData, List docFeatures) throws IOException { + private void processIndex(Configuration cfg, List indexData) throws IOException { /* Get or create a template */ Template temp = cfg.getTemplate("generic.index.template.html"); /* Merge data-model with template */ Writer out = new OutputStreamWriter(new FileOutputStream(new File("testdoc/index.html"))); try { - temp.process(groupIndexData(indexData, docFeatures), out); + temp.process(groupIndexData(indexData), out); out.flush(); } catch ( TemplateException e ) { throw new ReviewedStingException("Failed to create GATK documentation", e); } } - private Map groupIndexData(List indexData, List docFeatures) { + private Map groupIndexData(List indexData) { // // root -> data -> { summary -> y, filename -> z }, etc // -> groups -> group1, group2, etc. @@ -182,9 +217,11 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { Collections.sort(indexData); + Set docFeatures = new HashSet(); List> data = new ArrayList>(); - for ( DocumentationData indexDatum : indexData ) { - data.add(indexDatum.toMap()); + for ( DocWorkUnit workUnit : indexData ) { + data.add(workUnit.toMap()); + docFeatures.add(workUnit.annotation); } List> groups = new ArrayList>(); @@ -205,30 +242,23 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { return root; } - private DocumentationData processDocumentationWithHandler(Configuration cfg, - DocumentedGATKFeatureHandler handler, - ClassDoc doc) + private void processDocWorkUnit(Configuration cfg, DocWorkUnit unit, Map all) throws IOException { - System.out.printf("Processing documentation for class %s%n", doc); + System.out.printf("Processing documentation for class %s%n", unit.classDoc); - DocumentationData docData = handler.processOne(doc); - docData.setGroup(handler.getGroupName()); + unit.handler.processOne(unit, all); // Get or create a template - Template temp = cfg.getTemplate(handler.getTemplateName(doc)); + Template temp = cfg.getTemplate(unit.handler.getTemplateName(unit.classDoc)); // Merge data-model with template - String filename = handler.getDestinationFilename(doc); - docData.setFilename(filename); - File outputPath = new File("testdoc/" + filename); + File outputPath = new File("testdoc/" + unit.filename); try { Writer out = new OutputStreamWriter(new FileOutputStream(outputPath)); - temp.process(docData.forTemplate, out); + temp.process(unit.forTemplate, out); out.flush(); } catch ( TemplateException e ) { throw new ReviewedStingException("Failed to create GATK documentation", e); } - - return docData; } } 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 a4e3e5031..d85e86bfe 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java @@ -35,10 +35,7 @@ import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.*; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @@ -54,20 +51,16 @@ public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler { } } + @Override public String getTemplateName(ClassDoc doc) throws IOException { return "generic.template.html"; } @Override - public GATKDoclet.DocumentationData processOne(ClassDoc doc) { - System.out.printf("%s class %s%n", getGroupName(), doc); - Map root = buildWalkerDataModel(doc); // Create the root hash - return new GATKDoclet.DocumentationData(doc.name(), (String)root.get("summary"), root); - } - - - private Map buildWalkerDataModel(ClassDoc classdoc) { + public void processOne(GATKDoclet.DocWorkUnit toProcess, Map all) { + System.out.printf("%s class %s%n", toProcess.group, toProcess.classDoc); + ClassDoc classdoc = toProcess.classDoc; Map root = new HashMap(); root.put("name", classdoc.name()); @@ -109,8 +102,21 @@ public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler { throw new RuntimeException(e); } + List> extraDocsData = new ArrayList>(); + for ( Class extraDocClass : toProcess.annotation.extraDocs() ) { + final GATKDoclet.DocWorkUnit otherUnit = all.get(extraDocClass); + if ( otherUnit == null ) + throw new ReviewedStingException("Requested extraDocs for class without any documentation: " + extraDocClass); + extraDocsData.add( + new HashMap(){{ + put("filename", otherUnit.filename); + put("name", otherUnit.name);}}); + + } + root.put("extradocs", extraDocsData); + //System.out.printf("Root is %s%n", root); - return root; + toProcess.setHandlerContent(summaryBuilder.toString(), root); } protected ParsingEngine createStandardGATKParsingEngine() { diff --git a/settings/helpTemplates/generic.template.html b/settings/helpTemplates/generic.template.html index ecf24a56e..27c26749e 100644 --- a/settings/helpTemplates/generic.template.html +++ b/settings/helpTemplates/generic.template.html @@ -38,26 +38,47 @@

Description

${description} - <#-- Create the argument summary --> -

Arguments

- - - - - - - - <@argumentlist name="Required" myargs=arguments.required/> - <@argumentlist name="Optional" myargs=arguments.optional/> - <@argumentlist name="Hidden" myargs=arguments.hidden/> - <@argumentlist name="Depreciated" myargs=arguments.depreciated/> -
NameSynonymsTypeSummary
- - <#-- Create the argument details --> -

Argument details

- <#list arguments.all as arg> - <@argumentDetails arg=arg/> - + <#-- Create the argument summary --> + <#if arguments.all?size != 0> +
+

Feature specific arguments

+ + + + + + + + <@argumentlist name="Required" myargs=arguments.required/> + <@argumentlist name="Optional" myargs=arguments.optional/> + <@argumentlist name="Hidden" myargs=arguments.hidden/> + <@argumentlist name="Depreciated" myargs=arguments.depreciated/> +
NameSynonymsTypeSummary
+ + + <#-- Create references to related capabilities if appropriate --> + <#if extradocs?size != 0> +
+

Related capabilities

+ The arguments described in the entries below can be supplied to this tool to modify + its behavior. For example, the -L argument directs the GATK engine restricts processing + to specific genomic intervals. This capability is available to all GATK walkers. + + + + <#-- List all of the --> + <#if arguments.all?size != 0> +
+ <#-- Create the argument details --> +

Argument details

+ <#list arguments.all as arg> + <@argumentDetails arg=arg/> + +