diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/context/PackageableElementType.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/context/PackageableElementType.java index 3be6d626f0f..e5bd1d06827 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/context/PackageableElementType.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-protocol-pure/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/context/PackageableElementType.java @@ -24,6 +24,7 @@ public enum PackageableElementType FUNCTION, STORE, RUNTIME, + BINDING, MAPPING, SERVICE, PERSISTENCE, diff --git a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/routing.pure b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/routing.pure index e756af5bbc9..5ad8c440348 100644 --- a/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/routing.pure +++ b/legend-engine-core/legend-engine-core-pure/legend-engine-pure-code-compiled-core/src/main/resources/core/pure/router/store/routing.pure @@ -365,7 +365,11 @@ function meta::pure::router::store::routing::specializedFunctionExpressionRoute $r->reactivate($inScopeVars);, i:InstanceValue[1] |$i.values])); let fromMapping = $resolvedParameters->at(0)->cast(@Mapping); - let fromRuntime = $resolvedParameters->at(1)->cast(@Runtime); + let fromRuntime = $resolvedParameters->at(1) + ->match([ + r:Runtime[1]| $r, + fe: FunctionExpression[1] | $fe->meta::pure::router::preeval::preval($inScopeVars, $extensions, $debug)->reactivate($inScopeVars) + ])->toOne()->cast(@Runtime); let fromExecutionContext = if($resolvedParameters->size() == 3, | $resolvedParameters->at(2)->cast(@meta::pure::runtime::ExecutionContext), | $executionContext); let currentRoutingStrategy = $state.routingStrategy; diff --git a/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/generation/generation.pure b/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/generation/generation.pure index dda6942d6d2..729ca6a0d47 100644 --- a/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/generation/generation.pure +++ b/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/generation/generation.pure @@ -43,8 +43,8 @@ function meta::external::function::activator::hostedService::validator::validate let params = $h.function->functionType().parameters->evaluateAndDeactivate(); let oneParams = $params->filter(p|$p->deactivate().multiplicity == PureOne); let nonOneParams = $params->filter(p|!$p->deactivate().multiplicity == PureOne); - //all [1] params in pattern - $oneParams->map(p| assert($pattern->contains('{'+$p.name+'}'), 'Parameter '+$p.name+' with multiplicty [1] must be in service pattern.')); + //all [1] params in pattern TODO + //$oneParams->map(p| assert($pattern->contains('{'+$p.name+'}'), 'Parameter "'+$p.name+'"" with multiplicty [1] must be in service pattern.')); //all non [1] params not in pattern $nonOneParams->map(p| assert($pattern->contains('{'+$p.name+'}'), 'Parameter '+$p.name+' with multiplicty not [1] cannot be in service pattern.')); //Service has a base pattern @@ -154,41 +154,27 @@ function meta::external::function::activator::hostedService::generation::isMulti function meta::external::function::activator::hostedService::generation::getEnvironmentkey(h:HostedService[1] ):String[1] { let func = $h.function; - let valueSpecification = $func->cast(@ConcreteFunctionDefinition).expressionSequence->cast(@SimpleFunctionExpression)->evaluateAndDeactivate().parametersValues - ->filter(x| $x.genericType.rawType->toOne()->in([ExecutionEnvironmentInstance, SingleExecutionParameters])); - //today we'll get a function cos we're in the pure IDE. from syudio we should be getting a packageable element so the need for the inner match will be eliminated - $valueSpecification->match([ - s:SimpleFunctionExpression[1]| $s->evaluateAndDeactivate().parametersValues->filter(x| $x.genericType.rawType->toOne()==String)->map(pv| - $pv->match([ - v:VariableExpression[1]| $v.name; - ]); - )->toOne();, - a:Any[1]| fail('unexpected type'); 'any'; - ]) ; + let exprs = meta::pure::functions::meta::findExpressionsForFunctionInFunctionDefinition($func->cast(@ConcreteFunctionDefinition),multiExecFuncs()); + let pv = $exprs->first()->toOne('Found no multiExecution expressions')->cast(@SimpleFunctionExpression).parametersValues->at(1); + assert($pv->instanceOf(VariableExpression)); + $pv->cast(@VariableExpression).name; } function meta::external::function::activator::hostedService::generation::getExecutionParam(func: PackageableFunction[1]):PackageableElement[*] +{ + let exprs = meta::pure::functions::meta::findExpressionsForFunctionInFunctionDefinition($func->cast(@ConcreteFunctionDefinition),multiExecFuncs()); + let elements = $exprs ->map(e| $e.parametersValues->at(0)->reactivate()); + $elements->cast(@PackageableElement); +} + +function meta::external::function::activator::hostedService::generation::multiExecFuncs(): Function[*] { - let valueSpecification = $func->cast(@ConcreteFunctionDefinition).expressionSequence->cast(@SimpleFunctionExpression)->evaluateAndDeactivate().parametersValues - ->filter(x| $x.genericType.rawType->toOne()->in([ExecutionEnvironmentInstance, SingleExecutionParameters, DataSpace, DataSpaceExecutionContext])); - //today we'll get a function cos we're in the pure IDE. from syudio we should be getting a packageable element so the need for the inner match will be eliminated - if($valueSpecification->isNotEmpty(), - |$valueSpecification->match([ - s:SimpleFunctionExpression[1]|if($s.func->in([get_ExecutionEnvironmentInstance_1__String_1__SingleExecutionParameters_1_, get_DataSpace_1__String_1__DataSpaceExecutionContext_1_ ]), - |$s->evaluateAndDeactivate().parametersValues->filter(x| $x.genericType.rawType->toOne()->in([ExecutionEnvironmentInstance, DataSpace]))->map(pv| - $pv->match([ - s:SimpleFunctionExpression[1]| $s->reactivate()->toOne();, - i:InstanceValue[1]| $i.values->toOne();, - e: ExecutionEnvironmentInstance[1]| $e - ]));, - |$s->reactivate()->toOne() - );, - e: ExecutionEnvironmentInstance[1]| $e, - d: DataSpace[1] | $d, - a:Any[1]| fail('unexpected type'); $a; - ]), - |[])->cast(@PackageableElement); + [ + getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_, + get_ExecutionEnvironmentInstance_1__String_1__SingleExecutionParameters_1_, + get_DataSpace_1__String_1__DataSpaceExecutionContext_1_ + ] } function meta::external::function::activator::hostedService::generation::rebuildServiceUsingFlattenedParams(h:HostedService[1] ):Pair[*] @@ -196,12 +182,7 @@ function meta::external::function::activator::hostedService::generation::rebuild let execParam = getExecutionParam($h.function); $execParam->match([ e : ExecutionEnvironmentInstance[*] | assert($e->size()== 1, 'Found too many/not enough execution environment instances. Size='+ $e->size()->toString()); - $e.executionParameters->map( - p | assert($p->instanceOf(SingleExecutionParameters),'Only handles singleExecutionParams'); - let newFunc = rebuildFromExpression($h.function, $p->cast(@SingleExecutionParameters).mapping, $p->cast(@SingleExecutionParameters).runtime); - let newHostedService = ^$h(function=$newFunc); - pair($p->cast(@SingleExecutionParameters).key, $newHostedService); - );, + rebuildFromExpressionForExecutionEnv($h, $e->cast(@ExecutionEnvironmentInstance)->toOne());, d : DataSpace[*] | assert($d->size() == 1, 'Found too many/ not enough dataSpaces, Size =' + $d->size()->toString()); $d.executionContexts->map( ec | let newFunc = rebuildFromExpression($h.function, $ec.mapping, $ec.defaultRuntime.runtimeValue); @@ -212,6 +193,67 @@ function meta::external::function::activator::hostedService::generation::rebuild ]); } +function meta::external::function::activator::hostedService::generation::rebuildFromExpressionForExecutionEnv(h:HostedService[1], e:ExecutionEnvironmentInstance[1]): Pair[*] +{ + + let shouldMergeRuntime = meta::pure::functions::meta::findExpressionsForFunctionInFunctionDefinition($h.function->cast(@ConcreteFunctionDefinition),getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_)->isNotEmpty(); + if($shouldMergeRuntime, + |$e.executionParameters->map( + p | assert($p->instanceOf(SingleExecutionParameters),'Only handles singleExecutionParams'); + let newFunc = rewriteUsingRuntimeComponents($h.function->cast(@ConcreteFunctionDefinition), $p->cast(@SingleExecutionParameters)); + let newHostedService = ^$h(function=$newFunc); + pair($p->cast(@SingleExecutionParameters).key, $newHostedService); + ), + | + $e.executionParameters->map( + p | assert($p->instanceOf(SingleExecutionParameters),'Only handles singleExecutionParams'); + let newFunc = rebuildFromExpression($h.function, $p->cast(@SingleExecutionParameters).mapping, $p->cast(@SingleExecutionParameters).runtime->toOne()); + let newHostedService = ^$h(function=$newFunc); + pair($p->cast(@SingleExecutionParameters).key, $newHostedService); + ) + ); +} + +function meta::external::function::activator::hostedService::generation::rewriteUsingRuntimeComponents(originalFunction:ConcreteFunctionDefinition[1], execParam :meta::legend::service::metamodel::SingleExecutionParameters[1] ): ConcreteFunctionDefinition[1] +{ + let getWithRuntime = meta::pure::functions::meta::findExpressionsForFunctionInFunctionDefinition($originalFunction->cast(@ConcreteFunctionDefinition),getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_); + let runtimeComp = $execParam.runtimeComponents; + let getWithModelQueryExpression = ^SimpleFunctionExpression(genericType=^GenericType(rawType = Runtime), + multiplicity=PureOne, + func= meta::core::runtime::getRuntimeWithModelQueryConnection_Class_1__Binding_1__String_1__Runtime_1_, + importGroup = system::imports::coreImport, + parametersValues = [ + ^InstanceValue(genericType=^GenericType(rawType = Class),multiplicity=PureOne, values = [$runtimeComp.class]), + ^InstanceValue(genericType=^GenericType(rawType = Binding),multiplicity=PureOne, values = [$runtimeComp.binding]), + $getWithRuntime->cast(@SimpleFunctionExpression).parametersValues->last()->toOne()->cast(@VariableExpression) + ] + ); + let mergeRuntimeExpression = ^SimpleFunctionExpression(genericType=^GenericType(rawType = Runtime), + multiplicity=PureOne, + func= meta::core::runtime::mergeRuntimes_Any_$1_MANY$__Runtime_1_, + importGroup = system::imports::coreImport, + parametersValues = [ + ^InstanceValue(genericType=^GenericType(rawType = Any),multiplicity=ZeroMany, values = [$getWithModelQueryExpression , $runtimeComp.runtime->toOne()]) + ] + ); + let serializeExpr =$originalFunction.expressionSequence->toOne()->cast(@SimpleFunctionExpression); + let fromExpr = $serializeExpr->evaluateAndDeactivate().parametersValues; + let newFrom = ^SimpleFunctionExpression( + importGroup = system::imports::coreImport, + functionName = 'from', + func = meta::pure::mapping::from_T_m__Mapping_1__Runtime_1__T_m_, + genericType = $fromExpr->at(0).genericType, + multiplicity = PureOne, + parametersValues = $fromExpr->at(0)->cast(@SimpleFunctionExpression)->evaluateAndDeactivate().parametersValues->at(0) + ->concatenate(^InstanceValue(genericType =^GenericType(rawType = Mapping), multiplicity = PureOne, values = $execParam->at(0)->cast(@meta::legend::service::metamodel::SingleExecutionParameters).mapping)) + ->concatenate(^InstanceValue(genericType =^GenericType(rawType = Runtime), multiplicity = PureOne, values = $mergeRuntimeExpression)) + )->evaluateAndDeactivate(); + ^$originalFunction( + expressionSequence = ^$serializeExpr(parametersValues = $newFrom->concatenate($fromExpr->tail())) + ); + +} + function meta::external::function::activator::hostedService::generation::rebuildFromExpression(func: PackageableFunction[1], mapping: Mapping[1], runtime: Runtime[1]): PackageableFunction[1] { let fromExpression = ^SimpleFunctionExpression( diff --git a/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/showcase/showcaseServices.pure b/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/showcase/showcaseServices.pure index 96979c0be09..4ac222be8bd 100644 --- a/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/showcase/showcaseServices.pure +++ b/legend-engine-xts-hostedService/legend-engine-xt-hostedService-pure/src/main/resources/core_hostedservice/showcase/showcaseServices.pure @@ -1,3 +1,7 @@ +import meta::legend::service::metamodel::*; +import meta::legend::service::*; +import meta::external::store::model::*; +import meta::core::runtime::*; import meta::external::function::activator::*; import meta::external::function::activator::hostedService::generation::*; import meta::external::format::shared::functions::*; @@ -76,7 +80,77 @@ function meta::external::function::activator::hostedService::tests::simplefuncti } +function meta::external::function::activator::hostedService::tests::simpleServiceMergeRuntime():Any[*] +{ + let extensions = meta::external::format::shared::externalFormatExtension()->concatenate(meta::relational::extension::relationalExtensions()); + + let service = ^HostedService + ( + pattern = '/service/{key}/{data}', + ownership = ^UserList(users = ['debelp', 'harted']), + documentation = 'bla bla', + autoActivateUpdates = true, + function= meta::external::function::activator::hostedService::tests::functionWithRuntimeComponents_String_1__String_1__String_1_ + ); + $service->meta::external::function::activator::hostedService::generation::getEnvironmentkey()->println(); + //validate + $service->meta::external::function::activator::hostedService::validator::validateService(); + $service-> meta::external::function::activator::hostedService::generation::isMultiEenvironmentService()->println(); //fail(); + //printlnPlan + $service->rebuildServiceUsingFlattenedParams().second->map(s|$s->meta::external::function::activator::hostedService::generation::printPlan()); +} + +function meta::external::function::activator::hostedService::tests::functionWithRuntimeComponents(key:String[1], data:String[1]):String[1] +{ + meta::external::format::shared::executionPlan::tests::TargetPerson.all() + ->graphFetch(#{meta::external::format::shared::executionPlan::tests::TargetPerson{fullName}}#) + ->from(meta::external::function::activator::hostedService::tests::execEnvInstance()->getWithRuntime($key, $data)) + ->serialize( #{meta::external::format::shared::executionPlan::tests::TargetPerson{fullName}}#); +} + + +function meta::external::function::activator::hostedService::tests::testBindingX(): Binding[1] +{ + ^Binding( + name = 'MyBindingMo', + package = meta::external::format::shared::executionPlan::tests::_Person.package, + contentType = 'application/x.flatdata', + modelUnit = ^ModelUnit() + ); +} + +function meta::external::function::activator::hostedService::tests::execEnvInstance():meta::legend::service::metamodel::ExecutionEnvironmentInstance[1] +{ + let runtime2 = ^meta::core::runtime::Runtime( + connectionStores = ^ConnectionStore( + element=^ModelStore(), + connection=^ModelChainConnection(mappings = meta::external::format::shared::executionPlan::tests::M2MMapping1)) + ); + ^meta::legend::service::metamodel::ExecutionEnvironmentInstance( + executionParameters = [ + ^meta::legend::service::metamodel::SingleExecutionParameters + ( + key = 'UAT', + mapping = meta::external::format::shared::executionPlan::tests::M2MMapping, + runtimeComponents = ^meta::legend::service::metamodel::RuntimeComponents( + runtime = $runtime2, + class = meta::external::format::shared::executionPlan::tests::_Person, + binding = meta::external::function::activator::hostedService::tests::testBindingX() + ) + ), + ^meta::legend::service::metamodel::SingleExecutionParameters + ( + key = 'PROD', + mapping = meta::external::format::shared::executionPlan::tests::M2MMapping, + runtimeComponents = ^meta::legend::service::metamodel::RuntimeComponents( + runtime = $runtime2, + class = meta::external::format::shared::executionPlan::tests::_Person, + binding = meta::external::function::activator::hostedService::tests::testBindingX() + ) + ) + ]); +} // relational with single execution param @@ -104,20 +178,23 @@ function meta::external::function::activator::hostedService::tests::simpleRelati runtime= meta::external::function::activator::hostedService::tests::testRuntime(dbInc) )) } -// Simple relational with Execution env instance +//Simple relational with Execution env instance function meta::external::function::activator::hostedService::tests::simpleServiceTDSShowcase4():Any[*] { let service = ^HostedService ( - pattern = '/service', + pattern = '/service/{env}', ownership = ^UserList(users = ['debelp', 'harted']), documentation = 'bla bla', autoActivateUpdates = true, - function= meta::external::function::activator::hostedService::tests::simpleRelationalfunctionWithExecutionEnvInstance__TabularDataSet_1_ + function= meta::external::function::activator::hostedService::tests::simpleRelationalfunctionWithExecutionEnvInstance_String_1__TabularDataSet_1_ ); //isMulti print('isMultiExecService:'); $service-> meta::external::function::activator::hostedService::generation::isMultiEenvironmentService()->println(); + + $service->meta::external::function::activator::hostedService::generation::getEnvironmentkey()->println(); + //validate $service->meta::external::function::activator::hostedService::validator::validateService(); //printlnPlan @@ -125,12 +202,6 @@ function meta::external::function::activator::hostedService::tests::simpleServic } -function meta::external::function::activator::hostedService::tests::simpleRelationalfunctionWithExecutionEnvInstance():TabularDataSet[1] -{ - PersonX.all()->filter(p|$p.firstName == 'haha')->project([col(p|$p.firstName, 'firstName'), col(p|$p.lastName, 'lastName')]) - ->from(meta::external::function::activator::hostedService::tests::TestExecutionEnviroment()); -} - // Simple relational with Execution env instance function meta::external::function::activator::hostedService::tests::simpleServiceTDSShowcase4X():Any[*] { @@ -163,12 +234,12 @@ function meta::external::function::activator::hostedService::tests::simpleServic { let service = ^HostedService ( - pattern = '/service', + pattern = '/service/{env}', ownership = ^UserList(users = ['debelp', 'harted']), binding = ^Binding(name='serviceBinding', contentType = 'application/json',modelUnit = meta::pure::model::unit::newModelUnit()->include(PersonX)), documentation = 'bla bla', autoActivateUpdates = true, - function= meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance__PersonX_MANY_ + function= meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance_String_1__PersonX_MANY_ ); //validate @@ -182,12 +253,12 @@ function meta::external::function::activator::hostedService::tests::simpleServic { let service = ^HostedService ( - pattern = '/service', + pattern = '/service/{env}', ownership = ^UserList(users = ['debelp', 'harted']), contentType = 'application/json', documentation = 'bla bla', autoActivateUpdates = true, - function= meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance__PersonX_MANY_ + function= meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance_String_1__PersonX_MANY_ ); //isMulti print('isMultiExecService:'); @@ -199,9 +270,9 @@ $service-> meta::external::function::activator::hostedService::generation::isMul } -function meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance():PersonX[*] +function meta::external::function::activator::hostedService::tests::simplegraphFetchfunctionWithExecutionEnvInstance(env:String[1]):PersonX[*] { - PersonX.all()->graphFetch(#{ PersonX {firstName} } #)->from(meta::external::function::activator::hostedService::tests::TestExecutionEnviroment()); + PersonX.all()->graphFetch(#{ PersonX {firstName} } #)->from(meta::external::function::activator::hostedService::tests::TestExecutionEnviroment()->get($env)); } function meta::external::function::activator::hostedService::tests::TestExecutionEnviroment(): meta::legend::service::metamodel::ExecutionEnvironmentInstance[1] @@ -214,6 +285,7 @@ function meta::external::function::activator::hostedService::tests::TestExecutio key = 'UAT', mapping = simpleRelationalMapping, runtime = meta::external::function::activator::hostedService::tests::testRuntime(dbInc) + ), ^meta::legend::service::metamodel::SingleExecutionParameters ( diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/pom.xml b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/pom.xml index ba19eb6d851..9d5b9621a99 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/pom.xml +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/pom.xml @@ -71,6 +71,11 @@ legend-engine-xt-data-space-pure-metamodel ${project.version} + + org.finos.legend.engine + legend-engine-xt-json-pure + ${project.version} + @@ -119,6 +124,11 @@ legend-engine-xt-data-space-pure-metamodel ${project.version} + + org.finos.legend.engine + legend-engine-xt-json-pure + ${project.version} + @@ -131,6 +141,7 @@ org.finos.legend.engine:legend-engine-xt-data-space-pure-metamodel:jar + org.finos.legend.engine:legend-engine-xt-json-pure:jar @@ -180,6 +191,10 @@ org.finos.legend.engine legend-engine-xt-data-space-pure-metamodel + + org.finos.legend.engine + legend-engine-xt-json-pure + org.finos.legend.pure legend-pure-m2-dsl-mapping-pure diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service.definition.json b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service.definition.json index 0bbee9979f4..18a2329740c 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service.definition.json +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service.definition.json @@ -8,6 +8,7 @@ "platform_dsl_store", "core_functions_unclassified", "core_data_space_metamodel", + "core_external_format_json", "core" ] } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/extension.pure b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/extension.pure index ee6e257bbcb..3529ca33cc9 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/extension.pure +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/extension.pure @@ -30,7 +30,7 @@ function meta::legend::service::serviceExtension() : Extension[1] i:InstanceValue[1] |$i.values])); let fromSingleExecParams = $resolvedParameters->at(0)->cast(@meta::legend::service::metamodel::SingleExecutionParameters); let fromMapping = $fromSingleExecParams.mapping; - let fromRuntime = $fromSingleExecParams.runtime; + let fromRuntime = $fromSingleExecParams.runtime->toOne(); let currentRoutingStrategy = $state.routingStrategy; let newRoutingStrategy = getRoutingStrategyFromMappingAndRuntime($currentRoutingStrategy, $fromMapping, $fromRuntime, $extensions); diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/helperFunctions.pure b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/helperFunctions.pure index ed7b5b1ef36..3b05ed6eedd 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/helperFunctions.pure +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/helperFunctions.pure @@ -31,6 +31,16 @@ function meta::legend::service::get(execEnv: ExecutionEnvironmentInstance[1], ke $singleExecParam->at(0); } +function meta::legend::service::getWithRuntime(execEnv: ExecutionEnvironmentInstance[1], key:String[1], data:String[1]): SingleExecutionParameters[1] +{ + assert($execEnv.executionParameters->at(0)->instanceOf(SingleExecutionParameters),| 'Please provide the subkey using function ->get(masterKey,subKey)'); + let singleExecParam = $execEnv.executionParameters->cast(@SingleExecutionParameters)->filter(x| $x.key == $key->toOne()); + assert($singleExecParam->isNotEmpty(),| 'The key value provided is not present in the execution environment'); + let r = $singleExecParam->toOne().rebuildRuntime($data); + let param = $singleExecParam->toOne(); + ^$param(runtime = $r); +} + function meta::legend::service::get(execEnv: ExecutionEnvironmentInstance[1], masterKey:String[1], subKey:String[1]):SingleExecutionParameters[1] { assert($execEnv.executionParameters->at(0)->instanceOf(MultiExecutionParameters),| 'Please use the function ->get(key)'); @@ -44,7 +54,8 @@ function meta::legend::service::get(execEnv: ExecutionEnvironmentInstance[1], ma function meta::legend::service::getKeyFromFunctionDefinition(func: FunctionDefinition[1]):String[1] { let getExprList = $func->findExpressionsForFunctionInFunctionDefinition([meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__SingleExecutionParameters_1_, - meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_]); + meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_, + meta::legend::service::getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_]); $getExprList->evaluateAndDeactivate()->map(exp | $exp.parametersValues->at(1)->evaluateAndDeactivate()->cast(@VariableExpression).name)->at(0)->cast(@String); } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/metamodel.pure b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/metamodel.pure index a25ab5db551..1406afa7923 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/metamodel.pure +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service-pure/src/main/resources/core_service/service/metamodel.pure @@ -103,12 +103,31 @@ Class meta::legend::service::metamodel::ExecutionParameters } Class meta::legend::service::metamodel::SingleExecutionParameters extends ExecutionParameters +[ + runtimeOrFunction: assert($this.runtime->concatenate($this.runtimeComponents)->size() == 1, 'Must specify either a runtime or a runtime function') +] { key : String[1]; mapping : Mapping[1]; - runtime : Runtime[1]; + runtime : Runtime[0..1]; + runtimeComponents : meta::legend::service::metamodel::RuntimeComponents[0..1]; + + rebuildRuntime(data:String[1]) + { + assert($this.runtimeComponents->isNotEmpty(), 'Must exist'); + let r = $this.runtimeComponents->toOne(); + mergeRuntimes([getRuntimeWithModelQueryConnection($r.class, $r.binding, $data), $r.runtime]); + }:Runtime[1]; + } +Class meta::legend::service::metamodel::RuntimeComponents +{ + runtime : Runtime[1]; + binding: meta::external::format::shared::binding::Binding[1]; + class: Class[1]; + +} Class meta::legend::service::metamodel::MultiExecutionParameters extends ExecutionParameters { masterKey: String[1]; diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/pom.xml b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/pom.xml index 0437d26978c..6eb3178033d 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/pom.xml +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/pom.xml @@ -108,6 +108,10 @@ org.finos.legend.engine legend-engine-protocol + + org.finos.legend.engine + legend-engine-pure-platform-java + org.finos.legend.engine legend-engine-protocol-pure @@ -187,10 +191,19 @@ legend-engine-xt-json-model test + + org.finos.legend.engine + legend-engine-xt-json-pure + test + org.finos.legend.engine legend-engine-xt-data-space-protocol + + org.finos.legend.engine + legend-engine-pure-platform-java + \ No newline at end of file diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceLexerGrammar.g4 b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceLexerGrammar.g4 index ff3b2329de4..a9f98ef00b3 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceLexerGrammar.g4 +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceLexerGrammar.g4 @@ -29,7 +29,9 @@ SERVICE_FUNCTION: 'query'; SERVICE_EXECUTION_KEY: 'key'; SERVICE_MAPPING: 'mapping'; SERVICE_RUNTIME: 'runtime'; - +SERVICE_COMPONENT_BINDING: 'binding'; +SERVICE_COMPONENT_CLASS: 'class'; +SERVICE_RUNTIME_COMPONENTS: 'runtimeComponents'; SERVICE_TEST_SUITES: 'testSuites'; SERVICE_TEST_DATA: 'data'; SERVICE_TEST_CONNECTION_DATA: 'connections'; diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceParserGrammar.g4 b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceParserGrammar.g4 index c8de15b557d..fda1e4bfb1b 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceParserGrammar.g4 +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/ServiceParserGrammar.g4 @@ -21,7 +21,7 @@ identifier: VALID_STRING | STRING | SERVICE_TEST_SUITES | SERVICE_TEST_DATA | SERVICE_TEST_CONNECTION_DATA | SERVICE_TEST_TESTS | SERVICE_TEST_ASSERTS | SERVICE_TEST_PARAMETERS | SERVICE_TEST_SERIALIZATION_FORMAT | SERVICE_TEST | PARAM_GROUP | ASSERT_FOR_KEYS | SERVICE_POST_VALIDATION | SERVICE_POST_VALIDATION_DESCRIPTION | SERVICE_POST_VALIDATION_PARAMETERS | SERVICE_POST_VALIDATION_ASSERTIONS - | EXEC_ENV + | EXEC_ENV | SERVICE_COMPONENT_BINDING | SERVICE_COMPONENT_CLASS | SERVICE_RUNTIME_COMPONENTS ; @@ -269,8 +269,20 @@ execParams: singleExecEnv | multiExecEnv singleExecEnv: identifier COLON BRACE_OPEN serviceMapping - serviceRuntime + (serviceRuntime | serviceRuntimeComponents) * BRACE_CLOSE ; multiExecEnv: identifier COLON BRACKET_OPEN singleExecEnv (COMMA singleExecEnv)* BRACKET_CLOSE -; \ No newline at end of file +; + +serviceRuntimeComponents: SERVICE_RUNTIME_COMPONENTS COLON BRACE_OPEN (componentRuntime | componentClass| componentBinding )* BRACE_CLOSE +; + +componentRuntime: SERVICE_RUNTIME COLON runtimePointer +; + +componentClass: SERVICE_COMPONENT_CLASS COLON qualifiedName SEMI_COLON +; + +componentBinding: SERVICE_COMPONENT_BINDING COLON qualifiedName SEMI_COLON +; diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/HelperServiceBuilder.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/HelperServiceBuilder.java index 13a752c2a73..eaf12ded7ce 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/HelperServiceBuilder.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/HelperServiceBuilder.java @@ -27,9 +27,11 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.ParameterValue; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.EngineRuntime; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.*; +import org.finos.legend.engine.shared.core.operational.Assert; import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; import org.finos.legend.pure.generated.*; import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.LambdaFunction; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.InstanceValue; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.VariableExpression; @@ -283,13 +285,42 @@ public static Root_meta_legend_service_metamodel_ExecutionParameters processExec { SingleExecutionParameters execParams = (SingleExecutionParameters) params; Mapping mapping = context.resolveMapping(execParams.mapping, execParams.mappingSourceInformation); - inferEmbeddedRuntimeMapping(execParams.runtime, execParams.mapping); - Root_meta_core_runtime_Runtime runtime = HelperRuntimeBuilder.buildPureRuntime(execParams.runtime, context); - HelperRuntimeBuilder.checkRuntimeMappingCoverage(runtime, Lists.fixedSize.of(mapping), context, execParams.runtime.sourceInformation); - return new Root_meta_legend_service_metamodel_SingleExecutionParameters_Impl("", null, context.pureModel.getClass("meta::legend::service::metamodel::SingleExecutionParameters")) + Root_meta_legend_service_metamodel_SingleExecutionParameters param = new Root_meta_legend_service_metamodel_SingleExecutionParameters_Impl("", null, context.pureModel.getClass("meta::legend::service::metamodel::SingleExecutionParameters")) ._key(execParams.key) - ._mapping(mapping) - ._runtime(runtime); + ._mapping(mapping); + if (execParams.runtime != null && execParams.runtimeComponents != null) + { + throw new EngineException("Cannot use both runtime and runtime components", execParams.sourceInformation, EngineErrorType.COMPILATION); + } + if (execParams.runtime != null) + { + inferEmbeddedRuntimeMapping(execParams.runtime, execParams.mapping); + Root_meta_core_runtime_Runtime runtime = HelperRuntimeBuilder.buildPureRuntime(execParams.runtime, context); + HelperRuntimeBuilder.checkRuntimeMappingCoverage(runtime, Lists.fixedSize.of(mapping), context, execParams.runtime.sourceInformation); + param._runtime(runtime); + } + else + { + Assert.assertTrue(execParams.runtimeComponents != null, () -> "Runtime components must be specified when runtime isn't"); + RuntimeComponents c = execParams.runtimeComponents; + PackageableElement binding = null; + try + { + binding = platform_pure_essential_meta_graph_pathToElement.Root_meta_pure_functions_meta_pathToElement_String_1__PackageableElement_1_(c.binding.path, context.getExecutionSupport()); + Assert.assertTrue(binding instanceof Root_meta_external_format_shared_binding_Binding, () -> "provide a valid Binding"); + } + catch (Exception e) + { + throw new EngineException("Cannot resolve binding. Error: " + e.getMessage(), execParams.runtimeComponents.sourceInformation, EngineErrorType.COMPILATION); + } + + Root_meta_legend_service_metamodel_RuntimeComponents components = new Root_meta_legend_service_metamodel_RuntimeComponents_Impl("") + ._runtime(HelperRuntimeBuilder.buildPureRuntime(c.runtime, context)) + ._class(context.resolveClass(c.clazz.path)) + ._binding((Root_meta_external_format_shared_binding_Binding)binding); + param._runtimeComponents(components); + } + return param; } else if (params instanceof MultiExecutionParameters) { diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/ServiceCompilerExtensionImpl.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/ServiceCompilerExtensionImpl.java index cd20748fd21..4c6e15a172b 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/ServiceCompilerExtensionImpl.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/compiler/toPureGraph/ServiceCompilerExtensionImpl.java @@ -38,6 +38,7 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.data.DataElement; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.dataSpace.DataSpace; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.Binding; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.PackageableRuntime; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.ExecutionEnvironmentInstance; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.Service; @@ -200,7 +201,7 @@ public Iterable> getExtraProcessors() }), Processor.newProcessor( ExecutionEnvironmentInstance.class, - Lists.fixedSize.with(PackageableConnection.class, PackageableRuntime.class), + Lists.fixedSize.with(PackageableConnection.class, PackageableRuntime.class, Binding.class), (execEnv, context) -> new Root_meta_legend_service_metamodel_ExecutionEnvironmentInstance_Impl(execEnv.name, null, context.pureModel.getClass("meta::legend::service::metamodel::ExecutionEnvironmentInstance")) ._name(execEnv.name), (execEnv, context) -> @@ -359,7 +360,8 @@ public List>> getExt org.eclipse.collections.api.factory.Lists.mutable.with( new FunctionHandlerDispatchBuilderInfo("meta::pure::mapping::from_T_m__SingleExecutionParameters_1__T_m_", (List ps) -> ps.size() == 2 && handlers.isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "SingleExecutionParameters".equals(ps.get(1)._genericType()._rawType()._name()))), new FunctionHandlerDispatchBuilderInfo("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__SingleExecutionParameters_1_", (List ps) -> ps.size() == 2 && handlers.isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "ExecutionEnvironmentInstance".equals(ps.get(0)._genericType()._rawType()._name())) && handlers.isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "String".equals(ps.get(1)._genericType()._rawType()._name()))), - new FunctionHandlerDispatchBuilderInfo("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", (List ps) -> ps.size() == 3 && handlers.isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "ExecutionEnvironmentInstance".equals(ps.get(0)._genericType()._rawType()._name())) && handlers.isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "String".equals(ps.get(1)._genericType()._rawType()._name())) && handlers.isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "String".equals(ps.get(2)._genericType()._rawType()._name()))) + new FunctionHandlerDispatchBuilderInfo("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", (List ps) -> ps.size() == 3 && handlers.isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "ExecutionEnvironmentInstance".equals(ps.get(0)._genericType()._rawType()._name())) && handlers.isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "String".equals(ps.get(1)._genericType()._rawType()._name())) && handlers.isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "String".equals(ps.get(2)._genericType()._rawType()._name()))), + new FunctionHandlerDispatchBuilderInfo("meta::legend::service::getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", (List ps) -> ps.size() == 3 && handlers.isOne(ps.get(0)._multiplicity()) && ("Nil".equals(ps.get(0)._genericType()._rawType()._name()) || "ExecutionEnvironmentInstance".equals(ps.get(0)._genericType()._rawType()._name())) && handlers.isOne(ps.get(1)._multiplicity()) && ("Nil".equals(ps.get(1)._genericType()._rawType()._name()) || "String".equals(ps.get(1)._genericType()._rawType()._name())) && handlers.isOne(ps.get(2)._multiplicity()) && ("Nil".equals(ps.get(2)._genericType()._rawType()._name()) || "String".equals(ps.get(2)._genericType()._rawType()._name()))) )); } @@ -374,7 +376,11 @@ public List>> // getter for execution parameters from execution environment new FunctionExpressionBuilderRegistrationInfo(null, handlers.m( handlers.m(handlers.h("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__SingleExecutionParameters_1_", false, ps -> handlers.res("meta::legend::service::metamodel::SingleExecutionParameters", "one"), ps -> ps.size() == 2)), - handlers.m(handlers.h("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", false, ps -> handlers.res("meta::legend::service::metamodel::SingleExecutionParameters", "one"), ps -> ps.size() == 3)))) + handlers.m(handlers.h("meta::legend::service::get_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", false, ps -> handlers.res("meta::legend::service::metamodel::SingleExecutionParameters", "one"), ps -> ps.size() == 3)) + )), + new FunctionExpressionBuilderRegistrationInfo(null, handlers.m( + handlers.m(handlers.h("meta::legend::service::getWithRuntime_ExecutionEnvironmentInstance_1__String_1__String_1__SingleExecutionParameters_1_", false, ps -> handlers.res("meta::legend::service::metamodel::SingleExecutionParameters", "one"), ps -> ps.size() == 3))) + ) )); } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/from/ServiceParseTreeWalker.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/from/ServiceParseTreeWalker.java index c82abd1e6ec..ec6fea53e3d 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/from/ServiceParseTreeWalker.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/from/ServiceParseTreeWalker.java @@ -28,6 +28,8 @@ import org.finos.legend.engine.language.pure.grammar.from.test.assertion.HelperTestAssertionGrammarParser; import org.finos.legend.engine.protocol.pure.v1.model.SourceInformation; import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; +import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementPointer; +import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementType; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.ParameterValue; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr; @@ -47,6 +49,7 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.PostValidationAssertion; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.PureMultiExecution; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.PureSingleExecution; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.RuntimeComponents; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.Service; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.ServiceTest; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service.ServiceTestSuite; @@ -584,8 +587,16 @@ private SingleExecutionParameters visitSingleExecutionParameters(ServiceParserGr singleExecParams.mapping = PureGrammarParserUtility.fromQualifiedName(mappingContext.qualifiedName().packagePath() == null ? Collections.emptyList() : mappingContext.qualifiedName().packagePath().identifier(), mappingContext.qualifiedName().identifier()); singleExecParams.mappingSourceInformation = walkerSourceInformation.getSourceInformation(mappingContext.qualifiedName()); // runtime - ServiceParserGrammar.ServiceRuntimeContext runtimeContext = PureGrammarParserUtility.validateAndExtractRequiredField(Collections.singletonList(ctx.serviceRuntime()), "runtime", singleExecParams.sourceInformation); - singleExecParams.runtime = this.visitRuntime(runtimeContext); + ServiceParserGrammar.ServiceRuntimeContext runtimeContext = PureGrammarParserUtility.validateAndExtractOptionalField(ctx.serviceRuntime(), "runtime", singleExecParams.sourceInformation); + if (runtimeContext != null) + { + singleExecParams.runtime = this.visitRuntime(runtimeContext); + } + ServiceParserGrammar.ServiceRuntimeComponentsContext serviceRuntimeComponentsContext = PureGrammarParserUtility.validateAndExtractOptionalField(ctx.serviceRuntimeComponents(), "runtimeComponents", singleExecParams.sourceInformation); + if (serviceRuntimeComponentsContext != null) + { + singleExecParams.runtimeComponents = this.visitRuntimeComponents(serviceRuntimeComponentsContext); + } return singleExecParams; } @@ -597,4 +608,30 @@ private MultiExecutionParameters visitMultiExecutionParameters(ServiceParserGram multiExecParams.singleExecutionParameters = ListIterate.collect(singleExecCtxList, this::visitSingleExecutionParameters); return multiExecParams; } + + private RuntimeComponents visitRuntimeComponents(ServiceParserGrammar.ServiceRuntimeComponentsContext ctx) + { + RuntimeComponents runtimeComponents = new RuntimeComponents(); + + ServiceParserGrammar.ComponentRuntimeContext componentRuntime = ctx.componentRuntime().get(0); + ServiceParserGrammar.ComponentClassContext componentClass = ctx.componentClass().get(0); + ServiceParserGrammar.ComponentBindingContext componentBinding = ctx.componentBinding().get(0); + RuntimePointer runtimePtr = new RuntimePointer(); + runtimePtr.runtime = PureGrammarParserUtility.fromQualifiedName(componentRuntime.runtimePointer().qualifiedName().packagePath() == null ? Collections.emptyList() : componentRuntime.runtimePointer().qualifiedName().packagePath().identifier(), componentRuntime.runtimePointer().qualifiedName().identifier()); + runtimePtr.sourceInformation = walkerSourceInformation.getSourceInformation(componentRuntime); + PackageableElementPointer bindingPtr = new PackageableElementPointer(); + bindingPtr.type = PackageableElementType.BINDING; + bindingPtr.path = PureGrammarParserUtility.fromQualifiedName(componentBinding.qualifiedName().packagePath() == null ? Collections.emptyList() : componentBinding.qualifiedName().packagePath().identifier(), componentBinding.qualifiedName().identifier()); + bindingPtr.sourceInformation = walkerSourceInformation.getSourceInformation(componentBinding); + + PackageableElementPointer classPtr = new PackageableElementPointer(); + classPtr.type = PackageableElementType.CLASS; + classPtr.path = PureGrammarParserUtility.fromQualifiedName(componentClass.qualifiedName().packagePath() == null ? Collections.emptyList() : componentClass.qualifiedName().packagePath().identifier(), componentClass.qualifiedName().identifier()); + classPtr.sourceInformation = walkerSourceInformation.getSourceInformation(componentClass); + + runtimeComponents.clazz = classPtr; + runtimeComponents.binding = bindingPtr; + runtimeComponents.runtime = runtimePtr; + return runtimeComponents; + } } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/to/HelperExecutionEnvironmentGrammarComposer.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/to/HelperExecutionEnvironmentGrammarComposer.java index a9d296d92c7..00c1022e96c 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/to/HelperExecutionEnvironmentGrammarComposer.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/language/pure/dsl/service/grammar/to/HelperExecutionEnvironmentGrammarComposer.java @@ -32,7 +32,18 @@ protected static String renderSingleExecutionParameter(SingleExecutionParameters str.append(getTabString(baseIndentation)).append(parameters.key).append(":\n"); str.append(getTabString(baseIndentation)).append("{\n"); str.append(getTabString(baseIndentation + 1)).append("mapping: ").append(parameters.mapping).append(";\n"); - str.append(HelperServiceGrammarComposer.renderServiceExecutionRuntime(parameters.runtime, baseIndentation + 1, context)); + if (parameters.runtime != null) + { + str.append(HelperServiceGrammarComposer.renderServiceExecutionRuntime(parameters.runtime, baseIndentation + 1, context)); + } + if (parameters.runtimeComponents != null) + { + str.append(getTabString(baseIndentation + 1)).append("runtimeComponents:").append("\n").append(getTabString(baseIndentation + 1)).append("{\n"); + str.append(getTabString(baseIndentation + 2)).append("class: ").append(parameters.runtimeComponents.clazz.path).append(";\n"); + str.append(getTabString(baseIndentation + 2)).append("binding: ").append(parameters.runtimeComponents.binding.path).append(";\n"); + str.append(HelperServiceGrammarComposer.renderServiceExecutionRuntime(parameters.runtimeComponents.runtime, baseIndentation + 2, context)); + str.append("\n").append(getTabString(baseIndentation + 1)).append("}"); + } str.append("\n").append(getTabString(baseIndentation)).append("}"); return str.toString(); } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/RuntimeComponents.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/RuntimeComponents.java new file mode 100644 index 00000000000..448ff33b23c --- /dev/null +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/RuntimeComponents.java @@ -0,0 +1,28 @@ +// Copyright 2021 Goldman Sachs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.finos.legend.engine.protocol.pure.v1.model.packageableElement.service; + +import org.finos.legend.engine.protocol.pure.v1.model.SourceInformation; +import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementPointer; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.Runtime; + +public class RuntimeComponents +{ + public Runtime runtime; + public PackageableElementPointer clazz; + public PackageableElementPointer binding; + public SourceInformation sourceInformation; + +} diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/SingleExecutionParameters.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/SingleExecutionParameters.java index 37cd6a4f219..24b21b0f82e 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/SingleExecutionParameters.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/service/SingleExecutionParameters.java @@ -22,6 +22,7 @@ public class SingleExecutionParameters extends ExecutionParameters public String key; public String mapping; public Runtime runtime; + public RuntimeComponents runtimeComponents; public SourceInformation sourceInformation; public SourceInformation mappingSourceInformation; } diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestServiceCompilationFromGrammar.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestServiceCompilationFromGrammar.java index 1bc96a631b6..0357d8b9d5c 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestServiceCompilationFromGrammar.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/compiler/test/TestServiceCompilationFromGrammar.java @@ -3492,5 +3492,100 @@ public void testExecutionEnvironmentCompilation() " }\n" + " ];\n" + "}\n","COMPILATION error at [27:16-31]: Can't find runtime 'test::myRuntime1'"); + + test(resource + "###Service\n" + + "ExecutionEnvironment test::executionEnvironment\n" + + "{\n" + + " executions:\n" + + " [\n" + + " UAT:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::myRuntime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " },\n" + + " PROD:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::myRuntime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " }\n" + + " ];\n" + + "}\n","COMPILATION error at [20:1-45:1]: Error in 'test::executionEnvironment': Cannot resolve binding. Error: Execution error at (resource:/platform/pure/essential/meta/graph/pathToElement.pure line:20 column:12), \"'test::bind' is not a valid PackageableElement: could not find 'test' in Root\""); + + String binding = "###ExternalFormat\n" + + "Binding test::bind\n" + + "{\n" + + " contentType: 'application/json';\n" + + " modelIncludes: [\n" + + " test::class\n" + + " ];\n" + + "}\n"; + test(resource + binding + "###Service\n" + + "ExecutionEnvironment test::executionEnvironment\n" + + "{\n" + + " executions:\n" + + " [\n" + + " UAT:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::runtime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " },\n" + + " PROD:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::runtime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " }\n" + + " ];\n" + + "}\n"); + + test(resource + binding + "###Service\n" + + "ExecutionEnvironment test::executionEnvironment\n" + + "{\n" + + " executions:\n" + + " [\n" + + " UAT:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtime: test::runtime;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::runtime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " },\n" + + " PROD:\n" + + " {\n" + + " mapping: test::mapping;\n" + + " runtime: test::runtime;\n" + + " runtimeComponents:\n" + + " {\n" + + " runtime: test::runtime;\n" + + " class: test::class;\n" + + " binding: test::bind;\n" + + " }\n" + + " }\n" + + " ];\n" + + "}\n", "COMPILATION error at [32:5-42:5]: Cannot use both runtime and runtime components"); + } } \ No newline at end of file diff --git a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestServiceGrammarRoundtrip.java b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestServiceGrammarRoundtrip.java index 4325d0bc764..a1163525ad8 100644 --- a/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestServiceGrammarRoundtrip.java +++ b/legend-engine-xts-service/legend-engine-language-pure-dsl-service/src/test/java/org/finos/legend/engine/language/pure/grammar/test/TestServiceGrammarRoundtrip.java @@ -1344,6 +1344,34 @@ public void testExecutionEnvironment() " ];\n" + "}\n"); + test("###Service\n" + + "ExecutionEnvironment test::executionEnvironment\n" + + "{\n" + + " executions:\n" + + " [\n" + + " UAT:\n" + + " {\n" + + " mapping: test::myMapping1;\n" + + " runtimeComponents:\n" + + " {\n" + + " class: test::myClass;\n" + + " binding: test::Binding;\n" + + " runtime: test::myRuntime1;\n" + + " }\n" + + " },\n" + + " PROD:\n" + + " {\n" + + " mapping: test::myMapping2;\n" + + " runtimeComponents:\n" + + " {\n" + + " class: test::myClass;\n" + + " binding: test::Binding;\n" + + " runtime: test::myRuntime1;\n" + + " }\n" + + " }\n" + + " ];\n" + + "}\n"); + test("###Service\n" + "ExecutionEnvironment test::executionEnvironment\n" + "{\n" + @@ -1544,6 +1572,21 @@ public void testExecutionEnvironmentInSingleExecService() " }\n" + "}\n" + "\n" + + "Service meta::pure::myServiceMulti2\n" + + "{\n" + + " pattern: 'url/myUrl/{env}';\n" + + " owners:\n" + + " [\n" + + " 'ownerName'\n" + + " ];\n" + + " documentation: 'this is just for context';\n" + + " autoActivateUpdates: true;\n" + + " execution: Multi\n" + + " {\n" + + " query: {env: String[1],data: String[1]|model::pure::mapping::modelToModel::test::shared::dest::Product.all()->from(test::executionEnvironment->getWithRuntime($env, $data))->graphFetchChecked(#{model::pure::mapping::modelToModel::test::shared::dest::Product{name}}#)->serialize(#{model::pure::mapping::modelToModel::test::shared::dest::Product{name}}#)};\n" + + " }\n" + + "}\n" + + "\n" + "ExecutionEnvironment test::executionEnvironment\n" + "{\n" + " executions:\n" +