From 7be8c35eb231e77e1312628bbe8890aacc593c42 Mon Sep 17 00:00:00 2001 From: kshakir Date: Wed, 7 Jul 2010 03:15:10 +0000 Subject: [PATCH] Workaround for scala trait erasing parameterized types: - Requiring explicit @ClassType on parameterized fields in traits. - Scatter / Gather functions are now abstract classes since @ClassType can't be used on parameterized fields with type parameters. git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3726 348d0f76-0448-11de-a6fe-93d51630548a --- .../sting/commandline/ClassType.java | 39 +++++++++++++++++++ .../unifiedgenotyper_example.properties | 1 + .../queue/function/DispatchFunction.scala | 3 +- .../queue/function/gatk/GatkFunction.scala | 3 +- .../scattergather/GatherFunction.scala | 6 ++- .../scattergather/ScatterFunction.scala | 8 +++- .../sting/queue/util/ReflectionUtils.scala | 5 ++- 7 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 java/src/org/broadinstitute/sting/commandline/ClassType.java diff --git a/java/src/org/broadinstitute/sting/commandline/ClassType.java b/java/src/org/broadinstitute/sting/commandline/ClassType.java new file mode 100644 index 000000000..1e3f63987 --- /dev/null +++ b/java/src/org/broadinstitute/sting/commandline/ClassType.java @@ -0,0 +1,39 @@ +/* + * 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.commandline; + +import java.lang.annotation.*; + +/** + * Annotates generic fields where the parameterized type is not specified or erased. + * Primarily used for Queue traits. Defined in java since scala does not support RetentionPolicy.RUNTIME. + */ +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +public @interface ClassType { + Class value(); +} diff --git a/scala/qscript/unifiedgenotyper_example.properties b/scala/qscript/unifiedgenotyper_example.properties index 6730f6b22..bdf99d9fd 100644 --- a/scala/qscript/unifiedgenotyper_example.properties +++ b/scala/qscript/unifiedgenotyper_example.properties @@ -3,3 +3,4 @@ referenceFile = /path/to/reference.fasta dbsnp = /path/to/dbsnp intervals = /path/to/my.interval_list jobNamePrefix = Q +memoryLimit = 2 diff --git a/scala/src/org/broadinstitute/sting/queue/function/DispatchFunction.scala b/scala/src/org/broadinstitute/sting/queue/function/DispatchFunction.scala index cea5e862e..2c3bef739 100644 --- a/scala/src/org/broadinstitute/sting/queue/function/DispatchFunction.scala +++ b/scala/src/org/broadinstitute/sting/queue/function/DispatchFunction.scala @@ -2,14 +2,15 @@ package org.broadinstitute.sting.queue.function import java.io.File import java.lang.management.ManagementFactory -import org.broadinstitute.sting.commandline.{Output, Input} import org.broadinstitute.sting.queue.function.scattergather.{Gather, SimpleTextGatherFunction} import org.broadinstitute.sting.queue.util.IOUtils +import org.broadinstitute.sting.commandline.{ClassType, Output, Input} trait DispatchFunction extends InputOutputFunction { def commandLine: String @Input(doc="Upper memory limit", required=false) + @ClassType(classOf[Int]) var memoryLimit: Option[Int] = None /** diff --git a/scala/src/org/broadinstitute/sting/queue/function/gatk/GatkFunction.scala b/scala/src/org/broadinstitute/sting/queue/function/gatk/GatkFunction.scala index e985f39d2..c68a5c3a3 100644 --- a/scala/src/org/broadinstitute/sting/queue/function/gatk/GatkFunction.scala +++ b/scala/src/org/broadinstitute/sting/queue/function/gatk/GatkFunction.scala @@ -3,7 +3,7 @@ package org.broadinstitute.sting.queue.function.gatk import java.io.File import org.broadinstitute.sting.queue.function.IntervalFunction import org.broadinstitute.sting.queue.function.scattergather.{Scatter, ScatterGatherableFunction, IntervalScatterFunction} -import org.broadinstitute.sting.commandline.Input +import org.broadinstitute.sting.commandline.{ClassType, Input} trait GatkFunction extends ScatterGatherableFunction with IntervalFunction { @Input(doc="Temporary directory to write any files", required=false) @@ -16,6 +16,7 @@ trait GatkFunction extends ScatterGatherableFunction with IntervalFunction { var referenceFile: File = _ @Input(doc="Bam files", required=false) + @ClassType(classOf[File]) var bamFiles: List[File] = Nil @Input(doc="Intervals", required=false) diff --git a/scala/src/org/broadinstitute/sting/queue/function/scattergather/GatherFunction.scala b/scala/src/org/broadinstitute/sting/queue/function/scattergather/GatherFunction.scala index 72941b18f..3bced51ee 100644 --- a/scala/src/org/broadinstitute/sting/queue/function/scattergather/GatherFunction.scala +++ b/scala/src/org/broadinstitute/sting/queue/function/scattergather/GatherFunction.scala @@ -3,7 +3,11 @@ package org.broadinstitute.sting.queue.function.scattergather import org.broadinstitute.sting.queue.function.{CommandLineFunction} import org.broadinstitute.sting.commandline.{Input, Output} -trait GatherFunction extends CommandLineFunction { +/** + * Base class for Gather command line functions. + * NOTE: Using an abstract class instead of a trait due to scala parameterized type erasure on traits. + */ +abstract class GatherFunction extends CommandLineFunction { type GatherType @Input(doc="Parts to gather back into the original output") diff --git a/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterFunction.scala b/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterFunction.scala index c17beb9c4..05320ccb8 100644 --- a/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterFunction.scala +++ b/scala/src/org/broadinstitute/sting/queue/function/scattergather/ScatterFunction.scala @@ -1,10 +1,14 @@ package org.broadinstitute.sting.queue.function.scattergather import org.broadinstitute.sting.queue.function.CommandLineFunction -import org.broadinstitute.sting.commandline.{Input, Output} import java.io.File +import org.broadinstitute.sting.commandline.{Input, Output} -trait ScatterFunction extends CommandLineFunction { +/** + * Base class for Scatter command line functions. + * NOTE: Using an abstract class instead of a trait due to scala parameterized type erasure on traits. + */ +abstract class ScatterFunction extends CommandLineFunction { type ScatterType @Input(doc="Original input to scatter") diff --git a/scala/src/org/broadinstitute/sting/queue/util/ReflectionUtils.scala b/scala/src/org/broadinstitute/sting/queue/util/ReflectionUtils.scala index c865f35c5..566e3cc02 100644 --- a/scala/src/org/broadinstitute/sting/queue/util/ReflectionUtils.scala +++ b/scala/src/org/broadinstitute/sting/queue/util/ReflectionUtils.scala @@ -4,6 +4,7 @@ import org.broadinstitute.sting.queue.QException import java.lang.annotation.Annotation import scala.concurrent.JavaConversions._ import java.lang.reflect.{ParameterizedType, Field} +import org.broadinstitute.sting.commandline.ClassType object ReflectionUtils { def hasAnnotation(field: Field, annotation: Class[_ <: Annotation]) = field.getAnnotation(annotation) != null @@ -73,12 +74,14 @@ object ReflectionUtils { } } - private def getGenericTypes(field: Field) = { + private def getGenericTypes(field: Field): Option[Array[Class[_]]] = { // TODO: Refactor: based on java code in org.broadinstitute.sting.commandline.ArgumentTypeDescriptor // If this is a parameterized collection, find the contained type. If blow up if only one type exists. if (field.getGenericType.isInstanceOf[ParameterizedType]) { val parameterizedType = field.getGenericType.asInstanceOf[ParameterizedType] Some(parameterizedType.getActualTypeArguments.map(_.asInstanceOf[Class[_]])) + } else if (hasAnnotation(field, classOf[ClassType])) { + Some(Array(getAnnotation(field, classOf[ClassType]).value)) } else None }