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

pl.touk.nussknacker.engine.compile.nodecompilation.EvaluableLazyParameterCreator.scala Maven / Gradle / Ivy

The newest version!
package pl.touk.nussknacker.engine.compile.nodecompilation

import pl.touk.nussknacker.engine.api.LazyParameter._
import pl.touk.nussknacker.engine.api._
import pl.touk.nussknacker.engine.api.parameter.ParameterName
import pl.touk.nussknacker.engine.api.typed.typing._
import pl.touk.nussknacker.engine.compile.ExpressionCompiler
import pl.touk.nussknacker.engine.compiledgraph.BaseCompiledParameter
import pl.touk.nussknacker.engine.expression.ExpressionEvaluator
import pl.touk.nussknacker.engine.expression.parse.CompiledExpression
import pl.touk.nussknacker.engine.graph.expression.Expression

// This class looks like a LazyParameter but actually it's not - it's a creator of the LazyParameter.
// It's Flink specific. And should not be evaluated directly. See the `evaluate` method implementation and
// DefaultToEvaluateFunctionConverter class.
final class EvaluableLazyParameterCreator[T <: AnyRef](
    nodeId: NodeId,
    parameterDef: definition.Parameter,
    expression: Expression,
    override val returnType: TypingResult
) extends CustomLazyParameter[T] {

  def create(deps: EvaluableLazyParameterCreatorDeps): EvaluableLazyParameter[T] = {
    createEvaluableLazyParameter(deps)
  }

  override def evaluate: Evaluate[T] = { _ =>
    throw new IllegalStateException(
      s"[${classOf[EvaluableLazyParameterCreator[_]].getName}] looks like a LazyParameter, but actually it's a creator of [${classOf[EvaluableLazyParameter[T]].getName}] instance. It cannot be evaluated directly!"
    )
  }

  private def createEvaluableLazyParameter(deps: EvaluableLazyParameterCreatorDeps) = {
    val compiledExpression = deps.expressionCompiler
      .compileWithoutContextValidation(expression, parameterDef.name, parameterDef.typ)(nodeId)
      .valueOr(err =>
        throw new IllegalArgumentException(s"Compilation failed with errors: ${err.toList.mkString(", ")}")
      )
    val compiledParameter: BaseCompiledParameter = new BaseCompiledParameter {
      override val name: ParameterName                      = parameterDef.name
      override val expression: CompiledExpression           = compiledExpression
      override val shouldBeWrappedWithScalaOption: Boolean  = parameterDef.scalaOptionParameter
      override val shouldBeWrappedWithJavaOptional: Boolean = parameterDef.javaOptionalParameter
    }
    new EvaluableLazyParameter[T](
      compiledParameter,
      deps.expressionEvaluator,
      nodeId,
      deps.jobData,
      returnType
    )
  }

}

class EvaluableLazyParameterCreatorDeps(
    val expressionCompiler: ExpressionCompiler,
    val expressionEvaluator: ExpressionEvaluator,
    val jobData: JobData
)

class DefaultToEvaluateFunctionConverter(deps: EvaluableLazyParameterCreatorDeps) extends ToEvaluateFunctionConverter {

  override def toEvaluateFunction[T <: AnyRef](lazyParameter: LazyParameter[T]): Evaluate[T] = {
    // it's important that it's (...): (Context => T)
    // and not e.g. (...)(Context) => T as we want to be sure when body is evaluated (in particular expression compilation)!
    prepareLazyParameterToBeEvaluated(lazyParameter).evaluate
  }

  private def prepareLazyParameterToBeEvaluated[T <: AnyRef](lazyParameter: LazyParameter[T]): LazyParameter[T] = {
    lazyParameter match {
      case creator: EvaluableLazyParameterCreator[T] =>
        prepareLazyParameterToBeEvaluated(creator.create(deps))
      case p: EvaluableLazyParameter[T] => p
      case p: FixedLazyParameter[T]     => p
      case p: ProductLazyParameter[_, _] =>
        LazyParameter
          .product(
            prepareLazyParameterToBeEvaluated(p.arg1),
            prepareLazyParameterToBeEvaluated(p.arg2)
          )
          .asInstanceOf[LazyParameter[T]]
      case p: SequenceLazyParameter[_, T] =>
        LazyParameter.sequence(
          fa = p.args.map(prepareLazyParameterToBeEvaluated),
          wrapResult = p.wrapResult,
          wrapReturnType = p.wrapReturnType
        )
      case p: MappedLazyParameter[_, T] =>
        LazyParameter.mapped(
          prepareLazyParameterToBeEvaluated(p.arg),
          p.fun,
          p.transformTypingResult
        )
      case p: CustomLazyParameter[T] => p
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy