From 4f33e7a9e6178c73de0dfca7659827f82a9ffde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82abek?= Date: Tue, 5 Nov 2024 11:16:11 +0100 Subject: [PATCH 1/4] make multiple fields public vals in EvaluableLazyParameter and SpelExpression --- .../EvaluableLazyParameter.scala | 6 +- .../engine/spel/SpelExpression.scala | 4 +- .../nussknacker/engine/InterpreterSpec.scala | 100 +++++++++++++++++- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala index 1e441c02717..f9008de3c62 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala @@ -7,10 +7,10 @@ import pl.touk.nussknacker.engine.compiledgraph.{BaseCompiledParameter, Compiled import pl.touk.nussknacker.engine.expression.ExpressionEvaluator class EvaluableLazyParameter[T <: AnyRef]( - compiledParameter: BaseCompiledParameter, - expressionEvaluator: ExpressionEvaluator, + val compiledParameter: BaseCompiledParameter, + val expressionEvaluator: ExpressionEvaluator, nodeId: NodeId, - jobData: JobData, + val jobData: JobData, override val returnType: TypingResult ) extends CustomLazyParameter[T] { diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala index a521545c97f..42d761c4fbe 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala @@ -81,10 +81,10 @@ class SpelExpressionEvaluationException(val expression: String, val ctxId: Strin ) class SpelExpression( - parsed: ParsedSpelExpression, + val parsed: ParsedSpelExpression, expectedReturnType: TypingResult, flavour: Flavour, - evaluationContextPreparer: EvaluationContextPreparer + val evaluationContextPreparer: EvaluationContextPreparer ) extends CompiledExpression with LazyLogging { diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala index e5135ece369..cc1e4dfb081 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala @@ -6,6 +6,7 @@ import cats.effect.IO import cats.effect.unsafe.IORuntime import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers +import org.springframework.expression.common.CompositeStringExpression import org.springframework.expression.spel.standard.SpelExpression import pl.touk.nussknacker.engine.InterpreterSpec._ import pl.touk.nussknacker.engine.api._ @@ -17,7 +18,12 @@ import pl.touk.nussknacker.engine.api.context.transformation.{ NodeDependencyValue, SingleInputDynamicComponent } -import pl.touk.nussknacker.engine.api.context.{ContextTransformation, ProcessCompilationError, ValidationContext} +import pl.touk.nussknacker.engine.api.context.{ + ContextTransformation, + OutputVar, + ProcessCompilationError, + ValidationContext +} import pl.touk.nussknacker.engine.api.definition.{AdditionalVariable => _, _} import pl.touk.nussknacker.engine.api.dict.embedded.EmbeddedDictDefinition import pl.touk.nussknacker.engine.api.exception.NuExceptionInfo @@ -32,9 +38,10 @@ import pl.touk.nussknacker.engine.build.{GraphBuilder, ScenarioBuilder} import pl.touk.nussknacker.engine.canonicalgraph.canonicalnode.FlatNode import pl.touk.nussknacker.engine.canonicalgraph.{CanonicalProcess, canonicalnode} import pl.touk.nussknacker.engine.compile._ +import pl.touk.nussknacker.engine.compile.nodecompilation.EvaluableLazyParameter import pl.touk.nussknacker.engine.compiledgraph.part.{CustomNodePart, ProcessPart, SinkPart} +import pl.touk.nussknacker.engine.definition.component.Components import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode -import pl.touk.nussknacker.engine.definition.component.{ComponentDefinitionWithImplementation, Components} import pl.touk.nussknacker.engine.definition.model.{ModelDefinition, ModelDefinitionWithClasses} import pl.touk.nussknacker.engine.dict.SimpleDictRegistry import pl.touk.nussknacker.engine.graph.evaluatedparam.{Parameter => NodeParameter} @@ -46,7 +53,7 @@ import pl.touk.nussknacker.engine.graph.sink.SinkRef import pl.touk.nussknacker.engine.graph.variable.Field import pl.touk.nussknacker.engine.modelconfig.ComponentsUiConfig import pl.touk.nussknacker.engine.resultcollector.ProductionServiceInvocationCollector -import pl.touk.nussknacker.engine.spel.SpelExpressionRepr +import pl.touk.nussknacker.engine.spel.{ParsedSpelExpression, SpelExpressionParser, SpelExpressionRepr} import pl.touk.nussknacker.engine.testing.ModelDefinitionBuilder import pl.touk.nussknacker.engine.util.service.{ EagerServiceWithStaticParametersAndReturnType, @@ -72,6 +79,7 @@ class InterpreterSpec extends AnyFunSuite with Matchers { ComponentDefinition("spelNodeService", SpelNodeService), ComponentDefinition("withExplicitMethod", WithExplicitDefinitionService), ComponentDefinition("spelTemplateService", ServiceUsingSpelTemplate), + ComponentDefinition("spelTemplateAstOperationService", SpelTemplateServiceWithAstOperation), ComponentDefinition("optionTypesService", OptionTypesService), ComponentDefinition("optionalTypesService", OptionalTypesService), ComponentDefinition("nullableTypesService", NullableTypesService), @@ -1020,6 +1028,22 @@ class InterpreterSpec extends AnyFunSuite with Matchers { interpretProcess(process, Transaction()) shouldBe "someKey" } + test("its possible to parse and evaluate spel template subexpressions inside service") { + val process = ScenarioBuilder + .streaming("test") + .source("start", "transaction-source") + .enricher( + "ex", + "out", + "spelTemplateAstOperationService", + "template" -> Expression.spelTemplate(s"#{'Hello'}#{#input.msisdn}") + ) + .buildSimpleVariable("result-end", resultVariable, "#out".spel) + .emptySink("end-end", "dummySink") + + interpretProcess(process, Transaction(msisdn = "foo")) should equal("Map(value-0 -> Hello, value-1 -> foo)") + } + } class ThrowingService extends Service { @@ -1288,4 +1312,74 @@ object InterpreterSpec { } + object SpelTemplateServiceWithAstOperation extends EagerService with SingleInputDynamicComponent[ServiceInvoker] { + + private val spelTemplateParameter = ParameterDeclaration + .lazyMandatory[String](ParameterName("template")) + .withCreator(modify = + _.copy( + editor = Some(SpelTemplateParameterEditor), + defaultValue = Some(Expression.spelTemplate("")) + ) + ) + + override type State = Any + + override def contextTransformation(context: ValidationContext, dependencies: List[NodeDependencyValue])( + implicit nodeId: NodeId + ): SpelTemplateServiceWithAstOperation.ContextTransformationDefinition = { + case TransformationStep(Nil, _) => NextParameters(List(spelTemplateParameter.createParameter())) + case TransformationStep((ParameterName("template"), DefinedLazyParameter(_)) :: Nil, _) => + FinalResults.forValidation(context, List.empty)(validation = + ctx => + ctx.withVariable( + OutputVariableNameDependency.extract(dependencies), + Typed[String], + Some(ParameterName(OutputVar.VariableFieldName)) + ) + ) + } + + override def implementation( + params: Params, + dependencies: List[NodeDependencyValue], + finalState: Option[Any] + ): ServiceInvoker = new ServiceInvoker { + + override def invoke(context: Context)( + implicit ec: ExecutionContext, + collector: InvocationCollectors.ServiceInvocationCollector, + componentUseCase: ComponentUseCase + ): Future[Any] = { + val lazyParam = spelTemplateParameter.extractValueUnsafe(params).asInstanceOf[EvaluableLazyParameter[String]] + val baseExpr = + lazyParam.compiledParameter.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] + val parsedExpr = baseExpr.parsed + val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] + + val subValues = compositeExpr.getExpressions.toList.map { subExpr => + val evalutorContextPreparer = baseExpr.evaluationContextPreparer + + val parsedSubexpression = ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) + val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( + parsedSubexpression, + typing.Typed[String], + SpelExpressionParser.Standard, + evalutorContextPreparer + ) + + val evaluator = lazyParam.expressionEvaluator + val jobData = lazyParam.jobData + evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value + } + + val result = subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString + Future.successful(result) + } + + } + + override def nodeDependencies: List[NodeDependency] = List(OutputVariableNameDependency) + } + } From 0fb230066432025befd803d9f92658d02434ab0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82abek?= Date: Fri, 8 Nov 2024 18:38:57 +0100 Subject: [PATCH 2/4] wip --- .../EvaluableLazyParameter.scala | 30 ++++++++--- .../nussknacker/engine/InterpreterSpec.scala | 53 +++++++++++-------- 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala index f9008de3c62..f4ab282e90a 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala @@ -2,7 +2,7 @@ package pl.touk.nussknacker.engine.compile.nodecompilation import pl.touk.nussknacker.engine.api.LazyParameter.{CustomLazyParameter, Evaluate} import pl.touk.nussknacker.engine.api.typed.typing.TypingResult -import pl.touk.nussknacker.engine.api.{Context, JobData, MetaData, NodeId} +import pl.touk.nussknacker.engine.api.{Context, JobData, NodeId} import pl.touk.nussknacker.engine.compiledgraph.{BaseCompiledParameter, CompiledParameter} import pl.touk.nussknacker.engine.expression.ExpressionEvaluator @@ -11,7 +11,8 @@ class EvaluableLazyParameter[T <: AnyRef]( val expressionEvaluator: ExpressionEvaluator, nodeId: NodeId, val jobData: JobData, - override val returnType: TypingResult + override val returnType: TypingResult, + val customEvaluate: Option[(BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T] = None ) extends CustomLazyParameter[T] { def this( @@ -23,10 +24,27 @@ class EvaluableLazyParameter[T <: AnyRef]( this(compiledParameter, expressionEvaluator, nodeId, jobData, compiledParameter.typingInfo.typingResult) override val evaluate: Evaluate[T] = { ctx: Context => - expressionEvaluator - .evaluateParameter(compiledParameter, ctx)(nodeId, jobData) - .value - .asInstanceOf[T] + customEvaluate + .map(evaluate => evaluate(compiledParameter, expressionEvaluator, nodeId, jobData, ctx)) + .getOrElse { + expressionEvaluator + .evaluateParameter(compiledParameter, ctx)(nodeId, jobData) + .value + .asInstanceOf[T] + } + } + + def withCustomEvaluationLogic( + customEvaluate: (BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T + ): EvaluableLazyParameter[T] = { + new EvaluableLazyParameter( + compiledParameter, + expressionEvaluator, + nodeId, + jobData, + returnType, + Some(customEvaluate) + ) } } diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala index cc1e4dfb081..004ad969485 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala @@ -39,11 +39,13 @@ import pl.touk.nussknacker.engine.canonicalgraph.canonicalnode.FlatNode import pl.touk.nussknacker.engine.canonicalgraph.{CanonicalProcess, canonicalnode} import pl.touk.nussknacker.engine.compile._ import pl.touk.nussknacker.engine.compile.nodecompilation.EvaluableLazyParameter +import pl.touk.nussknacker.engine.compiledgraph.BaseCompiledParameter import pl.touk.nussknacker.engine.compiledgraph.part.{CustomNodePart, ProcessPart, SinkPart} import pl.touk.nussknacker.engine.definition.component.Components import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode import pl.touk.nussknacker.engine.definition.model.{ModelDefinition, ModelDefinitionWithClasses} import pl.touk.nussknacker.engine.dict.SimpleDictRegistry +import pl.touk.nussknacker.engine.expression.ExpressionEvaluator import pl.touk.nussknacker.engine.graph.evaluatedparam.{Parameter => NodeParameter} import pl.touk.nussknacker.engine.graph.expression._ import pl.touk.nussknacker.engine.graph.fragment.FragmentRef @@ -1351,30 +1353,37 @@ object InterpreterSpec { collector: InvocationCollectors.ServiceInvocationCollector, componentUseCase: ComponentUseCase ): Future[Any] = { - val lazyParam = spelTemplateParameter.extractValueUnsafe(params).asInstanceOf[EvaluableLazyParameter[String]] - val baseExpr = - lazyParam.compiledParameter.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] - val parsedExpr = baseExpr.parsed - val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] - - val subValues = compositeExpr.getExpressions.toList.map { subExpr => - val evalutorContextPreparer = baseExpr.evaluationContextPreparer - - val parsedSubexpression = ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) - val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( - parsedSubexpression, - typing.Typed[String], - SpelExpressionParser.Standard, - evalutorContextPreparer - ) - - val evaluator = lazyParam.expressionEvaluator - val jobData = lazyParam.jobData - evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value + def customEvaluation( + param: BaseCompiledParameter, + exprEval: ExpressionEvaluator, + nodeId: NodeId, + jobData: JobData, + context: Context + ): String = { + val baseExpr = param.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] + val parsedExpr = baseExpr.parsed + val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] + val subValues = compositeExpr.getExpressions.toList.map { subExpr => + val evalutorContextPreparer = baseExpr.evaluationContextPreparer + val parsedSubexpression = + ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) + val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( + parsedSubexpression, + typing.Typed[String], + SpelExpressionParser.Standard, + evalutorContextPreparer + ) + val evaluator = exprEval + evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value + } + subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString } - val result = subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString - Future.successful(result) + val lazyParam = spelTemplateParameter + .extractValueUnsafe(params) + .asInstanceOf[EvaluableLazyParameter[String]] + .withCustomEvaluationLogic(customEvaluation) + Future.successful(lazyParam.evaluate(context)) } } From fcfc1279201324ceacd4af930d031b4a1539bd6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82abek?= Date: Tue, 12 Nov 2024 12:12:21 +0100 Subject: [PATCH 3/4] half-api approach with CustomLazyParamterWithCustomizableEvaluationLogic --- .../engine/api/LazyParameter.scala | 33 +++++++++++- .../touk/nussknacker/engine/Interpreter.scala | 1 - .../engine/compile/ExpressionCompiler.scala | 9 +--- .../nodecompilation/BuiltInNodeCompiler.scala | 4 +- .../EvaluableLazyParameter.scala | 14 +++-- .../EvaluableLazyParameterCreator.scala | 2 - .../nodecompilation/NodeCompiler.scala | 4 +- .../compiledgraph/CompiledParameter.scala | 10 +--- .../engine/compiledgraph/node.scala | 3 +- .../engine/compiledgraph/variable.scala | 2 +- ...lidationExpressionParameterValidator.scala | 3 +- .../expression/ExpressionEvaluator.scala | 5 +- .../engine/expression/NullExpression.scala | 3 +- .../expression/parse/CompiledExpression.scala | 11 +--- .../expression/parse/ExpressionParser.scala | 1 + .../DictKeyWithLabelExpressionParser.scala | 4 +- .../TabularDataDefinitionParser.scala | 4 +- .../engine/spel/SpelExpression.scala | 4 +- .../nussknacker/engine/InterpreterSpec.scala | 54 +++++++++---------- ...tionExpressionParameterValidatorTest.scala | 12 +++-- .../engine/spel/SpelExpressionSpec.scala | 4 +- .../engine/util/functions/BaseSpelSpec.scala | 3 +- 22 files changed, 102 insertions(+), 88 deletions(-) diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/LazyParameter.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/LazyParameter.scala index 90d756acf0d..6f51c9ebf53 100644 --- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/LazyParameter.scala +++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/LazyParameter.scala @@ -1,7 +1,9 @@ package pl.touk.nussknacker.engine.api import pl.touk.nussknacker.engine.api.LazyParameter.{Evaluate, MappedLazyParameter, ProductLazyParameter} +import pl.touk.nussknacker.engine.api.parameter.ParameterName import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypingResult} +import pl.touk.nussknacker.engine.graph.expression.Expression.Language import scala.reflect.runtime.universe.TypeTag @@ -66,7 +68,15 @@ object LazyParameter { ): LazyParameter[Y] = new MappedLazyParameter[T, Y](lazyParameter, fun, transformTypingResult) - trait CustomLazyParameter[+T <: AnyRef] extends LazyParameter[T] + trait CustomLazyParameter[T <: AnyRef] extends LazyParameter[T] + + trait CustomLazyParamterWithCustomizableEvaluationLogic[T <: AnyRef] extends CustomLazyParameter[T] { + + def withCustomEvaluationLogic( + customEvaluate: (BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => T + ): CustomLazyParamterWithCustomizableEvaluationLogic[T] + + } final class ProductLazyParameter[T <: AnyRef, Y <: AnyRef]( val arg1: LazyParameter[T], @@ -122,6 +132,27 @@ object LazyParameter { } +trait BaseCompiledParameter { + def name: ParameterName + def expression: CompiledExpression + def shouldBeWrappedWithScalaOption: Boolean + def shouldBeWrappedWithJavaOptional: Boolean +} + +trait CompiledExpression { + def language: Language + def original: String + def evaluate[T](ctx: Context, globals: Map[String, Any]): T +} + +trait BaseExpressionEvaluator { + + def evaluate[R](expr: CompiledExpression, expressionId: String, nodeId: String, ctx: Context)( + implicit jobData: JobData + ): ValueWithContext[R] + +} + // This class is Flink-specific. It allows to evaluate value of lazy parameter in case when LazyParameter isn't // a ready to evaluation function. In Flink case, LazyParameters are passed into Flink's operators so they // need to be Serializable. Because of that they can't hold heavy objects like ExpressionCompiler or ExpressionEvaluator diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/Interpreter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/Interpreter.scala index 12eb8a42c02..33ae8a7c90c 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/Interpreter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/Interpreter.scala @@ -12,7 +12,6 @@ import pl.touk.nussknacker.engine.compiledgraph.node._ import pl.touk.nussknacker.engine.compiledgraph.service._ import pl.touk.nussknacker.engine.compiledgraph.variable._ import pl.touk.nussknacker.engine.expression.ExpressionEvaluator -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression import pl.touk.nussknacker.engine.node.NodeComponentInfoExtractor import pl.touk.nussknacker.engine.util.SynchronousExecutionContextAndIORuntime diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/ExpressionCompiler.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/ExpressionCompiler.scala index 23c7426e4fb..3fccbc28034 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/ExpressionCompiler.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/ExpressionCompiler.scala @@ -4,7 +4,7 @@ import cats.data.Validated.{Invalid, Valid, invalid, invalidNel, valid} import cats.data.{Ior, IorNel, NonEmptyList, Validated, ValidatedNel} import cats.instances.list._ import pl.touk.nussknacker.engine.ModelData -import pl.touk.nussknacker.engine.api.{JobData, MetaData, NodeId} +import pl.touk.nussknacker.engine.api.{CompiledExpression, JobData, MetaData, NodeId} import pl.touk.nussknacker.engine.api.context.ProcessCompilationError._ import pl.touk.nussknacker.engine.api.context.{PartSubGraphCompilationError, ProcessCompilationError, ValidationContext} import pl.touk.nussknacker.engine.api.definition._ @@ -17,12 +17,7 @@ import pl.touk.nussknacker.engine.definition.clazz.ClassDefinitionSet import pl.touk.nussknacker.engine.definition.component.parameter.validator.ValidationExpressionParameterValidator import pl.touk.nussknacker.engine.definition.globalvariables.ExpressionConfigDefinition import pl.touk.nussknacker.engine.expression.{ExpressionEvaluator, NullExpression} -import pl.touk.nussknacker.engine.expression.parse.{ - CompiledExpression, - ExpressionParser, - TypedExpression, - TypedExpressionMap -} +import pl.touk.nussknacker.engine.expression.parse.{ExpressionParser, TypedExpression, TypedExpressionMap} import pl.touk.nussknacker.engine.graph.evaluatedparam.{BranchParameters, Parameter => NodeParameter} import pl.touk.nussknacker.engine.graph.expression.Expression import pl.touk.nussknacker.engine.graph.expression.Expression.Language diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/BuiltInNodeCompiler.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/BuiltInNodeCompiler.scala index b4b2c9106da..0416c9ac356 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/BuiltInNodeCompiler.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/BuiltInNodeCompiler.scala @@ -4,7 +4,7 @@ import cats.data.Validated.{Invalid, Valid} import cats.data.ValidatedNel import cats.implicits.{catsSyntaxTuple2Semigroupal, toFoldableOps, toTraverseOps} import cats.instances.list._ -import pl.touk.nussknacker.engine.api.NodeId +import pl.touk.nussknacker.engine.api.{CompiledExpression, NodeId} import pl.touk.nussknacker.engine.api.context._ import pl.touk.nussknacker.engine.api.expression.ExpressionTypingInfo import pl.touk.nussknacker.engine.api.parameter.ParameterName @@ -14,7 +14,7 @@ import pl.touk.nussknacker.engine.compile.nodecompilation.BaseComponentValidatio import pl.touk.nussknacker.engine.compile.nodecompilation.BuiltInNodeCompiler._ import pl.touk.nussknacker.engine.compile.nodecompilation.NodeCompiler.NodeCompilationResult import pl.touk.nussknacker.engine.compiledgraph -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.TypedExpression import pl.touk.nussknacker.engine.graph.expression.NodeExpressionId.DefaultExpressionIdParamName import pl.touk.nussknacker.engine.graph.expression._ import pl.touk.nussknacker.engine.graph.node diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala index f4ab282e90a..2785cba3ca0 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala @@ -1,9 +1,13 @@ package pl.touk.nussknacker.engine.compile.nodecompilation -import pl.touk.nussknacker.engine.api.LazyParameter.{CustomLazyParameter, Evaluate} +import pl.touk.nussknacker.engine.api.LazyParameter.{ + CustomLazyParameter, + CustomLazyParamterWithCustomizableEvaluationLogic, + Evaluate +} import pl.touk.nussknacker.engine.api.typed.typing.TypingResult -import pl.touk.nussknacker.engine.api.{Context, JobData, NodeId} -import pl.touk.nussknacker.engine.compiledgraph.{BaseCompiledParameter, CompiledParameter} +import pl.touk.nussknacker.engine.api.{BaseCompiledParameter, BaseExpressionEvaluator, Context, JobData, NodeId} +import pl.touk.nussknacker.engine.compiledgraph.CompiledParameter import pl.touk.nussknacker.engine.expression.ExpressionEvaluator class EvaluableLazyParameter[T <: AnyRef]( @@ -13,7 +17,7 @@ class EvaluableLazyParameter[T <: AnyRef]( val jobData: JobData, override val returnType: TypingResult, val customEvaluate: Option[(BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T] = None -) extends CustomLazyParameter[T] { +) extends CustomLazyParamterWithCustomizableEvaluationLogic[T] { def this( compiledParameter: CompiledParameter, @@ -35,7 +39,7 @@ class EvaluableLazyParameter[T <: AnyRef]( } def withCustomEvaluationLogic( - customEvaluate: (BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T + customEvaluate: (BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => T ): EvaluableLazyParameter[T] = { new EvaluableLazyParameter( compiledParameter, diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala index 1277c3b5de0..d66e2598029 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala @@ -5,9 +5,7 @@ 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. diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala index f27793e2795..cdfab155cad 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/NodeCompiler.scala @@ -3,7 +3,7 @@ package pl.touk.nussknacker.engine.compile.nodecompilation import cats.data.Validated.{Invalid, Valid, invalid, valid} import cats.data.{NonEmptyList, ValidatedNel, Writer} import cats.implicits._ -import pl.touk.nussknacker.engine.api._ +import pl.touk.nussknacker.engine.api.{CompiledExpression, _} import pl.touk.nussknacker.engine.api.component.ComponentType import pl.touk.nussknacker.engine.api.context.ProcessCompilationError._ import pl.touk.nussknacker.engine.api.context._ @@ -32,7 +32,7 @@ import pl.touk.nussknacker.engine.definition.component.methodbased.MethodBasedCo import pl.touk.nussknacker.engine.definition.fragment.FragmentParametersDefinitionExtractor import pl.touk.nussknacker.engine.definition.globalvariables.ExpressionConfigDefinition import pl.touk.nussknacker.engine.definition.model.ModelDefinition -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, TypedExpression, TypedExpressionMap} +import pl.touk.nussknacker.engine.expression.parse.{TypedExpression, TypedExpressionMap} import pl.touk.nussknacker.engine.graph.evaluatedparam.{BranchParameters, Parameter => NodeParameter} import pl.touk.nussknacker.engine.graph.expression.NodeExpressionId.branchParameterExpressionId import pl.touk.nussknacker.engine.graph.expression._ diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/CompiledParameter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/CompiledParameter.scala index 2c86b9476ff..31e89def3a1 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/CompiledParameter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/CompiledParameter.scala @@ -1,9 +1,10 @@ package pl.touk.nussknacker.engine.compiledgraph +import pl.touk.nussknacker.engine.api.{BaseCompiledParameter, CompiledExpression} import pl.touk.nussknacker.engine.api.definition.Parameter import pl.touk.nussknacker.engine.api.expression.ExpressionTypingInfo import pl.touk.nussknacker.engine.api.parameter.ParameterName -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.TypedExpression object CompiledParameter { @@ -29,10 +30,3 @@ final case class CompiledParameter( override val shouldBeWrappedWithJavaOptional: Boolean, typingInfo: ExpressionTypingInfo ) extends BaseCompiledParameter - -trait BaseCompiledParameter { - def name: ParameterName - def expression: CompiledExpression - def shouldBeWrappedWithScalaOption: Boolean - def shouldBeWrappedWithJavaOptional: Boolean -} diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/node.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/node.scala index d1e1dfef964..a1b86d27602 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/node.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/node.scala @@ -1,8 +1,9 @@ package pl.touk.nussknacker.engine.compiledgraph +import pl.touk.nussknacker.engine.api.CompiledExpression import pl.touk.nussknacker.engine.compiledgraph.service.ServiceRef import pl.touk.nussknacker.engine.compiledgraph.variable.Field -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.TypedExpression import pl.touk.nussknacker.engine.graph.node.BranchEndDefinition object node { diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/variable.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/variable.scala index 6e761b3f1b0..8ae1460ac0b 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/variable.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compiledgraph/variable.scala @@ -1,6 +1,6 @@ package pl.touk.nussknacker.engine.compiledgraph -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression +import pl.touk.nussknacker.engine.api.CompiledExpression object variable { diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidator.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidator.scala index 8828af73295..46b9aadd6a2 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidator.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidator.scala @@ -6,10 +6,9 @@ import pl.touk.nussknacker.engine.api.context.PartSubGraphCompilationError import pl.touk.nussknacker.engine.api.context.ProcessCompilationError._ import pl.touk.nussknacker.engine.api.definition.{CompileTimeEvaluableValueValidator, Validator} import pl.touk.nussknacker.engine.api.parameter.ParameterName -import pl.touk.nussknacker.engine.api.{Context, CustomMetaData, JobData, MetaData, NodeId} +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context, CustomMetaData, JobData, MetaData, NodeId} import pl.touk.nussknacker.engine.definition.component.parameter.validator.ValidationExpressionParameterValidator.variableName import pl.touk.nussknacker.engine.expression.ExpressionEvaluator -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression import pl.touk.nussknacker.engine.graph.expression.Expression import scala.util.Try diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/ExpressionEvaluator.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/ExpressionEvaluator.scala index 6db0ee2892b..3ec30ac607f 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/ExpressionEvaluator.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/ExpressionEvaluator.scala @@ -3,8 +3,7 @@ package pl.touk.nussknacker.engine.expression import pl.touk.nussknacker.engine.api.typed.CustomNodeValidationException import pl.touk.nussknacker.engine.api._ import pl.touk.nussknacker.engine.api.parameter.ParameterName -import pl.touk.nussknacker.engine.compiledgraph.{BaseCompiledParameter, CompiledParameter} -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression +import pl.touk.nussknacker.engine.compiledgraph.CompiledParameter import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap import pl.touk.nussknacker.engine.variables.GlobalVariablesPreparer @@ -39,7 +38,7 @@ class ExpressionEvaluator( globalVariablesPreparer: GlobalVariablesPreparer, listeners: Seq[ProcessListener], cacheGlobalVariables: Boolean -) { +) extends BaseExpressionEvaluator { private def prepareGlobals(jobData: JobData): Map[String, Any] = globalVariablesPreparer.prepareGlobalVariables(jobData).mapValuesNow(_.obj) diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/NullExpression.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/NullExpression.scala index d40f333e3dd..24688cd76cf 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/NullExpression.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/NullExpression.scala @@ -1,8 +1,7 @@ package pl.touk.nussknacker.engine.expression -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.graph.expression.Expression.Language -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression import pl.touk.nussknacker.engine.spel.SpelExpressionParser.Flavour case class NullExpression(original: String, flavour: Flavour) extends CompiledExpression { diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/CompiledExpression.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/CompiledExpression.scala index 0a0f3db5d64..e7625ceb069 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/CompiledExpression.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/CompiledExpression.scala @@ -1,19 +1,10 @@ package pl.touk.nussknacker.engine.expression.parse -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.api.expression.ExpressionTypingInfo import pl.touk.nussknacker.engine.api.typed.typing.TypingResult import pl.touk.nussknacker.engine.graph.expression.Expression.Language -trait CompiledExpression { - - def language: Language - - def original: String - - def evaluate[T](ctx: Context, globals: Map[String, Any]): T -} - sealed trait TypedValue case class TypedExpression(expression: CompiledExpression, typingInfo: ExpressionTypingInfo) extends TypedValue { diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/ExpressionParser.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/ExpressionParser.scala index 73c8b2ee3cc..2e7ec9ea109 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/ExpressionParser.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/expression/parse/ExpressionParser.scala @@ -1,6 +1,7 @@ package pl.touk.nussknacker.engine.expression.parse import cats.data.ValidatedNel +import pl.touk.nussknacker.engine.api.CompiledExpression import pl.touk.nussknacker.engine.api.context.ValidationContext import pl.touk.nussknacker.engine.api.generics.ExpressionParseError import pl.touk.nussknacker.engine.api.typed.typing.TypingResult diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/dictWithLabel/DictKeyWithLabelExpressionParser.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/dictWithLabel/DictKeyWithLabelExpressionParser.scala index c95b3d41437..70990f23a83 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/dictWithLabel/DictKeyWithLabelExpressionParser.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/dictWithLabel/DictKeyWithLabelExpressionParser.scala @@ -3,7 +3,7 @@ package pl.touk.nussknacker.engine.language.dictWithLabel import cats.data.Validated.{Valid, invalidNel} import cats.data.{NonEmptyList, Validated} import io.circe.parser -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.api.context.ValidationContext import pl.touk.nussknacker.engine.api.definition.{AdditionalVariable => _} import pl.touk.nussknacker.engine.api.expression.ExpressionTypingInfo @@ -11,7 +11,7 @@ import pl.touk.nussknacker.engine.api.generics.ExpressionParseError import pl.touk.nussknacker.engine.api.typed.typing import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypingResult} import pl.touk.nussknacker.engine.expression.NullExpression -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, ExpressionParser, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.{ExpressionParser, TypedExpression} import pl.touk.nussknacker.engine.graph.expression.Expression.Language import pl.touk.nussknacker.engine.graph.expression.{DictKeyWithLabelExpression, Expression} import pl.touk.nussknacker.engine.spel.SpelExpressionParseError.KeyWithLabelExpressionParsingError diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/tabularDataDefinition/TabularDataDefinitionParser.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/tabularDataDefinition/TabularDataDefinitionParser.scala index f77c70f53f2..87199bd8bd9 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/tabularDataDefinition/TabularDataDefinitionParser.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/language/tabularDataDefinition/TabularDataDefinitionParser.scala @@ -2,7 +2,7 @@ package pl.touk.nussknacker.engine.language.tabularDataDefinition import cats.data.ValidatedNel import cats.implicits._ -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.api.context.ValidationContext import pl.touk.nussknacker.engine.api.expression.ExpressionTypingInfo import pl.touk.nussknacker.engine.api.generics.ExpressionParseError @@ -13,7 +13,7 @@ import pl.touk.nussknacker.engine.api.generics.ExpressionParseError.{ TabularDataDefinitionParserErrorDetails } import pl.touk.nussknacker.engine.api.typed.typing -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, ExpressionParser, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.{ExpressionParser, TypedExpression} import pl.touk.nussknacker.engine.graph.expression.Expression.Language import pl.touk.nussknacker.engine.graph.expression.TabularTypedData import pl.touk.nussknacker.engine.graph.expression.TabularTypedData.CreationError.{ diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala index 42d761c4fbe..f37b88d2093 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/SpelExpression.scala @@ -13,7 +13,7 @@ import org.springframework.expression.spel.{ SpelParserConfiguration, standard } -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.api.context.ValidationContext import pl.touk.nussknacker.engine.api.dict.DictRegistry import pl.touk.nussknacker.engine.api.exception.NonTransientException @@ -24,7 +24,7 @@ import pl.touk.nussknacker.engine.definition.clazz.ClassDefinitionSet import pl.touk.nussknacker.engine.definition.globalvariables.ExpressionConfigDefinition import pl.touk.nussknacker.engine.dict.{KeysDictTyper, LabelsDictTyper} import pl.touk.nussknacker.engine.expression.NullExpression -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, ExpressionParser, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.{ExpressionParser, TypedExpression} import pl.touk.nussknacker.engine.graph.expression.Expression.Language import pl.touk.nussknacker.engine.graph.expression.{Expression => GraphExpression} import pl.touk.nussknacker.engine.spel.SpelExpressionParseError.ExpressionCompilationError diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala index 004ad969485..86a3ea3dabf 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala @@ -39,7 +39,6 @@ import pl.touk.nussknacker.engine.canonicalgraph.canonicalnode.FlatNode import pl.touk.nussknacker.engine.canonicalgraph.{CanonicalProcess, canonicalnode} import pl.touk.nussknacker.engine.compile._ import pl.touk.nussknacker.engine.compile.nodecompilation.EvaluableLazyParameter -import pl.touk.nussknacker.engine.compiledgraph.BaseCompiledParameter import pl.touk.nussknacker.engine.compiledgraph.part.{CustomNodePart, ProcessPart, SinkPart} import pl.touk.nussknacker.engine.definition.component.Components import pl.touk.nussknacker.engine.definition.component.Components.ComponentDefinitionExtractionMode @@ -1353,36 +1352,35 @@ object InterpreterSpec { collector: InvocationCollectors.ServiceInvocationCollector, componentUseCase: ComponentUseCase ): Future[Any] = { - def customEvaluation( - param: BaseCompiledParameter, - exprEval: ExpressionEvaluator, - nodeId: NodeId, - jobData: JobData, - context: Context - ): String = { - val baseExpr = param.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] - val parsedExpr = baseExpr.parsed - val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] - val subValues = compositeExpr.getExpressions.toList.map { subExpr => - val evalutorContextPreparer = baseExpr.evaluationContextPreparer - val parsedSubexpression = - ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) - val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( - parsedSubexpression, - typing.Typed[String], - SpelExpressionParser.Standard, - evalutorContextPreparer - ) - val evaluator = exprEval - evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value - } - subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString - } - val lazyParam = spelTemplateParameter .extractValueUnsafe(params) .asInstanceOf[EvaluableLazyParameter[String]] - .withCustomEvaluationLogic(customEvaluation) + .withCustomEvaluationLogic { + ( + param: BaseCompiledParameter, + exprEval: BaseExpressionEvaluator, + nodeId: NodeId, + jobData: JobData, + context: Context + ) => + val baseExpr = param.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] + val parsedExpr = baseExpr.parsed + val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] + val subValues = compositeExpr.getExpressions.toList.map { subExpr => + val evalutorContextPreparer = baseExpr.evaluationContextPreparer + val parsedSubexpression = + ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) + val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( + parsedSubexpression, + typing.Typed[String], + SpelExpressionParser.Standard, + evalutorContextPreparer + ) + val evaluator = exprEval + evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value + } + subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString + } Future.successful(lazyParam.evaluate(context)) } diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidatorTest.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidatorTest.scala index 8e0d17290c4..aeb41f564a4 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidatorTest.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/definition/component/parameter/validator/ValidationExpressionParameterValidatorTest.scala @@ -4,14 +4,20 @@ import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers import org.scalatest.prop.TableDrivenPropertyChecks import org.springframework.expression.spel.standard.SpelExpressionParser -import org.springframework.expression.spel.support.StandardEvaluationContext import pl.touk.nussknacker.engine.api.parameter.ParameterName -import pl.touk.nussknacker.engine.api.{Context, JobData, MetaData, NodeId, ProcessVersion, StreamMetaData} +import pl.touk.nussknacker.engine.api.{ + CompiledExpression, + Context, + JobData, + MetaData, + NodeId, + ProcessVersion, + StreamMetaData +} import pl.touk.nussknacker.engine.definition.clazz.ClassDefinitionTestUtils import pl.touk.nussknacker.engine.definition.component.parameter.validator.TestSpelExpression.expressionConfig import pl.touk.nussknacker.engine.definition.globalvariables.ExpressionConfigDefinition import pl.touk.nussknacker.engine.expression.ExpressionEvaluator -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression import pl.touk.nussknacker.engine.graph.expression.Expression import pl.touk.nussknacker.engine.graph.expression.Expression.Language import pl.touk.nussknacker.engine.spel.internal.EvaluationContextPreparer diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala index 58cbbcc6d98..95c28090f78 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala @@ -26,10 +26,10 @@ import pl.touk.nussknacker.engine.api.process.ExpressionConfig._ import pl.touk.nussknacker.engine.api.typed.TypedMap import pl.touk.nussknacker.engine.api.typed.typing.Typed.typedListWithElementValues import pl.touk.nussknacker.engine.api.typed.typing.{Typed, _} -import pl.touk.nussknacker.engine.api.{Context, Hidden, NodeId, SpelExpressionExcludeList} +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context, Hidden, NodeId, SpelExpressionExcludeList} import pl.touk.nussknacker.engine.definition.clazz.{ClassDefinitionSet, ClassDefinitionTestUtils, JavaClassWithVarargs} import pl.touk.nussknacker.engine.dict.SimpleDictRegistry -import pl.touk.nussknacker.engine.expression.parse.{CompiledExpression, TypedExpression} +import pl.touk.nussknacker.engine.expression.parse.TypedExpression import pl.touk.nussknacker.engine.spel.SpelExpressionParseError.IllegalOperationError.{ IllegalInvocationError, IllegalProjectionSelectionError, diff --git a/utils/default-helpers/src/test/scala/pl/touk/nussknacker/engine/util/functions/BaseSpelSpec.scala b/utils/default-helpers/src/test/scala/pl/touk/nussknacker/engine/util/functions/BaseSpelSpec.scala index 8f23f0c655e..22c2bc11407 100644 --- a/utils/default-helpers/src/test/scala/pl/touk/nussknacker/engine/util/functions/BaseSpelSpec.scala +++ b/utils/default-helpers/src/test/scala/pl/touk/nussknacker/engine/util/functions/BaseSpelSpec.scala @@ -1,13 +1,12 @@ package pl.touk.nussknacker.engine.util.functions import cats.data.{NonEmptyList, Validated, ValidatedNel} -import pl.touk.nussknacker.engine.api.Context +import pl.touk.nussknacker.engine.api.{CompiledExpression, Context} import pl.touk.nussknacker.engine.api.context.ValidationContext import pl.touk.nussknacker.engine.api.generics.ExpressionParseError import pl.touk.nussknacker.engine.api.typed.typing.{Typed, TypingResult, Unknown} import pl.touk.nussknacker.engine.definition.clazz.ClassDefinitionTestUtils import pl.touk.nussknacker.engine.dict.SimpleDictRegistry -import pl.touk.nussknacker.engine.expression.parse.CompiledExpression import pl.touk.nussknacker.engine.spel.SpelExpressionParser import pl.touk.nussknacker.engine.testing.ModelDefinitionBuilder import pl.touk.nussknacker.engine.util.Implicits.RichScalaMap From 8a33110d912cf54041b72dd70ec3439516a4b138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82abek?= Date: Tue, 12 Nov 2024 12:38:03 +0100 Subject: [PATCH 4/4] wip api approach with parameter creator --- .../api/definition/NodeDependency.scala | 14 ++++- .../EvaluableLazyParameter.scala | 14 ++++- .../EvaluableLazyParameterCreator.scala | 3 +- .../nodecompilation/ParameterEvaluator.scala | 16 +++--- .../nussknacker/engine/InterpreterSpec.scala | 56 ++++++++++--------- 5 files changed, 62 insertions(+), 41 deletions(-) diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/definition/NodeDependency.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/definition/NodeDependency.scala index 673f5dd84b5..4593a8469dd 100644 --- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/definition/NodeDependency.scala +++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/definition/NodeDependency.scala @@ -1,5 +1,6 @@ package pl.touk.nussknacker.engine.api.definition +import pl.touk.nussknacker.engine.api.{BaseCompiledParameter, BaseExpressionEvaluator, Context, JobData, NodeId} import pl.touk.nussknacker.engine.api.context.transformation.{ NodeDependencyValue, OutputVariableNameValue, @@ -134,6 +135,7 @@ case class Parameter( javaOptionalParameter: Boolean, hintText: Option[String], labelOpt: Option[String], + customEvaluate: Option[(BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => AnyRef] = None ) extends NodeDependency { def copy( @@ -180,6 +182,8 @@ case class Parameter( javaOptionalParameter: Boolean = this.javaOptionalParameter, hintText: Option[String] = this.hintText, labelOpt: Option[String] = this.labelOpt, + customEvaluate: Option[(BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => AnyRef] = + this.customEvaluate ): Parameter = { new Parameter( name, @@ -194,7 +198,8 @@ case class Parameter( scalaOptionParameter, javaOptionalParameter, hintText, - labelOpt + labelOpt, + customEvaluate ) } @@ -211,7 +216,9 @@ case class Parameter( scalaOptionParameter: Boolean, javaOptionalParameter: Boolean, hintText: Option[String], - labelOpt: Option[String] + labelOpt: Option[String], + customEvaluate: Option[(BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => AnyRef] = + None ): Parameter = { new Parameter( name, @@ -226,7 +233,8 @@ case class Parameter( scalaOptionParameter, javaOptionalParameter, hintText, - labelOpt + labelOpt, + customEvaluate ) } diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala index 2785cba3ca0..e98a2e52c32 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameter.scala @@ -16,16 +16,24 @@ class EvaluableLazyParameter[T <: AnyRef]( nodeId: NodeId, val jobData: JobData, override val returnType: TypingResult, - val customEvaluate: Option[(BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T] = None + val customEvaluate: Option[(BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T] ) extends CustomLazyParamterWithCustomizableEvaluationLogic[T] { def this( compiledParameter: CompiledParameter, expressionEvaluator: ExpressionEvaluator, nodeId: NodeId, - jobData: JobData + jobData: JobData, + customEvaluate: Option[(BaseCompiledParameter, ExpressionEvaluator, NodeId, JobData, Context) => T] = None ) = - this(compiledParameter, expressionEvaluator, nodeId, jobData, compiledParameter.typingInfo.typingResult) + this( + compiledParameter, + expressionEvaluator, + nodeId, + jobData, + compiledParameter.typingInfo.typingResult, + customEvaluate + ) override val evaluate: Evaluate[T] = { ctx: Context => customEvaluate diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala index d66e2598029..c9efb7ec351 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/EvaluableLazyParameterCreator.scala @@ -45,7 +45,8 @@ final class EvaluableLazyParameterCreator[T <: AnyRef]( deps.expressionEvaluator, nodeId, deps.jobData, - returnType + returnType, + None ) } diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/ParameterEvaluator.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/ParameterEvaluator.scala index 76616515702..ae1ccb26cdf 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/ParameterEvaluator.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/compile/nodecompilation/ParameterEvaluator.scala @@ -49,7 +49,7 @@ class ParameterEvaluator( .toMap } - private def prepareLazyParameter[T](param: TypedParameter, definition: ParameterDef)( + private def prepareLazyParameter(param: TypedParameter, definition: ParameterDef)( implicit jobData: JobData, nodeId: NodeId, lazyParameterCreationStrategy: LazyParameterCreationStrategy @@ -88,19 +88,21 @@ class ParameterEvaluator( } } - private def prepareLazyParameterExpression[T](definition: ParameterDef, exprValue: TypedExpression)( + private def prepareLazyParameterExpression(definition: ParameterDef, exprValue: TypedExpression)( implicit jobData: JobData, nodeId: NodeId, lazyParameterCreationStrategy: LazyParameterCreationStrategy - ): LazyParameter[Nothing] = { + ): LazyParameter[AnyRef] = { lazyParameterCreationStrategy match { case EvaluableLazyParameterStrategy => new EvaluableLazyParameter( - CompiledParameter(exprValue, definition), - runtimeExpressionEvaluator, - nodeId, - jobData + compiledParameter = CompiledParameter(exprValue, definition), + expressionEvaluator = runtimeExpressionEvaluator, + nodeId = nodeId, + jobData = jobData, + customEvaluate = definition.customEvaluate ) + // TODO: add customEvaluate here case PostponedEvaluatorLazyParameterStrategy => new EvaluableLazyParameterCreator( nodeId, diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala index 86a3ea3dabf..c262ccb7540 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/InterpreterSpec.scala @@ -1315,12 +1315,40 @@ object InterpreterSpec { object SpelTemplateServiceWithAstOperation extends EagerService with SingleInputDynamicComponent[ServiceInvoker] { + val eval: (BaseCompiledParameter, BaseExpressionEvaluator, NodeId, JobData, Context) => String = { + ( + param: BaseCompiledParameter, + exprEval: BaseExpressionEvaluator, + nodeId: NodeId, + jobData: JobData, + context: Context + ) => + val baseExpr = param.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] + val parsedExpr = baseExpr.parsed + val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] + val subValues = compositeExpr.getExpressions.toList.map { subExpr => + val evalutorContextPreparer = baseExpr.evaluationContextPreparer + val parsedSubexpression = + ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) + val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( + parsedSubexpression, + typing.Typed[String], + SpelExpressionParser.Standard, + evalutorContextPreparer + ) + val evaluator = exprEval + evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value + } + subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString + } + private val spelTemplateParameter = ParameterDeclaration .lazyMandatory[String](ParameterName("template")) .withCreator(modify = _.copy( editor = Some(SpelTemplateParameterEditor), - defaultValue = Some(Expression.spelTemplate("")) + defaultValue = Some(Expression.spelTemplate("")), + customEvaluate = Some(eval) ) ) @@ -1355,32 +1383,6 @@ object InterpreterSpec { val lazyParam = spelTemplateParameter .extractValueUnsafe(params) .asInstanceOf[EvaluableLazyParameter[String]] - .withCustomEvaluationLogic { - ( - param: BaseCompiledParameter, - exprEval: BaseExpressionEvaluator, - nodeId: NodeId, - jobData: JobData, - context: Context - ) => - val baseExpr = param.expression.asInstanceOf[pl.touk.nussknacker.engine.spel.SpelExpression] - val parsedExpr = baseExpr.parsed - val compositeExpr = parsedExpr.parsed.asInstanceOf[CompositeStringExpression] - val subValues = compositeExpr.getExpressions.toList.map { subExpr => - val evalutorContextPreparer = baseExpr.evaluationContextPreparer - val parsedSubexpression = - ParsedSpelExpression.apply(subExpr.getExpressionString, parsedExpr.parser, subExpr) - val compiledExpr = new pl.touk.nussknacker.engine.spel.SpelExpression( - parsedSubexpression, - typing.Typed[String], - SpelExpressionParser.Standard, - evalutorContextPreparer - ) - val evaluator = exprEval - evaluator.evaluate[String](compiledExpr, "subexpression", "irrelevant", context)(jobData).value - } - subValues.zipWithIndex.map { case (v, i) => s"value-$i" -> v }.toMap.toString - } Future.successful(lazyParam.evaluate(context)) }