Fix for a reflection issue with generic types.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3565 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
7a91dbd490
commit
c44fd05aa1
|
|
@ -27,8 +27,7 @@ package org.broadinstitute.sting.queue.util;
|
|||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Specifies the type of an input our output field.
|
||||
* Retains it during runtime to work around type erasure.
|
||||
* Specifies the type of an input or output field.
|
||||
* Written in java because scala doesn't support RetentionPolicy.RUNTIME
|
||||
*/
|
||||
@Documented
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package org.broadinstitute.sting.queue.function
|
||||
|
||||
import org.broadinstitute.sting.queue.util.{Input, Optional, ClassType}
|
||||
import org.broadinstitute.sting.queue.util.{Input, Optional}
|
||||
|
||||
trait MemoryLimitedFunction {
|
||||
@Input
|
||||
@Optional
|
||||
@ClassType(classOf[Int])
|
||||
var memoryLimit: Option[Int] = None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package org.broadinstitute.sting.queue.function.gatk
|
||||
|
||||
import java.io.File
|
||||
import org.broadinstitute.sting.queue.util.{ClassType, Input, Optional}
|
||||
import org.broadinstitute.sting.queue.util.{Input, Optional}
|
||||
import org.broadinstitute.sting.queue.function.{MemoryLimitedFunction, IntervalFunction, CommandLineFunction}
|
||||
|
||||
trait GatkFunction extends CommandLineFunction with MemoryLimitedFunction with IntervalFunction {
|
||||
|
|
@ -17,7 +17,6 @@ trait GatkFunction extends CommandLineFunction with MemoryLimitedFunction with I
|
|||
|
||||
@Input
|
||||
@Optional
|
||||
@ClassType(classOf[File])
|
||||
var bamFiles: List[File] = Nil
|
||||
|
||||
@Input
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package org.broadinstitute.sting.queue.util
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import org.broadinstitute.sting.queue.QException
|
||||
import java.lang.annotation.Annotation
|
||||
import scala.concurrent.JavaConversions
|
||||
import scala.concurrent.JavaConversions._
|
||||
import scala.collection.immutable.ListMap
|
||||
import java.lang.reflect.{ParameterizedType, Field}
|
||||
|
||||
object ReflectionUtils {
|
||||
def getField(obj: AnyRef, name: String) = getAllFields(obj.getClass).find(_.getName == name)
|
||||
|
|
@ -41,10 +41,7 @@ object ReflectionUtils {
|
|||
|
||||
if (classOf[Seq[_]].isAssignableFrom(field.getType)) {
|
||||
|
||||
if (!field.isAnnotationPresent(classOf[ClassType]))
|
||||
throw new QException("@ClassType must be specified due to type erasure for field: " + field)
|
||||
|
||||
val fieldType = field.getAnnotation(classOf[ClassType]).asInstanceOf[ClassType].value
|
||||
val fieldType = getCollectionType(field)
|
||||
val typeValue = coerce(fieldType, value)
|
||||
|
||||
var list = getter.invoke(obj).asInstanceOf[Seq[_]]
|
||||
|
|
@ -53,10 +50,7 @@ object ReflectionUtils {
|
|||
|
||||
} else if (classOf[Option[_]].isAssignableFrom(field.getType)) {
|
||||
|
||||
if (!field.isAnnotationPresent(classOf[ClassType]))
|
||||
throw new QException("@ClassType must be specified due to type erasure for field: " + field)
|
||||
|
||||
val fieldType = field.getAnnotation(classOf[ClassType]).asInstanceOf[ClassType].value
|
||||
val fieldType = getCollectionType(field)
|
||||
val typeValue = coerce(fieldType, value)
|
||||
|
||||
setter.invoke(obj, Some(typeValue))
|
||||
|
|
@ -70,6 +64,29 @@ object ReflectionUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private def getCollectionType(field: Field) = {
|
||||
getGenericTypes(field) match {
|
||||
case Some(classes) =>
|
||||
if (classes.length > 1)
|
||||
throw new IllegalArgumentException("Field contains more than one generic type: " + field)
|
||||
classes(0)
|
||||
case None =>
|
||||
if (!field.isAnnotationPresent(classOf[ClassType]))
|
||||
throw new QException("@ClassType must be specified for unparameterized field: " + field)
|
||||
field.getAnnotation(classOf[ClassType]).asInstanceOf[ClassType].value
|
||||
}
|
||||
}
|
||||
|
||||
private def getGenericTypes(field: Field) = {
|
||||
// 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 None
|
||||
}
|
||||
|
||||
private[util] def fieldGetter(field: Field) = field.getDeclaringClass.getMethod(field.getName)
|
||||
private[util] def fieldSetter(field: Field) = field.getDeclaringClass.getMethod(field.getName+"_$eq", field.getType)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue