From 439c34ed38b85e116991bed208402754eb74f0a1 Mon Sep 17 00:00:00 2001 From: aaron Date: Mon, 22 Mar 2010 07:39:20 +0000 Subject: [PATCH] clean-up before annotating VariantEval2 for output. git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3055 348d0f76-0448-11de-a6fe-93d51630548a --- .../utils/report/AnalysisModuleScanner.java | 18 +-- .../utils/report/ReportMarshaller.java | 119 +++++++++--------- .../utils/report/chunks/AnalysisChunk.java | 85 ------------- .../playground/utils/report/chunks/Chunk.java | 41 ------ .../utils/report/chunks/DataPointChunk.java | 88 ------------- .../utils/report/chunks/ParameterChunk.java | 89 ------------- .../utils/report/chunks/TableChunk.java | 109 ---------------- .../playground/utils/report/tags/Table.java | 20 --- .../utils/report/utils/ComplexDataUtils.java | 81 ++++++++++++ .../playground/utils/report/utils/Node.java | 49 ++++++++ .../utils/report/utils/TableType.java | 17 +++ .../report/AnalysisModuleScannerTest.java | 20 +-- 12 files changed, 208 insertions(+), 528 deletions(-) delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/chunks/AnalysisChunk.java delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/chunks/Chunk.java delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/chunks/DataPointChunk.java delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/chunks/ParameterChunk.java delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/chunks/TableChunk.java delete mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/tags/Table.java create mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/utils/ComplexDataUtils.java create mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/utils/Node.java create mode 100644 java/src/org/broadinstitute/sting/playground/utils/report/utils/TableType.java diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScanner.java b/java/src/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScanner.java index 382086316..e13f88ebf 100644 --- a/java/src/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScanner.java +++ b/java/src/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScanner.java @@ -26,7 +26,6 @@ package org.broadinstitute.sting.playground.utils.report; import org.broadinstitute.sting.playground.utils.report.tags.Analysis; import org.broadinstitute.sting.playground.utils.report.tags.DataPoint; import org.broadinstitute.sting.playground.utils.report.tags.Param; -import org.broadinstitute.sting.playground.utils.report.tags.Table; import org.broadinstitute.sting.utils.StingException; import java.lang.annotation.Annotation; @@ -46,10 +45,9 @@ import java.util.Map; public class AnalysisModuleScanner { // what we extracted from the class - private Map parameters = new HashMap(); // the parameter annotations - private Map tables = new HashMap(); // the table annotations - private Map datums = new HashMap(); // the data we've discovered - private Analysis analysis; // the analysis annotation + private Map parameters = new HashMap(); // the parameter annotations + private Map datums = new HashMap(); // the data we've discovered + private Analysis analysis; // the analysis annotation // private storage of the class type private final Class cls; @@ -92,8 +90,6 @@ public class AnalysisModuleScanner { for (Annotation annotation : f.getAnnotations()) { if (annotation.annotationType().equals(Param.class)) parameters.put(f, (Param) annotation); - if (annotation.annotationType().equals(Table.class)) - tables.put(f,(Table) annotation); if (annotation.annotationType().equals(DataPoint.class)) datums.put(f,(DataPoint) annotation); } @@ -107,14 +103,6 @@ public class AnalysisModuleScanner { return parameters; } - /** - * - * @return a list of table annotations found - */ - public Map getTables() { - return tables; - } - /** * * @return a map of the datum annotations found diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/ReportMarshaller.java b/java/src/org/broadinstitute/sting/playground/utils/report/ReportMarshaller.java index 47e51bbdc..5f15379ef 100644 --- a/java/src/org/broadinstitute/sting/playground/utils/report/ReportMarshaller.java +++ b/java/src/org/broadinstitute/sting/playground/utils/report/ReportMarshaller.java @@ -27,17 +27,15 @@ import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException; -import org.broadinstitute.sting.playground.utils.report.chunks.AnalysisChunk; -import org.broadinstitute.sting.playground.utils.report.chunks.DataPointChunk; -import org.broadinstitute.sting.playground.utils.report.chunks.ParameterChunk; -import org.broadinstitute.sting.playground.utils.report.chunks.TableChunk; -import org.broadinstitute.sting.utils.Pair; +import org.broadinstitute.sting.playground.utils.report.utils.ComplexDataUtils; +import org.broadinstitute.sting.playground.utils.report.utils.Node; +import org.broadinstitute.sting.utils.StingException; import java.io.*; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; @@ -52,9 +50,8 @@ public class ReportMarshaller { private Template temp; // the aggregation of all our analyses - private HashMap map; - private List analysisObjects; - private final File writeLocation; + private Node root; + private File writeLocation; /** * create a marshaled object * @@ -62,10 +59,15 @@ public class ReportMarshaller { * @param template the template to use */ public ReportMarshaller(String reportName, File filename, Template template) { - map = new HashMap(); - analysisObjects = new ArrayList(); - map.put("title",reportName); + init(reportName, filename); temp = template; + } + + private void init(String reportName, File filename) { + root = new Node(reportName); + Node title= new Node("title"); + title.addChild(new Node(reportName)); + root.addChild(title); this.writeLocation = filename; } @@ -75,11 +77,8 @@ public class ReportMarshaller { * @param reportName the report name */ public ReportMarshaller(String reportName, File filename) { - map = new HashMap(); - analysisObjects = new ArrayList(); - map.put("title",reportName); + init(reportName,filename); temp = createTemplate(); - this.writeLocation = filename; } @@ -93,28 +92,21 @@ public class ReportMarshaller { HashMap analysisMap = new HashMap(); AnalysisModuleScanner moduleScanner = new AnalysisModuleScanner(toMarshall); - Pair pair; + Node analysis = addAnalysis(moduleScanner); - pair = addAnalysis(moduleScanner); - analysisMap.put(pair.first,pair.second); - - pair = addParameters(toMarshall, moduleScanner); - analysisMap.put(pair.first,pair.second); - - pair = addDataPoints(toMarshall, moduleScanner); - analysisMap.put(pair.first,pair.second); - - pair = addTables(toMarshall, moduleScanner); - analysisMap.put(pair.first,pair.second); - - // add it to the list of analysis maps we have - analysisObjects.add(analysisMap); + analysis.addAllChildren(getParameterNodes(toMarshall, moduleScanner)); + analysis.addAllChildren(getDataPointNodes(toMarshall, moduleScanner)); + // add this analysis to the root node + root.addChild(analysis); } - private Pair addAnalysis(AnalysisModuleScanner moduleScanner) { - AnalysisChunk chunk = new AnalysisChunk(moduleScanner); - return new Pair("analysis",chunk); + private Node addAnalysis(AnalysisModuleScanner moduleScanner) { + Node analysis = new Node(moduleScanner.getAnalysis().name()); + Node description = new Node("description"); + description.createSubNode(moduleScanner.getAnalysis().description()); + analysis.addChild(description); + return analysis; } /** @@ -124,29 +116,14 @@ public class ReportMarshaller { * @param moduleScanner our scanner, which stores the annotated field information * @return a pair of a string and the list of Chunk objects */ - private Pair addParameters(Object toMarshall, AnalysisModuleScanner moduleScanner) { - List chunks = new ArrayList(); + private Collection getParameterNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) { + Collection nodes = new ArrayList(); for (Field f : moduleScanner.getParameters().keySet()) { - ParameterChunk chunk = new ParameterChunk(f, moduleScanner.getParameters(), toMarshall); - if (chunk.isValid()) chunks.add(chunk); + Node node = new Node(moduleScanner.getParameters().get(f).name().equals("") ? f.getName() : moduleScanner.getParameters().get(f).name()); + addChildNodeFromField(toMarshall, f, node); + nodes.add(node); } - return new Pair("parameters",chunks); - } - - /** - * output the Table objects we find - * - * @param toMarshall the object to output - * @param moduleScanner our scanner, which stores the annotated field information - * @return a pair of a string and the list of Chunk objects - */ - private Pair addTables(Object toMarshall, AnalysisModuleScanner moduleScanner) { - List chunks = new ArrayList(); - for (Field f : moduleScanner.getTables().keySet()) { - TableChunk chunk = new TableChunk(f, moduleScanner.getTables(), toMarshall); - if (chunk.isValid()) chunks.add(chunk); - } - return new Pair("tables",chunks); + return nodes; } /** @@ -156,18 +133,18 @@ public class ReportMarshaller { * @param moduleScanner our scanner, which stores the annotated field information * @return a pair of a string and the list of Chunk objects */ - private Pair addDataPoints(Object toMarshall, AnalysisModuleScanner moduleScanner) { - List chunks = new ArrayList(); + private Collection getDataPointNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) { + Collection nodes = new ArrayList(); for (Field f : moduleScanner.getData().keySet()) { - DataPointChunk chunk = new DataPointChunk(f, moduleScanner.getData(), toMarshall); - if (chunk.isValid()) chunks.add(chunk); + Node node = new Node(moduleScanner.getData().get(f).name().equals("") ? f.getName() : moduleScanner.getData().get(f).name()); + addChildNodeFromField(toMarshall, f, node); + nodes.add(node); } - return new Pair("datapoints",chunks); + return nodes; } /** call the method to finalize the report */ public void close() { - map.put("analyses",this.analysisObjects); Writer out = null; try { out = new OutputStreamWriter(new FileOutputStream(this.writeLocation)); @@ -175,6 +152,9 @@ public class ReportMarshaller { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } try { + // add the data to a map + Map map = new HashMap(); + map.put("root",root); temp.process(map, out); out.flush(); } catch (TemplateException e) { @@ -194,12 +174,27 @@ public class ReportMarshaller { cfg.setObjectWrapper(new DefaultObjectWrapper()); Template temp = null; try { - temp = cfg.getTemplate("myTestTemp.ftl"); + temp = cfg.getTemplate("machineReadable.ftl"); } catch (IOException e) { e.printStackTrace(); } return temp; } + + /** + * helper method for adding a Node to the specified node, given the field + * @param toMarshall the object which contains the specified field + * @param f the field + * @param node the node to add a child node to + */ + private static void addChildNodeFromField(Object toMarshall, Field f, Node node) { + f.setAccessible(true); + try { + node.addAllChildren(ComplexDataUtils.resolveObjects(f.get(toMarshall))); + } catch (IllegalAccessException e) { + throw new StingException("Unable to access field " + f); + } + } } diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/AnalysisChunk.java b/java/src/org/broadinstitute/sting/playground/utils/report/chunks/AnalysisChunk.java deleted file mode 100644 index c51011e46..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/AnalysisChunk.java +++ /dev/null @@ -1,85 +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.playground.utils.report.chunks; - -import org.broadinstitute.sting.playground.utils.report.AnalysisModuleScanner; -import org.broadinstitute.sting.playground.utils.report.tags.Analysis; - - -/** - * @author aaron - *

- * Class AnalysisChunk - *

- * The basic data we've decorated an analysis with - */ -public class AnalysisChunk implements Chunk { - public String name; - public String description; - public String version; - public String className; - /** - * extract the analysis data from an analysis annotation using the module scanner. - * @param moduleScanner the module scanner - */ - public AnalysisChunk(AnalysisModuleScanner moduleScanner) { - Analysis a = moduleScanner.getAnalysis(); - name = (a.name().equals("") ? moduleScanner.getModuleClass().getSimpleName() : a.name()); - description = a.description(); - version = a.version().equals("") ? "unknown" : a.version(); - className = moduleScanner.getModuleClass().getName(); - - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public String getVersion() { - return version; - } - - public String getClassName() { - return className; - } - - /** - * is the chunk we've created valid? Invalid chunk would contain null data, or various other - * factors that eliminate a chunk from being outputted. - * - * @return true if it's valid, false if not. - */ - @Override - public boolean isValid() { - if (name == null || name.equals("")) return false; - if (description == null || description.equals("")) return false; - if (version == null) return false; - if (className == null || className.equals("")) return false; - return true; - } -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/Chunk.java b/java/src/org/broadinstitute/sting/playground/utils/report/chunks/Chunk.java deleted file mode 100644 index 1bc73070c..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/Chunk.java +++ /dev/null @@ -1,41 +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.playground.utils.report.chunks; - -/** - * @author aaron - *

- * Interface Chunk - *

- * the basics of what a report data chunk needs to have - */ -public interface Chunk { - /** - * is the chunk we've created valid? Invalid chunk would contain null data, or various other - * factors that eliminate a chunk from being outputted. - * - * @return true if it's valid, false if not. - */ - public boolean isValid(); -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/DataPointChunk.java b/java/src/org/broadinstitute/sting/playground/utils/report/chunks/DataPointChunk.java deleted file mode 100644 index 013493936..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/DataPointChunk.java +++ /dev/null @@ -1,88 +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.playground.utils.report.chunks; - -import org.broadinstitute.sting.playground.utils.report.tags.DataPoint; -import org.broadinstitute.sting.utils.StingException; - -import java.lang.reflect.Field; -import java.util.Map; - - -/** - * @author aaron - *

- * Class DataPointChunk - *

- * a data point chunk - */ -public class DataPointChunk implements Chunk { - public String name; - public String description; - public String value; - - /** - * create a DataPointChunk from extracted information - * - * @param dpf the datapoint field - * @param mappings the mapping of datapoints to fields in the analysis object - * @param toMarshall the object we're marshaling from - */ - public DataPointChunk(Field dpf, Map mappings, Object toMarshall) { - try { - // make sure we can access the field - dpf.setAccessible(true); - name = mappings.get(dpf).name().equals("") ? dpf.getName() : mappings.get(dpf).name(); - description = mappings.get(dpf).description(); - value = dpf.get(toMarshall).toString(); - } catch (IllegalAccessException e) { - throw new StingException("Unable to access variable " + mappings.get(mappings.get(dpf)), e); - } - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public String getValue() { - return value; - } - - /** - * is the chunk we've created valid? Invalid chunk would contain null data, or various other - * factors that eliminate a chunk from being outputted. - * - * @return true if it's valid, false if not. - */ - @Override - public boolean isValid() { - if (name == null || name.equals("")) return false; - if (description == null || description.equals("")) return false; - return value != null; - } -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/ParameterChunk.java b/java/src/org/broadinstitute/sting/playground/utils/report/chunks/ParameterChunk.java deleted file mode 100644 index 679ddb6e1..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/ParameterChunk.java +++ /dev/null @@ -1,89 +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.playground.utils.report.chunks; - -import org.broadinstitute.sting.playground.utils.report.tags.Param; -import org.broadinstitute.sting.utils.StingException; - -import java.lang.reflect.Field; -import java.util.Map; - - -/** - * @author aaron - *

- * Class ParameterChunk - *

- * The basics of a parameter - */ -public class ParameterChunk implements Chunk { - public String name; - public String description; - public String value; - - /** - * create a ParameterChunk from extracted information - * - * @param pf the parameter annotated field - * @param mappings the mapping of params to fields in the analysis object - * @param toMarshall the object we're marshaling from - */ - public ParameterChunk(Field pf, Map mappings, Object toMarshall) { - try { - // make sure we can access the field - pf.setAccessible(true); - name = mappings.get(pf).name().equals("") ? pf.getName() : mappings.get(pf).name(); - description = mappings.get(pf).description(); - value = pf.get(toMarshall).toString(); - } catch (IllegalAccessException e) { - throw new StingException("Unable to access variable " + pf, e); - } - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public String getValue() { - return value; - } - - /** - * is the chunk we've created valid? Invalid chunk would contain null data, or various other - * factors that eliminate a chunk from being outputted. - * - * @return true if it's valid, false if not. - */ - @Override - public boolean isValid() { - if (name == null || name.equals("")) return false; - if (description == null || description.equals("")) return false; - if (value == null) return false; - return true; - } -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/TableChunk.java b/java/src/org/broadinstitute/sting/playground/utils/report/chunks/TableChunk.java deleted file mode 100644 index 381f8e201..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/chunks/TableChunk.java +++ /dev/null @@ -1,109 +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.playground.utils.report.chunks; - -import org.broadinstitute.sting.playground.utils.report.TableFormatter; -import org.broadinstitute.sting.playground.utils.report.tags.Table; -import org.broadinstitute.sting.utils.StingException; - -import java.lang.reflect.Field; -import java.util.List; -import java.util.Map; - - -/** - * @author aaron - *

- * Class TableChunk - *

- * all the information we gleam from a Table annotation, including the table entries - */ -public class TableChunk implements Chunk { - public final String name; - public final String header; - public final String description; - public final int columns; - public final TableFormatter table; - - /** - * create a TableChunk from extracted information - * - * @param tbf the Table annotated field - * @param mappings the mapping of datapoints to fields in the analysis object - * @param toMarshall the object we're marshaling from - */ - public TableChunk(Field tbf, Map mappings, Object toMarshall) { - try { - // make sure we can access the field - tbf.setAccessible(true); - name = mappings.get(tbf).name().equals("") ? tbf.getName() : mappings.get(tbf).name(); - description = mappings.get(tbf).description(); - header = mappings.get(tbf).header(); - columns = mappings.get(tbf).columns(); - table = new TableFormatter(tbf.get(toMarshall)); - } catch (IllegalAccessException e) { - throw new StingException("Unable to access variable " + tbf, e); - } - } - - public String getName() { - return name; - } - - public String getHeader() { - return header; - } - - public String getDescription() { - return description; - } - - public int getColumns() { - return columns; - } - - public TableFormatter getTable() { - return table; - } - - public List> getRows() { - return table.toRows(); - } - - /** - * is the chunk we've created valid? Invalid chunk would contain null data, or various other - * factors that eliminate a chunk from being outputted. - * - * @return true if it's valid, false if not. - */ - @Override - public boolean isValid() { - if (this.name == null || this.name.equals("")) return false; - if (this.header == null || this.header.equals("")) return false; - if (this.description == null) return false; - if (columns < 1) return false; - if (table == null || table.tableEntries == null) return false; - return true; - } -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/tags/Table.java b/java/src/org/broadinstitute/sting/playground/utils/report/tags/Table.java deleted file mode 100644 index b2d1bf3de..000000000 --- a/java/src/org/broadinstitute/sting/playground/utils/report/tags/Table.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.broadinstitute.sting.playground.utils.report.tags; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** - * @author aaron - *

- * Annotation Table - *

- * tells the report system to make a table out of the annotated field. The field - * can be of type List<>, Map<>, Vector<>, Collection<> or primative array. - */ -@Retention(RetentionPolicy.RUNTIME) -public @interface Table { - String name(); // the name - String header() default ""; // any text representing the table header - String description(); // a description of the table - int columns() default -1; // the number of columns to divide the data into -} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/utils/ComplexDataUtils.java b/java/src/org/broadinstitute/sting/playground/utils/report/utils/ComplexDataUtils.java new file mode 100644 index 000000000..330372c5d --- /dev/null +++ b/java/src/org/broadinstitute/sting/playground/utils/report/utils/ComplexDataUtils.java @@ -0,0 +1,81 @@ +package org.broadinstitute.sting.playground.utils.report.utils; + +import java.util.*; + + +/** + * + * @author aaron + * + * Class ComplexDataUtils + * + * This class contains methods and techniques for breaking down complex data in the output system + */ +public class ComplexDataUtils { + + /** + * convert any string -> object pairing into a string keyed tree + * @param obj the object + * @return a mapping of the name to the associated value tree. All non-leaf nodes will be Strings + */ + public static Collection resolveObjects(Object obj) { // TODO: fix this, we need a way to get the name of the list from the data point + Collection nodes = new ArrayList(); + + // the simplest case + if (obj == null) nodes.add(new Node("")); // throw new IllegalStateException("object is null"); + else if (obj instanceof TableType) + nodes.add(tableToNode((TableType)obj, ((TableType)obj).getName())); + else if (obj instanceof Map) { + for (Object key : ((Map)obj).keySet()) { + Node keyNode = new Node(key.toString()); + nodes.add(keyNode); + keyNode.addAllChildren(resolveObjects(((Map)obj).get(key))); + } + } else if (obj instanceof Collection) + nodes.addAll(listToNode((Collection)obj, "collection")); + else if (obj.getClass().isArray()) + nodes.addAll(listToNode(Arrays.asList(obj),"array")); + else + nodes.add(new Node(obj.toString())); + return nodes; + } + + + /** + * given a TableType object, make it into a tree using maps. + * @param table the table type to convert into a map + * @return + */ + private static Node tableToNode(TableType table, String name) { + Node root = new Node(name); + Object[] rows = table.getRowKeys(); + Object[] cols = table.getColumnKeys(); + for (int x = 0; x < table.getRowKeys().length; x++) { + Node row = new Node(rows[x].toString()); + root.addChild(row); + for (int y = 0; y < table.getRowKeys().length; y++) { + Node col = new Node(cols[y].toString()); + row.addChild(col); + col.addChild(new Node(table.getCell(x,y))); + } + } + return root; + } + + /** + * given a Collection object, make it into a tree using maps. + * @param coll the collection to iterate, and turn into a list + * @return a mapping of String to Object + */ + private static Collection listToNode(Collection coll, String name) { + Collection nodes = new ArrayList(); + Iterator iter = coll.iterator(); + for (int x = 0; x < coll.size(); x++) { + Node value = new Node(String.valueOf(x)); + value.addChild(new Node(iter.next().toString())); + nodes.add(value); + } + return nodes; + } + +} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/utils/Node.java b/java/src/org/broadinstitute/sting/playground/utils/report/utils/Node.java new file mode 100644 index 000000000..6eb4f2491 --- /dev/null +++ b/java/src/org/broadinstitute/sting/playground/utils/report/utils/Node.java @@ -0,0 +1,49 @@ +package org.broadinstitute.sting.playground.utils.report.utils; + +import java.util.Collection; +import java.util.LinkedHashSet; + +/** +* a node, extracted using the new report output system. +*/ +public class Node { + public String value; + public String description; // if one is available + public Collection children; + + public Node(String value) { + this.value = value; + } + + public void addChild(Node child) { + if (children == null) children = new LinkedHashSet(); + children.add(child); + } + + public void addAllChildren(Collection children) { + if (this.children == null) this.children = new LinkedHashSet(); + this.children.addAll(children); + } + + public Boolean getComplex() { return (children != null && children.size() > 0); } + + /** + * a convenience method for adding a new sub-node with the specified value + * @param value the value of the sub-node + */ + public void createSubNode(String value) { + addChild(new Node(value)); + } + + public String getValue() { + return value; + } + + public String getDescription() { + return description; + } + + public Collection getChildren() { + return children; + } +} diff --git a/java/src/org/broadinstitute/sting/playground/utils/report/utils/TableType.java b/java/src/org/broadinstitute/sting/playground/utils/report/utils/TableType.java new file mode 100644 index 000000000..1f9a5a5e9 --- /dev/null +++ b/java/src/org/broadinstitute/sting/playground/utils/report/utils/TableType.java @@ -0,0 +1,17 @@ +package org.broadinstitute.sting.playground.utils.report.utils; + + +/** + * + * @author aaron + * + * Class TableType + * + * an interface for turning arbritary objects into tables + */ +public interface TableType { + public Object[] getRowKeys(); + public Object[] getColumnKeys(); + public String getCell(int x, int y); + public String getName(); +} diff --git a/java/test/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScannerTest.java b/java/test/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScannerTest.java index 23a69b826..08b344384 100644 --- a/java/test/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScannerTest.java +++ b/java/test/org/broadinstitute/sting/playground/utils/report/AnalysisModuleScannerTest.java @@ -4,13 +4,9 @@ import org.broadinstitute.sting.BaseTest; import org.broadinstitute.sting.playground.utils.report.tags.Analysis; import org.broadinstitute.sting.playground.utils.report.tags.DataPoint; import org.broadinstitute.sting.playground.utils.report.tags.Param; -import org.broadinstitute.sting.playground.utils.report.tags.Table; import org.junit.Assert; import org.junit.Test; -import java.util.ArrayList; -import java.util.List; - /** * @author aaron @@ -29,10 +25,6 @@ public class AnalysisModuleScannerTest extends BaseTest { Assert.assertEquals(3, scanner.getParameters().size()); Assert.assertTrue("basic description".equals(scanner.getParameters().values().iterator().next().description())); - // check that we've found a table, and check its description - Assert.assertEquals(1, scanner.getTables().size()); - Assert.assertTrue("Generate a table from this data".equals(scanner.getTables().values().iterator().next().description())); - // check that the analysis name and description were set Assert.assertTrue("testAnalysis".equals(scanner.getAnalysis().name())); Assert.assertTrue("The is just a simple description".equals(scanner.getAnalysis().description())); @@ -64,17 +56,7 @@ class FakeAnalysis { @DataPoint(description = "basic description") public String text6 = "GRRR"; - @Table(name="FakeTable", description = "Generate a table from this data",columns=3) - public List values = new ArrayList(); - - public FakeAnalysis() { - values.add(1); - values.add(2); - values.add(3); - values.add(4); - values.add(5); - values.add(6); - + public FakeAnalysis() { } }