Skip to content
Closed
Prev Previous commit
Next Next commit
Resolving setters outside eval.
  • Loading branch information
viirya committed Mar 7, 2018
commit b51303a49c66a178e9cdd717605e3ef0d41e6a3a
Original file line number Diff line number Diff line change
Expand Up @@ -1261,20 +1261,27 @@ case class InitializeJavaBean(beanInstance: Expression, setters: Map[String, Exp
override def children: Seq[Expression] = beanInstance +: setters.values.toSeq
override def dataType: DataType = beanInstance.dataType

private lazy val resolvedSetters = {
val ObjectType(beanClass) = beanInstance.dataType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to put assert(beanInstance.dataType.isInstanceOf[ObjectType]) in the constructor?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.


setters.map { case (setterMethod, fieldExpr) =>
val foundMethods = beanClass.getMethods.filter { method =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Picking up our earlier conversation) You are not checking the argument?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will updated later.

method.getName == setterMethod && Modifier.isPublic(method.getModifiers) &&
method.getParameterTypes.length == 1
}
assert(foundMethods.length == 1,
throw new RuntimeException("The Java Bean class should have only one " +
s"setter $setterMethod method, but ${foundMethods.length} methods found."))
(foundMethods.head, fieldExpr)
}
}

override def eval(input: InternalRow): Any = {
val instance = beanInstance.eval(input).asInstanceOf[Object]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: better to put the cast inside if for avoiding unnecessary casts in case of many null cases?;

    val instance = beanInstance.eval(input)
    if (instance != null) {
      val obj = instance.asInstanceOf[Object]
      resolvedSetters.foreach {
        case (setter: Method, expr) =>
          setter.invoke(obj, expr.eval(input).asInstanceOf[Object])
      }
    }
    instance

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.

if (instance != null) {
setters.foreach { case (setterMethod, fieldExpr) =>
resolvedSetters.foreach { case (setterMethod, fieldExpr) =>
val fieldValue = fieldExpr.eval(input).asInstanceOf[Object]

val foundMethods = instance.getClass.getMethods.filter { method =>
method.getName == setterMethod && Modifier.isPublic(method.getModifiers) &&
method.getParameterTypes.length == 1
}
assert(foundMethods.length == 1,
throw new RuntimeException("The Java Bean instance should have only one " +
s"setter $setterMethod method, but ${foundMethods.length} methods found."))
foundMethods.head.invoke(instance, fieldValue)
setterMethod.invoke(instance, fieldValue)
}
}
instance
Expand Down