All Downloads are FREE. Search and download functionalities are using the official Maven repository.

pl.touk.nussknacker.engine.definition.component.methodbased.MethodDefinition.scala Maven / Gradle / Ivy

The newest version!
package pl.touk.nussknacker.engine.definition.component.methodbased

import com.typesafe.scalalogging.LazyLogging
import pl.touk.nussknacker.engine.api.definition._
import pl.touk.nussknacker.engine.api.parameter.ParameterName
import pl.touk.nussknacker.engine.api.typed.MissingOutputVariableException
import pl.touk.nussknacker.engine.api.typed.typing.TypingResult
import pl.touk.nussknacker.engine.api.util.ReflectUtils

import java.lang.reflect.{InvocationTargetException, Method}

class MethodDefinition(
    method: Method,
    orderedDependencies: OrderedDependencies,
    // TODO: remove after full switch to ContextTransformation API
    val returnType: TypingResult,
    val runtimeClass: Class[_]
) extends Serializable
    with LazyLogging {

  def definedParameters: List[Parameter] = orderedDependencies.definedParameters

  def invoke(
      obj: Any,
      params: Map[ParameterName, Any],
      outputVariableNameOpt: Option[String],
      additional: Seq[AnyRef]
  ): AnyRef = {
    val values = orderedDependencies.prepareValues(params, outputVariableNameOpt, additional)
    try {
      method.invoke(obj, values.map(_.asInstanceOf[Object]): _*)
    } catch {
      case ex: IllegalArgumentException =>
        // this usually indicates that parameters do not match or argument list is incorrect
        logger.debug(s"Failed to invoke method: ${method.getName}, with params: $values", ex)

        def className(obj: Any) =
          Option(obj).map(o => ReflectUtils.simpleNameWithoutSuffix(o.getClass)).getOrElse("null")

        val parameterValues = orderedDependencies.definedParameters.map(_.name).map(params)
        throw new IllegalArgumentException(
          s"""Failed to invoke "${method.getName}" on ${className(obj)} with parameter types: ${parameterValues.map(
              className
            )}: ${ex.getMessage}""",
          ex
        )
      // this is somehow an edge case - normally service returns failed future for exceptions
      case ex: InvocationTargetException =>
        throw ex.getTargetException
    }
  }

}

class OrderedDependencies(dependencies: List[NodeDependency]) extends Serializable {

  lazy val definedParameters: List[Parameter] = dependencies.collect { case param: Parameter =>
    param
  }

  def prepareValues(
      values: Map[ParameterName, Any],
      outputVariableNameOpt: Option[String],
      additionalDependencies: Seq[AnyRef]
  ): List[Any] = {
    dependencies.map {
      case param: Parameter =>
        values.getOrElse(param.name, throw new IllegalArgumentException(s"Missing parameter: ${param.name}"))
      case OutputVariableNameDependency =>
        outputVariableNameOpt.getOrElse(throw MissingOutputVariableException)
      case TypedNodeDependency(clazz) =>
        val found = additionalDependencies.find(clazz.isInstance)
        found.getOrElse {
          throw new IllegalArgumentException(s"Missing additional parameter of class: ${clazz.getName}")
        }
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy