diff --git a/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java b/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java index da2be74bf..3726e8e02 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java +++ b/public/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java @@ -34,6 +34,7 @@ import org.broadinstitute.sting.gatk.walkers.Attribution; import org.broadinstitute.sting.gatk.walkers.Walker; import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.ApplicationDetails; +import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.text.TextFormattingUtils; import java.util.*; diff --git a/public/java/src/org/broadinstitute/sting/gatk/filters/ReadFilter.java b/public/java/src/org/broadinstitute/sting/gatk/filters/ReadFilter.java index 227637761..003d9cd42 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/filters/ReadFilter.java +++ b/public/java/src/org/broadinstitute/sting/gatk/filters/ReadFilter.java @@ -2,6 +2,7 @@ package org.broadinstitute.sting.gatk.filters; import net.sf.picard.filter.SamRecordFilter; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; +import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; /** * A SamRecordFilter that also depends on the header. 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 384742302..24813f4c6 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/Walker.java @@ -31,6 +31,8 @@ import org.broadinstitute.sting.gatk.filters.MalformedReadFilter; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.baq.BAQ; import org.broadinstitute.sting.utils.collections.Pair; +import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; +import org.broadinstitute.sting.utils.help.WalkerDocumentationHandler; import java.util.List; @@ -44,6 +46,7 @@ import java.util.List; @ReadFilters(MalformedReadFilter.class) @PartitionBy(PartitionType.NONE) @BAQMode(QualityMode = BAQ.QualityMode.OVERWRITE_QUALS, ApplicationTime = BAQ.ApplicationTime.ON_INPUT) +@DocumentedGATKFeature( handler = WalkerDocumentationHandler.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/gatk/walkers/varianteval/stratifications/CpG.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java index 3e8a6ed17..e1f2ae983 100755 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/stratifications/CpG.java @@ -8,6 +8,18 @@ import org.broadinstitute.sting.utils.variantcontext.VariantContext; import java.util.ArrayList; import java.util.Set; +/** + * CpG is a stratification module for VariantEval that divides the input data by within/not within a CpG site + * + *

+ * It is a three-state stratification: + *

+ * A CpG site is defined as a site where the reference base at a locus is a C and the adjacent reference base in the 3' direction is a G. + */ public class CpG extends VariantStratifier { private ArrayList states; diff --git a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java new file mode 100644 index 000000000..02a7707e6 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeature.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011, 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.utils.help; + +import java.lang.annotation.*; + +/** + * An annotation to identify a class as a GATK capability for documentation + * + * @author depristo + */ +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface DocumentedGATKFeature { + Class handler(); +} diff --git a/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java new file mode 100644 index 000000000..e459e1543 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/help/DocumentedGATKFeatureHandler.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2011, 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.utils.help; + +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.FieldDoc; +import com.sun.javadoc.RootDoc; +import com.sun.javadoc.Tag; +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import org.broadinstitute.sting.commandline.*; +import org.broadinstitute.sting.gatk.CommandLineGATK; +import org.broadinstitute.sting.utils.Utils; +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; + +/** + * + */ +public abstract class DocumentedGATKFeatureHandler { + private GATKDoclet doclet; + + protected RootDoc getRootDoc() { + return this.doclet.rootDoc; + } + + public void setDoclet(GATKDoclet doclet) { + this.doclet = doclet; + } + + public boolean shouldBeProcessed(ClassDoc doc) { return true; } + + public String getDestinationFilename(ClassDoc doc) { + return ResourceBundleExtractorDoclet.getClassName(doc).replace(".", "_") + ".html"; + } + + public abstract String getGroupName(); + public abstract String getTemplateName(ClassDoc doc) throws IOException; + public abstract GATKDoclet.DocumentationData processOne(ClassDoc doc); +} 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 b6488cff9..e155923a5 100644 --- a/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java +++ b/public/java/src/org/broadinstitute/sting/utils/help/GATKDoclet.java @@ -24,29 +24,57 @@ package org.broadinstitute.sting.utils.help; -import com.sun.javadoc.*; +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.RootDoc; import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; -import org.broadinstitute.sting.commandline.*; -import org.broadinstitute.sting.gatk.CommandLineExecutable; -import org.broadinstitute.sting.gatk.CommandLineGATK; -import org.broadinstitute.sting.gatk.walkers.Walker; -import org.broadinstitute.sting.utils.Utils; -import org.broadinstitute.sting.utils.classloader.JVMUtils; +import org.apache.log4j.Logger; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; -import scala.reflect.Print; -import sun.tools.java.ClassNotFound; import java.io.*; -import java.lang.reflect.Field; 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 DocumentationData(String name, String summary, Map forTemplate) { + this.name = name; + 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); + data.put("summary", summary); + data.put("filename", filename); + data.put("group", group); + return data; + } + + public int compareTo(DocumentationData other) { + return this.name.compareTo(other.name); + } + } + RootDoc rootDoc; /** @@ -57,7 +85,6 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { */ public static boolean start(RootDoc rootDoc) throws IOException { GATKDoclet doclet = new GATKDoclet(); - //PrintStream out = doclet.loadData(rootDoc, false); doclet.processDocs(rootDoc, null); return true; } @@ -77,20 +104,20 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { Configuration cfg = new Configuration(); // Specify the data source where the template files come from. - // Here I set a file directory for it: cfg.setDirectoryForTemplateLoading(new File("settings/helpTemplates/")); // Specify how templates will see the data-model. This is an advanced topic... - // but just use this: cfg.setObjectWrapper(new DefaultObjectWrapper()); - List> indexData = new ArrayList>(); + List indexData = new ArrayList(); for ( ClassDoc doc : rootDoc.classes() ) { - if ( ResourceBundleExtractorDoclet.isWalker(doc) ) { // && getClassName(doc).contains("UGCalcLikelihoods")) { - System.out.printf("Walker class %s%n", doc); - indexData.add(processWalkerDocs(cfg, doc)); + DocumentedGATKFeatureHandler handler = getHandlerForClassDoc(doc); + if ( handler != null && handler.shouldBeProcessed(doc) ) { + DocumentationData docData = processDocumentationWithHandler(cfg, handler, doc); + indexData.add(docData); } } - processWalkerIndex(indexData,cfg); + + processIndex(cfg, indexData); } catch ( FileNotFoundException e ) { throw new RuntimeException(e); } catch ( IOException e ) { @@ -98,171 +125,91 @@ public class GATKDoclet extends ResourceBundleExtractorDoclet { } } - private void processWalkerIndex(List> indexData, Configuration cfg) throws IOException { + private DocumentedGATKFeatureHandler getHandlerForClassDoc(ClassDoc doc) { + try { + // todo -- what do I need the ? extends Object to pass the compiler? + Class docClass = ResourceBundleExtractorDoclet.getClassForDoc(doc); + if ( docClass.isAnnotationPresent(DocumentedGATKFeature.class) ) { + DocumentedGATKFeature feature = docClass.getAnnotation(DocumentedGATKFeature.class); + DocumentedGATKFeatureHandler handler = feature.handler().newInstance(); + handler.setDoclet(this); + return handler; + } 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 + } catch ( UnsatisfiedLinkError e) { + return null; // naughty BWA bindings + } + } + + private void processIndex(Configuration cfg, List indexData) throws IOException { /* Get or create a template */ Template temp = cfg.getTemplate("walker.index.template.html"); /* Merge data-model with template */ Writer out = new OutputStreamWriter(new FileOutputStream(new File("testdoc/index.html"))); try { - Map root = new HashMap(); - root.put("walkers", indexData); - temp.process(root, out); + temp.process(groupIndexData(indexData), out); out.flush(); } catch ( TemplateException e ) { throw new ReviewedStingException("Failed to create GATK documentation", e); } } - private Map processWalkerDocs(Configuration cfg, ClassDoc doc) throws IOException { - // Create the root hash - Map root = buildWalkerDataModel(doc); - - /* Get or create a template */ - Template temp = cfg.getTemplate("walker.template.html"); - - /* Merge data-model with template */ - File outputFile = new File(getClassName(doc).replace(".", "_") + ".html"); - File outputPath = new File("testdoc/" + outputFile); - try { - Writer out = new OutputStreamWriter(new FileOutputStream(outputPath)); - temp.process(root, out); - out.flush(); - } catch ( TemplateException e ) { - throw new ReviewedStingException("Failed to create GATK documentation", e); - } - - // add index data - Map indexData = new HashMap(); - indexData.put("filename", outputFile.toString()); - indexData.put("name", doc.name()); - indexData.put("summary", root.get("summary")); - return indexData; - } - - - private Map buildWalkerDataModel(ClassDoc classdoc) { + private Map groupIndexData(List indexData) { + // + // root -> data -> { summary -> y, filename -> z }, etc + // -> groups -> group1, group2, etc. Map root = new HashMap(); - root.put("name", classdoc.name()); + Collections.sort(indexData); - // Extract overrides from the doc tags. - StringBuilder summaryBuilder = new StringBuilder(); - for(Tag tag: classdoc.firstSentenceTags()) - summaryBuilder.append(tag.text()); - root.put("summary", summaryBuilder.toString()); - root.put("description", classdoc.commentText()); + List> data = new ArrayList>(); + Set groups = new HashSet(); - for(Tag tag: classdoc.tags()) { - root.put(tag.name(), tag.text()); + for ( DocumentationData indexDatum : indexData ) { + data.add(indexDatum.toMap()); + groups.add(indexDatum.group); } - ParsingEngine parsingEngine = createStandardGATKParsingEngine(); -// for (ArgumentDefinition argumentDefinition : parsingEngine.argumentDefinitions ) -// System.out.println(argumentDefinition); + root.put("data", data); + root.put("groups", new ArrayList(groups)); - Map> args = new HashMap>(); - root.put("arguments", args); - args.put("all", new ArrayList()); - args.put("required", new ArrayList()); - args.put("optional", new ArrayList()); - args.put("hidden", new ArrayList()); - args.put("depreciated", new ArrayList()); - try { - for ( ArgumentSource argumentSource : parsingEngine.extractArgumentSources(getClassForDoc(classdoc)) ) { - ArgumentDefinition argDef = argumentSource.createArgumentDefinitions().get(0); - FieldDoc fieldDoc = getFieldDoc(classdoc, argumentSource.field.getName()); - GATKDoc doc = docForArgument(fieldDoc, argDef); // todo -- why can you have multiple ones? - String kind = "optional"; - if ( argumentSource.isRequired() ) kind = "required"; - else if ( argumentSource.isHidden() ) kind = "hidden"; - else if ( argumentSource.isDeprecated() ) kind = "depreciated"; - args.get(kind).add(doc.toDataModel()); - args.get("all").add(doc.toDataModel()); - System.out.printf("Processing %s%n", argumentSource); - } - } catch ( ClassNotFoundException e ) { - throw new RuntimeException(e); - } - - System.out.printf("Root is %s%n", root); return root; } -// protected String withDefault(String val, String def) { -// return val == null ? def : val; -// } + private DocumentationData processDocumentationWithHandler(Configuration cfg, + DocumentedGATKFeatureHandler handler, + ClassDoc doc) + throws IOException { + System.out.printf("Processing documentation for class %s%n", doc); - protected ParsingEngine createStandardGATKParsingEngine() { - CommandLineProgram clp = new CommandLineGATK(); + DocumentationData docData = handler.processOne(doc); + docData.setGroup(handler.getGroupName()); + + // Get or create a template + Template temp = cfg.getTemplate(handler.getTemplateName(doc)); + + // Merge data-model with template + String filename = handler.getDestinationFilename(doc); + docData.setFilename(filename); + File outputPath = new File("testdoc/" + filename); try { - CommandLineProgram.start(clp, new String[]{}, true); - return clp.parser; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private FieldDoc getFieldDoc(ClassDoc classDoc, String name) { - return getFieldDoc(classDoc, name, true); - } - - private FieldDoc getFieldDoc(ClassDoc classDoc, String name, boolean primary) { - System.out.printf("Looking for %s in %s%n", name, classDoc.name()); - for ( FieldDoc fieldDoc : classDoc.fields(false) ) { - System.out.printf("fieldDoc " + fieldDoc + " name " + fieldDoc.name()); - if ( fieldDoc.name().equals(name) ) - return fieldDoc; - - Field field = getFieldForFieldDoc(fieldDoc); - if ( field.isAnnotationPresent(ArgumentCollection.class) ) { - ClassDoc typeDoc = this.rootDoc.classNamed(fieldDoc.type().qualifiedTypeName()); - if ( typeDoc == null ) - throw new ReviewedStingException("Tried to get javadocs for ArgumentCollection field " + fieldDoc + " but could't find the class in the RootDoc"); - else { - FieldDoc result = getFieldDoc(typeDoc, name, false); - if ( result != null ) - return result; - // else keep searching - } - } + Writer out = new OutputStreamWriter(new FileOutputStream(outputPath)); + temp.process(docData.forTemplate, out); + out.flush(); + } catch ( TemplateException e ) { + throw new ReviewedStingException("Failed to create GATK documentation", e); } - // if we didn't find it here, wander up to the superclass to find the field - if ( classDoc.superclass() != null ) { - return getFieldDoc(classDoc.superclass(), name, false); - } - - if ( primary ) - throw new RuntimeException("No field found for expected field " + name); - else - return null; - } - - protected GATKDoc docForArgument(FieldDoc fieldDoc, ArgumentDefinition def) { - final String name = def.fullName != null ? "--" + def.fullName : "-" + def.shortName; - GATKDoc doc = new GATKDoc(GATKDoc.DocType.WALKER_ARG, name); - - if ( def.fullName != null && def.shortName != null) - doc.addSynonym("-" + def.shortName); - - doc.addTag("required", def.required ? "yes" : "no"); - doc.addTag("type", def.argumentType.getSimpleName()); - if ( def.doc != null ) doc.setSummary(def.doc); - - List attributes = new ArrayList(); - attributes.add(def.ioType.annotationClass.getSimpleName()); - if ( def.required ) attributes.add("required"); - if ( def.isFlag ) attributes.add("flag"); - if ( def.isHidden ) attributes.add("hidden"); - doc.addTag("attributes", Utils.join(",", attributes)); - - // todo -- need depreciated value - - doc.addTag("options", def.validOptions == null ? GATKDoc.NA_STRING : Utils.join(",", def.validOptions)); - - doc.setFulltext(fieldDoc.commentText()); - - return doc; + return docData; } } diff --git a/public/java/src/org/broadinstitute/sting/utils/help/WalkerDocumentationHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/WalkerDocumentationHandler.java new file mode 100644 index 000000000..f9109db72 --- /dev/null +++ b/public/java/src/org/broadinstitute/sting/utils/help/WalkerDocumentationHandler.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2011, 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.utils.help; + +import com.sun.javadoc.ClassDoc; +import com.sun.javadoc.FieldDoc; +import com.sun.javadoc.RootDoc; +import com.sun.javadoc.Tag; +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import org.broadinstitute.sting.commandline.*; +import org.broadinstitute.sting.gatk.CommandLineGATK; +import org.broadinstitute.sting.utils.Utils; +import org.broadinstitute.sting.utils.classloader.JVMUtils; +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; + +/** + * + */ +public class WalkerDocumentationHandler extends DocumentedGATKFeatureHandler { + @Override + public boolean shouldBeProcessed(ClassDoc doc) { + try { + Class type = ResourceBundleExtractorDoclet.getClassForDoc(doc); + return JVMUtils.isConcrete(type); + } catch ( ClassNotFoundException e ) { + return false; + } + } + + @Override + public String getGroupName() { return "GATK Walkers"; } + + @Override + public String getTemplateName(ClassDoc doc) throws IOException { + return "walker.template.html"; + } + + @Override + public GATKDoclet.DocumentationData processOne(ClassDoc doc) { + System.out.printf("Walker class %s%n", 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) { + Map root = new HashMap(); + + root.put("name", classdoc.name()); + + // Extract overrides from the doc tags. + StringBuilder summaryBuilder = new StringBuilder(); + for(Tag tag: classdoc.firstSentenceTags()) + summaryBuilder.append(tag.text()); + root.put("summary", summaryBuilder.toString()); + root.put("description", classdoc.commentText()); + + for(Tag tag: classdoc.tags()) { + root.put(tag.name(), tag.text()); + } + + ParsingEngine parsingEngine = createStandardGATKParsingEngine(); + + Map> args = new HashMap>(); + root.put("arguments", args); + args.put("all", new ArrayList()); + args.put("required", new ArrayList()); + args.put("optional", new ArrayList()); + args.put("hidden", new ArrayList()); + args.put("depreciated", new ArrayList()); + try { + for ( ArgumentSource argumentSource : parsingEngine.extractArgumentSources(ResourceBundleExtractorDoclet.getClassForDoc(classdoc)) ) { + ArgumentDefinition argDef = argumentSource.createArgumentDefinitions().get(0); + FieldDoc fieldDoc = getFieldDoc(classdoc, argumentSource.field.getName()); + GATKDoc doc = docForArgument(fieldDoc, argDef); // todo -- why can you have multiple ones? + String kind = "optional"; + if ( argumentSource.isRequired() ) kind = "required"; + else if ( argumentSource.isHidden() ) kind = "hidden"; + else if ( argumentSource.isDeprecated() ) kind = "depreciated"; + args.get(kind).add(doc.toDataModel()); + args.get("all").add(doc.toDataModel()); + System.out.printf("Processing %s%n", argumentSource); + } + } catch ( ClassNotFoundException e ) { + throw new RuntimeException(e); + } + + //System.out.printf("Root is %s%n", root); + return root; + } + + protected ParsingEngine createStandardGATKParsingEngine() { + CommandLineProgram clp = new CommandLineGATK(); + try { + CommandLineProgram.start(clp, new String[]{}, true); + return clp.parser; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private FieldDoc getFieldDoc(ClassDoc classDoc, String name) { + return getFieldDoc(classDoc, name, true); + } + + private FieldDoc getFieldDoc(ClassDoc classDoc, String name, boolean primary) { + System.out.printf("Looking for %s in %s%n", name, classDoc.name()); + for ( FieldDoc fieldDoc : classDoc.fields(false) ) { + System.out.printf("fieldDoc " + fieldDoc + " name " + fieldDoc.name()); + if ( fieldDoc.name().equals(name) ) + return fieldDoc; + + Field field = ResourceBundleExtractorDoclet.getFieldForFieldDoc(fieldDoc); + if ( field.isAnnotationPresent(ArgumentCollection.class) ) { + ClassDoc typeDoc = getRootDoc().classNamed(fieldDoc.type().qualifiedTypeName()); + if ( typeDoc == null ) + throw new ReviewedStingException("Tried to get javadocs for ArgumentCollection field " + fieldDoc + " but could't find the class in the RootDoc"); + else { + FieldDoc result = getFieldDoc(typeDoc, name, false); + if ( result != null ) + return result; + // else keep searching + } + } + } + + // if we didn't find it here, wander up to the superclass to find the field + if ( classDoc.superclass() != null ) { + return getFieldDoc(classDoc.superclass(), name, false); + } + + if ( primary ) + throw new RuntimeException("No field found for expected field " + name); + else + return null; + } + + protected GATKDoc docForArgument(FieldDoc fieldDoc, ArgumentDefinition def) { + final String name = def.fullName != null ? "--" + def.fullName : "-" + def.shortName; + GATKDoc doc = new GATKDoc(GATKDoc.DocType.WALKER_ARG, name); + + if ( def.fullName != null && def.shortName != null) + doc.addSynonym("-" + def.shortName); + + doc.addTag("required", def.required ? "yes" : "no"); + doc.addTag("type", def.argumentType.getSimpleName()); + if ( def.doc != null ) doc.setSummary(def.doc); + + List attributes = new ArrayList(); + attributes.add(def.ioType.annotationClass.getSimpleName()); + if ( def.required ) attributes.add("required"); + if ( def.isFlag ) attributes.add("flag"); + if ( def.isHidden ) attributes.add("hidden"); + doc.addTag("attributes", Utils.join(",", attributes)); + + // todo -- need depreciated value + + doc.addTag("options", def.validOptions == null ? GATKDoc.NA_STRING : Utils.join(",", def.validOptions)); + + doc.setFulltext(fieldDoc.commentText()); + + return doc; + } +} diff --git a/settings/helpTemplates/walker.index.template.html b/settings/helpTemplates/walker.index.template.html index 5d4cd84d4..83020a6e0 100644 --- a/settings/helpTemplates/walker.index.template.html +++ b/settings/helpTemplates/walker.index.template.html @@ -1,21 +1,30 @@ - - - GATK walker index - - -

GATK walker index

+<#macro emitGroup group> +

${group}

- <#list walkers as walker> - - - - - + <#list data as datum> + <#if datum.group == group> + + + + + +
Name Summary
${walker.name}${walker.summary}
${datum.name}${datum.summary}
+ + + + + GATK documentation index + + +

GATK documentation index

+ <#list groups as group> + <@emitGroup group=group/> +