From 7cab709a88c86145d3be601c5ec2ea6476aa02a3 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Wed, 13 Mar 2013 14:57:28 -0400 Subject: [PATCH] Fixed the logic of the @Output annotation and its interaction with 'required'. ALL GATK DEVELOPERS PLEASE READ NOTES BELOW: I have updated the @Output annotation to behave differently and to include a 'defaultToStdout' tag. * The 'defaultToStdout' tags lets walkers specify whether to default to stdout if -o is not provided. * The logic for @Output is now: * if required==true then -o MUST be provided or a User Error is generated. * if required==false and defaultToStdout==true then the output is assigned to stdout if no -o is provided. * this is the default behavior (i.e. @Output with no modifiers). * if required==false and defaultToStdout==false then the output object is null. * use this combination for truly optional outputs (e.g. the -badSites option in AssessNA12878). * I have updated walkers so that previous behavior has been maintained (as best I could). * In general, all @Outputs with default long/short names have required=false. * Walkers with nWayOut options must have required==false and defaultToStdout==false (I added checks for this) * I added unit tests for @Output changes with David's help (thanks!). * #resolve GSA-837 --- .../bqsr/RecalibrationArgumentCollection.java | 4 +- .../bqsr/RecalibrationPerformance.java | 2 +- .../compression/reducereads/ReduceReads.java | 11 +- .../targets/BaseCoverageDistribution.java | 2 +- .../diagnostics/targets/DiagnoseTargets.java | 2 +- .../targets/FindCoveredIntervals.java | 2 +- .../walkers/genotyper/UnifiedGenotyper.java | 2 +- .../haplotypecaller/HaplotypeCaller.java | 8 +- .../haplotypecaller/HaplotypeResolver.java | 2 +- .../gatk/walkers/indels/IndelRealigner.java | 8 +- .../walkers/phasing/ReadBackedPhasing.java | 2 +- .../ValidationSiteSelector.java | 2 +- .../ApplyRecalibration.java | 2 +- .../VariantRecalibrator.java | 2 +- .../variantutils/RegenotypeVariants.java | 2 +- .../sting/commandline/ArgumentSource.java | 8 + .../sting/commandline/Output.java | 7 + .../OutputStreamArgumentTypeDescriptor.java | 6 +- .../SAMFileWriterArgumentTypeDescriptor.java | 6 +- .../VCFWriterArgumentTypeDescriptor.java | 8 +- .../gatk/walkers/ActiveRegionWalker.java | 4 +- .../walkers/annotator/VariantAnnotator.java | 2 +- .../walkers/beagle/BeagleOutputToVCF.java | 2 +- .../walkers/beagle/ProduceBeagleInput.java | 4 +- .../beagle/VariantsToBeagleUnphased.java | 2 +- .../diagnostics/CoveredByNSamplesSites.java | 2 +- .../gatk/walkers/diffengine/DiffObjects.java | 2 +- .../walkers/filters/VariantFiltration.java | 2 +- .../gatk/walkers/qc/DocumentationTest.java | 2 +- .../gatk/walkers/readutils/ClipReads.java | 4 +- .../gatk/walkers/readutils/PrintReads.java | 2 +- .../walkers/variantutils/CombineVariants.java | 2 +- .../variantutils/FilterLiftedVariants.java | 2 +- .../variantutils/LeftAlignVariants.java | 2 +- .../variantutils/LiftoverVariants.java | 2 +- .../walkers/variantutils/SelectHeaders.java | 2 +- .../walkers/variantutils/SelectVariants.java | 2 +- .../VariantValidationAssessor.java | 2 +- .../VariantsToAllelicPrimitives.java | 2 +- .../walkers/variantutils/VariantsToTable.java | 2 +- .../walkers/variantutils/VariantsToVCF.java | 2 +- .../ArgumentTypeDescriptorUnitTest.java | 183 ++++++++++++++++++ 42 files changed, 262 insertions(+), 57 deletions(-) create mode 100644 public/java/test/org/broadinstitute/sting/commandline/ArgumentTypeDescriptorUnitTest.java diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java index ee2edee5a..447569643 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationArgumentCollection.java @@ -91,7 +91,7 @@ public class RecalibrationArgumentCollection { * If not provided, then no plots will be generated (useful for queue scatter/gathering). * However, we *highly* recommend that users generate these plots whenever possible for QC checking. */ - @Output(fullName = "plot_pdf_file", shortName = "plots", doc = "The output recalibration pdf file to create", required = false) + @Output(fullName = "plot_pdf_file", shortName = "plots", doc = "The output recalibration pdf file to create", required = false, defaultToStdout = false) public File RECAL_PDF_FILE = null; /** @@ -220,7 +220,7 @@ public class RecalibrationArgumentCollection { public String FORCE_PLATFORM = null; @Hidden - @Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only") + @Output(fullName = "recal_table_update_log", shortName = "recal_table_update_log", required = false, doc = "If provided, log all updates to the recalibration tables to the given file. For debugging/testing purposes only", defaultToStdout = false) public PrintStream RECAL_TABLE_UPDATE_LOG = null; /** diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationPerformance.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationPerformance.java index fb11f6249..d0af08d90 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationPerformance.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/RecalibrationPerformance.java @@ -66,7 +66,7 @@ import java.io.*; @PartitionBy(PartitionType.READ) public class RecalibrationPerformance extends RodWalker implements NanoSchedulable { - @Output(doc="Write output to this file", required = true) + @Output(doc="Write output to this file") public PrintStream out; @Input(fullName="recal", shortName="recal", required=false, doc="The input covariates table file") diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java index bc582fd49..da9bc1b37 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/compression/reducereads/ReduceReads.java @@ -69,6 +69,7 @@ import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.Utils; import org.broadinstitute.sting.utils.clipping.ReadClipper; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.sting.utils.exceptions.UserException; import org.broadinstitute.sting.utils.help.DocumentedGATKFeature; import org.broadinstitute.sting.utils.help.HelpConstants; import org.broadinstitute.sting.utils.sam.BySampleSAMFileWriter; @@ -112,7 +113,7 @@ import org.broadinstitute.sting.utils.sam.ReadUtils; @Downsample(by=DownsampleType.BY_SAMPLE, toCoverage=40) public class ReduceReads extends ReadWalker, ReduceReadsStash> { - @Output(required=true) + @Output(required = false, defaultToStdout = false) private StingSAMFileWriter out = null; private SAMFileWriter writerToUse = null; @@ -259,6 +260,13 @@ public class ReduceReads extends ReadWalker, Redu @Override public void initialize() { super.initialize(); + + if ( !nwayout && out == null ) + throw new UserException.MissingArgument("out", "the output must be provided and is optional only for certain debugging modes"); + + if ( nwayout && out != null ) + throw new UserException.CommandLineException("--out and --nwayout can not be used simultaneously; please use one or the other"); + GenomeAnalysisEngine toolkit = getToolkit(); readNameHash = new Object2LongOpenHashMap(100000); // prepare the read name hash to keep track of what reads have had their read names compressed intervalList = new ObjectAVLTreeSet(); // get the interval list from the engine. If no interval list was provided, the walker will work in WGS mode @@ -266,7 +274,6 @@ public class ReduceReads extends ReadWalker, Redu if (toolkit.getIntervals() != null) intervalList.addAll(toolkit.getIntervals()); - final boolean preSorted = true; final boolean indexOnTheFly = true; final boolean keep_records = true; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java index 9bd08a020..b70581dd3 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/BaseCoverageDistribution.java @@ -99,7 +99,7 @@ public class BaseCoverageDistribution extends LocusWalker, Ma /** * The output GATK Report table */ - @Output(required = true, doc = "The output GATK Report table") + @Output(doc = "The output GATK Report table") private PrintStream out; /** diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/DiagnoseTargets.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/DiagnoseTargets.java index e4310588e..b302a967c 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/DiagnoseTargets.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/DiagnoseTargets.java @@ -110,7 +110,7 @@ import java.util.*; @PartitionBy(PartitionType.INTERVAL) public class DiagnoseTargets extends LocusWalker { - @Output(doc = "File to which variants should be written", required = true) + @Output(doc = "File to which variants should be written") private VariantContextWriter vcfWriter = null; @Argument(fullName = "minimum_base_quality", shortName = "BQ", doc = "The minimum Base Quality that is considered for calls", required = false) diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java index 6b4d1f7a8..eef581160 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/targets/FindCoveredIntervals.java @@ -92,7 +92,7 @@ import java.io.PrintStream; @PartitionBy(PartitionType.CONTIG) @ActiveRegionTraversalParameters(extension = 0, maxRegion = 50000) public class FindCoveredIntervals extends ActiveRegionWalker { - @Output(required = true) + @Output private PrintStream out; @Argument(fullName = "uncovered", shortName = "u", required = false, doc = "output intervals that fail the coverage threshold instead") diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java index 4347a1a84..54fcad1df 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/genotyper/UnifiedGenotyper.java @@ -180,7 +180,7 @@ public class UnifiedGenotyper extends LocusWalker, Unif * A raw, unfiltered, highly sensitive callset in VCF format. */ //@Gather(className = "org.broadinstitute.sting.queue.extensions.gatk.CatVariantsGatherer") - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter writer = null; @Hidden diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java index 7948b93a9..4bf09ad2d 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeCaller.java @@ -139,10 +139,10 @@ public class HaplotypeCaller extends ActiveRegionWalker implem /** * A raw, unfiltered, highly sensitive callset in VCF format. */ - @Output(doc="File to which variants should be written", required = true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; - @Output(fullName="graphOutput", shortName="graph", doc="File to which debug assembly graph information should be written", required = false) + @Output(fullName="graphOutput", shortName="graph", doc="File to which debug assembly graph information should be written", required = false, defaultToStdout = false) protected PrintStream graphWriter = null; /** @@ -170,14 +170,14 @@ public class HaplotypeCaller extends ActiveRegionWalker implem * in the following screenshot: https://www.dropbox.com/s/xvy7sbxpf13x5bp/haplotypecaller%20bamout%20for%20docs.png * */ - @Output(fullName="bamOutput", shortName="bamout", doc="File to which assembled haplotypes should be written", required = false) + @Output(fullName="bamOutput", shortName="bamout", doc="File to which assembled haplotypes should be written", required = false, defaultToStdout = false) protected StingSAMFileWriter bamWriter = null; private HaplotypeBAMWriter haplotypeBAMWriter; /** * The type of BAM output we want to see. */ - @Output(fullName="bamWriterType", shortName="bamWriterType", doc="How should haplotypes be written to the BAM?", required = false) + @Argument(fullName="bamWriterType", shortName="bamWriterType", doc="How should haplotypes be written to the BAM?", required = false) public HaplotypeBAMWriter.Type bamWriterType = HaplotypeBAMWriter.Type.CALLED_HAPLOTYPES; /** diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeResolver.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeResolver.java index 4de9488e9..facc929cd 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeResolver.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/haplotypecaller/HaplotypeResolver.java @@ -125,7 +125,7 @@ public class HaplotypeResolver extends RodWalker { @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true) public List> variants; - @Output(doc="File to which variants should be written", required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter baseWriter = null; private VariantContextWriter writer; diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java index d3a13df29..7d8243c98 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/indels/IndelRealigner.java @@ -189,7 +189,7 @@ public class IndelRealigner extends ReadWalker { /** * The realigned bam file. */ - @Output(required=false, doc="Output bam") + @Output(required=false, doc="Output bam", defaultToStdout=false) protected StingSAMFileWriter writer = null; protected ConstrainedMateFixingManager manager = null; protected SAMFileWriter writerToUse = null; @@ -295,15 +295,15 @@ public class IndelRealigner extends ReadWalker { protected boolean KEEP_ALL_PG_RECORDS = false; @Hidden - @Output(fullName="indelsFileForDebugging", shortName="indels", required=false, doc="Output file (text) for the indels found; FOR DEBUGGING PURPOSES ONLY") + @Output(fullName="indelsFileForDebugging", shortName="indels", required=false, defaultToStdout=false, doc="Output file (text) for the indels found; FOR DEBUGGING PURPOSES ONLY") protected String OUT_INDELS = null; @Hidden - @Output(fullName="statisticsFileForDebugging", shortName="stats", doc="print out statistics (what does or doesn't get cleaned); FOR DEBUGGING PURPOSES ONLY", required=false) + @Output(fullName="statisticsFileForDebugging", shortName="stats", doc="print out statistics (what does or doesn't get cleaned); FOR DEBUGGING PURPOSES ONLY", required=false, defaultToStdout=false) protected String OUT_STATS = null; @Hidden - @Output(fullName="SNPsFileForDebugging", shortName="snps", doc="print out whether mismatching columns do or don't get cleaned out; FOR DEBUGGING PURPOSES ONLY", required=false) + @Output(fullName="SNPsFileForDebugging", shortName="snps", doc="print out whether mismatching columns do or don't get cleaned out; FOR DEBUGGING PURPOSES ONLY", required=false, defaultToStdout=false) protected String OUT_SNPS = null; // fasta reference reader to supplement the edges of the reference sequence diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java index c1b484542..a297b38cf 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/phasing/ReadBackedPhasing.java @@ -131,7 +131,7 @@ public class ReadBackedPhasing extends RodWalker { /** * The output VCF file */ - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; /** diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/ApplyRecalibration.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/ApplyRecalibration.java index 22425e62e..7de0c7e60 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/ApplyRecalibration.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/ApplyRecalibration.java @@ -128,7 +128,7 @@ public class ApplyRecalibration extends RodWalker implements T ///////////////////////////// // Outputs ///////////////////////////// - @Output( doc="The output filtered and recalibrated VCF file in which each variant is annotated with its VQSLOD value", required=true) + @Output( doc="The output filtered and recalibrated VCF file in which each variant is annotated with its VQSLOD value") private VariantContextWriter vcfWriter = null; ///////////////////////////// diff --git a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java index 99d926ea5..320328ab1 100644 --- a/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java +++ b/protected/java/src/org/broadinstitute/sting/gatk/walkers/variantrecalibration/VariantRecalibrator.java @@ -194,7 +194,7 @@ public class VariantRecalibrator extends RodWalker implements T @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; private UnifiedGenotyperEngine UG_engine = null; diff --git a/public/java/src/org/broadinstitute/sting/commandline/ArgumentSource.java b/public/java/src/org/broadinstitute/sting/commandline/ArgumentSource.java index b9c785879..efacde231 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/ArgumentSource.java +++ b/public/java/src/org/broadinstitute/sting/commandline/ArgumentSource.java @@ -175,6 +175,14 @@ public class ArgumentSource { return field.isAnnotationPresent(Deprecated.class); } + /** + * Returns whether the field should default to stdout if not provided explicitly on the command-line. + * @return True if field should default to stdout. + */ + public boolean defaultsToStdout() { + return field.isAnnotationPresent(Output.class) && (Boolean)CommandLineUtils.getValue(ArgumentTypeDescriptor.getArgumentAnnotation(this),"defaultToStdout"); + } + /** * Returns false if a type-specific default can be employed. * @return True to throw in a type specific default. False otherwise. diff --git a/public/java/src/org/broadinstitute/sting/commandline/Output.java b/public/java/src/org/broadinstitute/sting/commandline/Output.java index 47a47602a..0db870f2e 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/Output.java +++ b/public/java/src/org/broadinstitute/sting/commandline/Output.java @@ -66,6 +66,13 @@ public @interface Output { */ boolean required() default false; + /** + * If this argument is not required, should it default to use stdout if no + * output file is explicitly provided on the command-line? + * @return True if the argument should default to stdout. False otherwise. + */ + boolean defaultToStdout() default true; + /** * Should this command-line argument be exclusive of others. Should be * a comma-separated list of names of arguments of which this should be diff --git a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/OutputStreamArgumentTypeDescriptor.java b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/OutputStreamArgumentTypeDescriptor.java index fbcc32d78..18185f12e 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/OutputStreamArgumentTypeDescriptor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/OutputStreamArgumentTypeDescriptor.java @@ -66,7 +66,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor { @Override public boolean createsTypeDefault(ArgumentSource source) { - return source.isRequired(); + return !source.isRequired() && source.defaultsToStdout(); } @Override @@ -76,7 +76,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor { @Override public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) { - if(!source.isRequired()) + if(source.isRequired() || !source.defaultsToStdout()) throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default."); OutputStreamStub stub = new OutputStreamStub(defaultOutputStream); engine.addOutput(stub); @@ -90,7 +90,7 @@ public class OutputStreamArgumentTypeDescriptor extends ArgumentTypeDescriptor { // This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object; // therefore, the user must have failed to specify a type default - if(fileName == null && !source.isRequired()) + if(fileName == null && source.isRequired()) throw new MissingArgumentValueException(definition); OutputStreamStub stub = new OutputStreamStub(new File(fileName)); diff --git a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java index 34a7f967f..458846db0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/SAMFileWriterArgumentTypeDescriptor.java @@ -89,7 +89,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor @Override public boolean createsTypeDefault(ArgumentSource source) { - return source.isRequired(); + return !source.isRequired() && source.defaultsToStdout(); } @Override @@ -99,7 +99,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor @Override public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) { - if(!source.isRequired()) + if(source.isRequired() || !source.defaultsToStdout()) throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default."); SAMFileWriterStub stub = new SAMFileWriterStub(engine,defaultOutputStream); engine.addOutput(stub); @@ -162,7 +162,7 @@ public class SAMFileWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor DEFAULT_ARGUMENT_FULLNAME, DEFAULT_ARGUMENT_SHORTNAME, ArgumentDefinition.getDoc(annotation), - false, + source.isRequired(), false, source.isMultiValued(), source.isHidden(), diff --git a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/VCFWriterArgumentTypeDescriptor.java b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/VCFWriterArgumentTypeDescriptor.java index 5b03859f5..91013673f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/io/stubs/VCFWriterArgumentTypeDescriptor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/io/stubs/VCFWriterArgumentTypeDescriptor.java @@ -110,7 +110,7 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor { */ @Override public boolean createsTypeDefault(ArgumentSource source) { - return source.isRequired(); + return !source.isRequired() && source.defaultsToStdout(); } @Override @@ -119,8 +119,8 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor { } @Override - public Object createTypeDefault(ParsingEngine parsingEngine,ArgumentSource source, Type type) { - if(!source.isRequired()) + public Object createTypeDefault(ParsingEngine parsingEngine, ArgumentSource source, Type type) { + if(source.isRequired() || !source.defaultsToStdout()) throw new ReviewedStingException("BUG: tried to create type default for argument type descriptor that can't support a type default."); VariantContextWriterStub stub = new VariantContextWriterStub(engine, defaultOutputStream, argumentSources); engine.addOutput(stub); @@ -143,7 +143,7 @@ public class VCFWriterArgumentTypeDescriptor extends ArgumentTypeDescriptor { // This parser has been passed a null filename and the GATK is not responsible for creating a type default for the object; // therefore, the user must have failed to specify a type default - if(writerFile == null && !source.isRequired()) + if(writerFile == null && source.isRequired()) throw new MissingArgumentValueException(defaultArgumentDefinition); // Create a stub for the given object. diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java index e14e50b1a..ebfc52d3f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/ActiveRegionWalker.java @@ -67,7 +67,7 @@ public abstract class ActiveRegionWalker extends Walker extends Walker implements Ann public List> resources = Collections.emptyList(); public List> getResourceRodBindings() { return resources; } - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java index 4b96dbffb..15bd79586 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/BeagleOutputToVCF.java @@ -106,7 +106,7 @@ public class BeagleOutputToVCF extends RodWalker { @Input(fullName="beaglePhased", shortName = "beaglePhased", doc="Beagle-produced .phased file containing phased genotypes", required=true) public RodBinding beaglePhased; - @Output(doc="VCF File to which variants should be written",required=true) + @Output(doc="VCF File to which variants should be written") protected VariantContextWriter vcfWriter = null; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java index 618fda0df..6e5aa250f 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/ProduceBeagleInput.java @@ -89,11 +89,11 @@ public class ProduceBeagleInput extends RodWalker { public RodBinding validation; - @Output(doc="File to which BEAGLE input should be written",required=true) + @Output(doc="File to which BEAGLE input should be written") protected PrintStream beagleWriter = null; @Hidden - @Output(doc="File to which BEAGLE markers should be written", shortName="markers", fullName = "markers", required = false) + @Output(doc="File to which BEAGLE markers should be written", shortName="markers", fullName = "markers", required = false, defaultToStdout = false) protected PrintStream markers = null; int markerCounter = 1; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java index ab0ce79fd..646c57a2b 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/beagle/VariantsToBeagleUnphased.java @@ -62,7 +62,7 @@ public class VariantsToBeagleUnphased extends RodWalker { @Input(fullName="variants", shortName = "V", doc="Input VCF file", required=true) public RodBinding variants; - @Output(doc="File to which BEAGLE unphased genotypes should be written",required=true) + @Output(doc="File to which BEAGLE unphased genotypes should be written") protected PrintStream beagleWriter = null; @Argument(fullName = "bootstrap_fraction", shortName = "bs", doc = "Proportion of records to be used in bootstrap set", required = false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java index 169c2708b..bff2ace63 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diagnostics/CoveredByNSamplesSites.java @@ -75,7 +75,7 @@ import java.util.Collection; @By(DataSource.REFERENCE_ORDERED_DATA) public class CoveredByNSamplesSites extends RodWalker implements TreeReducible { - @Output(fullName = "OutputIntervals", shortName = "out", doc = "Name of file for output intervals", required = true) + @Output(fullName = "OutputIntervals", shortName = "out", doc = "Name of file for output intervals") PrintStream outputStream; @ArgumentCollection diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjects.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjects.java index 6b5189dfd..524f5c250 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjects.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjects.java @@ -146,7 +146,7 @@ public class DiffObjects extends RodWalker { * * See http://www.broadinstitute.org/gatk/guide/article?id=1299 for details. */ - @Output(doc="File to which results should be written",required=true) + @Output(doc="File to which results should be written") protected PrintStream out; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java index c59c61803..8feb9101c 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/filters/VariantFiltration.java @@ -92,7 +92,7 @@ public class VariantFiltration extends RodWalker { @Input(fullName="mask", doc="Input ROD mask", required=false) public RodBinding mask; - @Output(doc="File to which variants should be written", required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter writer = null; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/DocumentationTest.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/DocumentationTest.java index 8902773f7..5db67a7f0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/DocumentationTest.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/qc/DocumentationTest.java @@ -73,7 +73,7 @@ public class DocumentationTest extends RodWalker { @Input(fullName="featureArg", shortName = "featureArg", doc="A RodBinding of feature", required=false) private RodBinding featureArg = null; - @Output(doc="VCFWriter",required=true) + @Output(doc="VCFWriter") protected VariantContextWriter vcfWriter = null; @Advanced diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java index 739da5a98..879022299 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/readutils/ClipReads.java @@ -161,13 +161,13 @@ public class ClipReads extends ReadWalker implements NanoSchedulable { - @Output(doc="Write output to this BAM filename instead of STDOUT", required = true) + @Output(doc="Write output to this BAM filename instead of STDOUT") StingSAMFileWriter out; @Argument(fullName = "readGroup", shortName = "readGroup", doc="Exclude all reads with this read group from the output", required = false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java index 436a973df..45dbc937d 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariants.java @@ -133,7 +133,7 @@ public class CombineVariants extends RodWalker implements Tree @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true) public List> variants; - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; @Argument(shortName="genotypeMergeOptions", doc="Determines how we should merge genotype records for samples shared across the ROD files", required=false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java index f285fb797..e61cda765 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/FilterLiftedVariants.java @@ -56,7 +56,7 @@ public class FilterLiftedVariants extends RodWalker { private static final int MAX_VARIANT_SIZE = 100; - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter writer = null; private long failedLocs = 0, totalLocs = 0; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java index e6d3e6e94..700b34b38 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LeftAlignVariants.java @@ -87,7 +87,7 @@ public class LeftAlignVariants extends RodWalker { @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter baseWriter = null; private VariantContextWriter writer; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java index 0a7ad5b7b..17d50f101 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/LiftoverVariants.java @@ -62,7 +62,7 @@ public class LiftoverVariants extends RodWalker { @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected File file = null; protected VariantContextWriter writer = null; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java index 9bbf728e1..478bba846 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectHeaders.java @@ -110,7 +110,7 @@ public class SelectHeaders extends RodWalker implements TreeRe @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc = "File to which variants should be written", required = true) + @Output(doc = "File to which variants should be written") protected VariantContextWriter vcfWriter; @Argument(fullName = "header_name", shortName = "hn", doc = "Include header. Can be specified multiple times", required = false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java index f72ce3bd6..1c5e9d1ba 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/SelectVariants.java @@ -199,7 +199,7 @@ public class SelectVariants extends RodWalker implements TreeR @Input(fullName="concordance", shortName = "conc", doc="Output variants that were also called in this comparison track", required=false) protected RodBinding concordanceTrack; - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfWriter = null; @Argument(fullName="sample_name", shortName="sn", doc="Include genotypes from this sample. Can be specified multiple times", required=false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java index 0e2a04bf2..d189459c0 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantValidationAssessor.java @@ -91,7 +91,7 @@ public class VariantValidationAssessor extends RodWalker @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter vcfwriter = null; @Argument(fullName="maxHardy", doc="Maximum phred-scaled Hardy-Weinberg violation pvalue to consider an assay valid", required=false) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToAllelicPrimitives.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToAllelicPrimitives.java index 319183f28..e25f158f2 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToAllelicPrimitives.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToAllelicPrimitives.java @@ -84,7 +84,7 @@ public class VariantsToAllelicPrimitives extends RodWalker { @ArgumentCollection protected StandardVariantContextInputArgumentCollection variantCollection = new StandardVariantContextInputArgumentCollection(); - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter baseWriter = null; private VariantContextWriter vcfWriter; diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java index 444eb745c..f1f93f1f5 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToTable.java @@ -111,7 +111,7 @@ public class VariantsToTable extends RodWalker { @Input(fullName="variant", shortName = "V", doc="Input VCF file", required=true) public List> variants; - @Output(doc="File to which results should be written",required=true) + @Output(doc="File to which results should be written") protected PrintStream out; /** diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java index 7c7f52803..96b66a0e3 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/variantutils/VariantsToVCF.java @@ -87,7 +87,7 @@ import java.util.*; @Reference(window=@Window(start=-40,stop=40)) public class VariantsToVCF extends RodWalker { - @Output(doc="File to which variants should be written",required=true) + @Output(doc="File to which variants should be written") protected VariantContextWriter baseWriter = null; private VariantContextWriter vcfwriter; // needed because hapmap/dbsnp indel records move diff --git a/public/java/test/org/broadinstitute/sting/commandline/ArgumentTypeDescriptorUnitTest.java b/public/java/test/org/broadinstitute/sting/commandline/ArgumentTypeDescriptorUnitTest.java new file mode 100644 index 000000000..85ad5d575 --- /dev/null +++ b/public/java/test/org/broadinstitute/sting/commandline/ArgumentTypeDescriptorUnitTest.java @@ -0,0 +1,183 @@ +/* +* Copyright (c) 2012 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 it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.sf.samtools.SAMFileWriter; +import org.broadinstitute.sting.BaseTest; +import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; +import org.broadinstitute.sting.gatk.io.stubs.*; +import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; +import org.broadinstitute.variant.variantcontext.writer.VariantContextWriter; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; + + +public class ArgumentTypeDescriptorUnitTest extends BaseTest { + + //////////////////////////////////////////////////////////////////// + // This section tests the functionality of the @Output annotation // + //////////////////////////////////////////////////////////////////// + + private class ATDTestCommandLineProgram extends CommandLineProgram { + public int execute() { return 0; } + + @Override + public Collection getArgumentTypeDescriptors() { + final GenomeAnalysisEngine engine = new GenomeAnalysisEngine(); + return Arrays.asList( new SAMFileWriterArgumentTypeDescriptor(engine, System.out), + new OutputStreamArgumentTypeDescriptor(engine, System.out), + new VCFWriterArgumentTypeDescriptor(engine, System.out, null)); + } + + protected abstract class ATDTestOutputArgumentSource { + public abstract Object getOut(); + } + + protected class OutputRequiredSamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = true) + public SAMFileWriter out; + public Object getOut() { return out; } + } + + protected class OutputRequiredVcfArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = true) + public VariantContextWriter out; + public Object getOut() { return out; } + } + + protected class OutputRequiredStreamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = true) + public PrintStream out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredNoDefaultSamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false, defaultToStdout = false) + public SAMFileWriter out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredNoDefaultVcfArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false, defaultToStdout = false) + public VariantContextWriter out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredNoDefaultStreamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false, defaultToStdout = false) + public PrintStream out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredSamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false) + public SAMFileWriter out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredVcfArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false) + public VariantContextWriter out; + public Object getOut() { return out; } + } + + protected class OutputNotRequiredStreamArgumentSource extends ATDTestOutputArgumentSource { + @Output(shortName="o", doc="output file", required = false) + public PrintStream out; + public Object getOut() { return out; } + } + } + + @DataProvider(name = "OutputProvider") + public Object[][] OutputProvider() { + + ObjectArrayList tests = new ObjectArrayList(); + + final ATDTestCommandLineProgram clp = new ATDTestCommandLineProgram(); + + for ( final Object obj : Arrays.asList(clp.new OutputRequiredSamArgumentSource(), clp.new OutputRequiredVcfArgumentSource(), clp.new OutputRequiredStreamArgumentSource()) ) { + for ( final boolean provided : Arrays.asList(true, false) ) { + tests.add(new Object[]{obj, true, true, provided}); + } + } + + for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredSamArgumentSource(), clp.new OutputNotRequiredVcfArgumentSource(), clp.new OutputNotRequiredStreamArgumentSource()) ) { + for ( final boolean provided : Arrays.asList(true, false) ) { + tests.add(new Object[]{obj, false, true, provided}); + } + } + + for ( final Object obj : Arrays.asList(clp.new OutputNotRequiredNoDefaultSamArgumentSource(), clp.new OutputNotRequiredNoDefaultVcfArgumentSource(), clp.new OutputNotRequiredNoDefaultStreamArgumentSource()) ) { + for ( final boolean provided : Arrays.asList(true, false) ) { + tests.add(new Object[]{obj, false, false, provided}); + } + } + + return tests.toArray(new Object[][]{}); + } + + @Test(dataProvider = "OutputProvider") + public void testOutput(final ATDTestCommandLineProgram.ATDTestOutputArgumentSource argumentSource, final boolean required, final boolean hasDefault, final boolean provided) { + + final ParsingEngine parser = new ParsingEngine(new ATDTestCommandLineProgram()); + parser.addArgumentSource(argumentSource.getClass()); + parser.parse(provided ? new String[] {"out", "foo"} : new String[] {}); + + try { + parser.loadArgumentsIntoObject(argumentSource); + + if ( !provided && (required || !hasDefault) ) + Assert.assertEquals(argumentSource.getOut(), null); + else if ( !provided ) + Assert.assertNotEquals(argumentSource.getOut(), null); + else if ( argumentSource.getOut() == null || !(argumentSource.getOut() instanceof SAMFileWriterStub) ) // can't test this one case + Assert.assertEquals(!provided, outputIsStdout(argumentSource.getOut())); + + } catch (Exception e) { + throw new ReviewedStingException(e.getMessage()); + } + } + + private static boolean outputIsStdout(final Object out) { + if ( out == null ) { + return false; + } else if ( out instanceof SAMFileWriterStub ) { + return ((SAMFileWriterStub)out).getOutputStream() != System.out; + } else if ( out instanceof VariantContextWriterStub ) { + return ((VariantContextWriterStub)out).getOutputStream() == System.out; + } else if ( out instanceof OutputStreamStub ) { + return ((OutputStreamStub)out).getOutputStream() == System.out; + } + return false; + } + +} \ No newline at end of file