From 3dd857267f6bc6b693867a763c5004bdf4742e21 Mon Sep 17 00:00:00 2001 From: Sahil Shah Date: Mon, 29 Jan 2024 14:39:56 +0000 Subject: [PATCH] add support for mastery resolution key filter (#2578) --- .../from/antlr4/MasteryLexerGrammar.g4 | 1 + .../from/antlr4/MasteryParserGrammar.g4 | 3 + .../HelperMasterRecordDefinitionBuilder.java | 43 ++++-- .../toPureGraph/MasteryCompilerExtension.java | 2 +- .../grammar/from/MasteryParseTreeWalker.java | 7 + .../to/HelperMasteryGrammarComposer.java | 4 + .../TestMasteryCompilationFromGrammar.java | 129 ++++++++++++++++++ .../mastery/identity/ResolutionQuery.java | 1 + .../core_mastery/mastery/metamodel.pure | 3 + 9 files changed, 184 insertions(+), 9 deletions(-) diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryLexerGrammar.g4 b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryLexerGrammar.g4 index 7a15d60935f..4c455731861 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryLexerGrammar.g4 +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryLexerGrammar.g4 @@ -57,6 +57,7 @@ RESOLUTION_QUERY_KEY_TYPE_GENERATED_PRIMARY_KEY:'GeneratedPrimaryKey'; //Validat RESOLUTION_QUERY_KEY_TYPE_SUPPLIED_PRIMARY_KEY: 'SuppliedPrimaryKey'; //Validated against equality key to ensure an actuial PK and create if don't find match RESOLUTION_QUERY_KEY_TYPE_ALTERNATE_KEY: 'AlternateKey'; //AlternateKey (In an AlternateKey is specified then at least one required in the input record or fail resolution). AlternateKey && (CurationModel field == Create) then the input source is attempting to create a new record (e.g. from UI) block if existing record found RESOLUTION_QUERY_KEY_TYPE_OPTIONAL: 'Optional'; +RESOLUTION_QUERY_FILTER: 'filter'; // -------------------------------------- PRECEDENCE RULES -------------------------------------- PRECEDENCE_RULES: 'precedenceRules'; diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryParserGrammar.g4 b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryParserGrammar.g4 index ababf38b27f..c7627c7a8ef 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryParserGrammar.g4 +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/antlr4/org/finos/legend/engine/language/pure/grammar/from/antlr4/MasteryParserGrammar.g4 @@ -277,6 +277,7 @@ resolutionQuery: BRACE_OPEN | resolutionQueryKeyType | resolutionQueryOptional | resolutionQueryPrecedence + | resolutionQueryFilter )* BRACE_CLOSE ; @@ -300,6 +301,8 @@ resolutionQueryOptional: RESOLUTION_QUERY_OPTIONAL COLON boolean ; resolutionQueryPrecedence: PRECEDENCE COLON INTEGER SEMI_COLON ; +resolutionQueryFilter: RESOLUTION_QUERY_FILTER COLON lambdaFunction SEMI_COLON +; // -------------------------------------- PRECEDENCE RULES-------------------------------------- precedenceRules: PRECEDENCE_RULES COLON diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/HelperMasterRecordDefinitionBuilder.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/HelperMasterRecordDefinitionBuilder.java index bf54d74e517..7065284cc54 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/HelperMasterRecordDefinitionBuilder.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/HelperMasterRecordDefinitionBuilder.java @@ -31,7 +31,6 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.RecordSource; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.RecordSourceVisitor; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.acquisition.AcquisitionProtocol; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.acquisition.KafkaAcquisitionProtocol; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.authorization.Authorization; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.identity.CollectionEquality; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.identity.IdentityResolution; @@ -39,6 +38,7 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.identity.ResolutionQuery; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.precedence.*; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mastery.trigger.Trigger; +import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.Variable; import org.finos.legend.engine.protocol.pure.v1.model.valueSpecification.raw.Lambda; import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; import org.finos.legend.pure.generated.*; @@ -49,7 +49,6 @@ import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; -import org.finos.legend.pure.m4.coreinstance.CoreInstance; import java.util.*; import java.util.stream.Collectors; @@ -58,7 +57,6 @@ import static com.google.common.collect.Sets.newHashSet; import static java.lang.String.format; import static java.util.Objects.nonNull; -import static org.apache.commons.lang3.BooleanUtils.isFalse; import static org.apache.commons.lang3.BooleanUtils.isTrue; public class HelperMasterRecordDefinitionBuilder @@ -66,7 +64,6 @@ public class HelperMasterRecordDefinitionBuilder private static final String MASTERY_PACKAGE_PREFIX = "meta::pure::mastery::metamodel"; private static final String ROOT = "Root"; private static final Set CONDITIONAL_BLOCK_RULE_PREDICATE_INPUT = newHashSet("incoming", "current"); - private static final IdentityResolutionBuilder IDENTITY_RESOLUTION_BUILDER = new IdentityResolutionBuilder(); private HelperMasterRecordDefinitionBuilder() { @@ -104,15 +101,21 @@ private static String determineFullPath(Type type) return Iterate.makeString(deque, "", "::", "::" + type._name()); } - public static Root_meta_pure_mastery_metamodel_identity_IdentityResolution buildIdentityResolution(IdentityResolution identityResolution, CompileContext context) + public static Root_meta_pure_mastery_metamodel_identity_IdentityResolution buildIdentityResolution(IdentityResolution identityResolution, String modelClass, CompileContext context) { - IDENTITY_RESOLUTION_BUILDER.context = context; - return identityResolution.accept(IDENTITY_RESOLUTION_BUILDER); + return identityResolution.accept(new IdentityResolutionBuilder(context, modelClass)); } private static class IdentityResolutionBuilder implements IdentityResolutionVisitor { - private CompileContext context; + private final CompileContext context; + private final String modelClass; + + public IdentityResolutionBuilder(CompileContext context, String modelClass) + { + this.context = context; + this.modelClass = modelClass; + } @Override public Root_meta_pure_mastery_metamodel_identity_IdentityResolution visit(IdentityResolution protocolVal) @@ -131,12 +134,36 @@ private Iterable visi resQuery._keyType(protocolQuery.keyType == null ? null : context.resolveEnumValue(KEY_TYPE_FULL_PATH, protocolQuery.keyType.name())); resQuery._optional(protocolQuery.optional); resQuery._precedence(protocolQuery.precedence); + if (protocolQuery.filter != null) + { + validateFilterInput(protocolQuery.filter); + resQuery._filter(HelperValueSpecificationBuilder.buildLambda(protocolQuery.filter, context)); + } ListIterate.forEachWithIndex(protocolQuery.queries, (lambda, i) -> resQuery._queriesAdd(HelperValueSpecificationBuilder.buildLambda(lambda, context))); list.add(resQuery); return list; } + + private void validateFilterInput(Lambda predicate) + { + List parameters = predicate.parameters; + if (parameters.size() != 1) + { + throw new EngineException(format("The resolution query filter must have exactly one parameter specified in the lambda function - found %s", parameters.size()), EngineErrorType.COMPILATION); + } + Variable parameter = parameters.get(0); + String parameterClass = parameter._class; + if (!modelClass.equals(parameterClass)) + { + throw new EngineException(format("Input Class for the resolution key filter should be %s, however found %s", modelClass, parameterClass), EngineErrorType.COMPILATION); + } + if (parameter.multiplicity.lowerBound != 1 || !parameter.multiplicity.isUpperBoundEqualTo(1)) + { + throw new EngineException("Expected input for resolution key filter to have multiplicity 1", EngineErrorType.COMPILATION); + } + } } public static RichIterable buildRecordSources(List recordSources, CompileContext context) diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/MasteryCompilerExtension.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/MasteryCompilerExtension.java index 8c931b445f7..a4f60e9f53f 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/MasteryCompilerExtension.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/toPureGraph/MasteryCompilerExtension.java @@ -76,7 +76,7 @@ public Iterable> getExtraProcessors() (masterRecordDefinition, context) -> { Root_meta_pure_mastery_metamodel_MasterRecordDefinition pureMasteryMetamodelMasterRecordDefinition = (Root_meta_pure_mastery_metamodel_MasterRecordDefinition) context.pureModel.getOrCreatePackage(masterRecordDefinition._package)._children().detect(c -> masterRecordDefinition.name.equals(c._name())); - pureMasteryMetamodelMasterRecordDefinition._identityResolution(HelperMasterRecordDefinitionBuilder.buildIdentityResolution(masterRecordDefinition.identityResolution, context)); + pureMasteryMetamodelMasterRecordDefinition._identityResolution(HelperMasterRecordDefinitionBuilder.buildIdentityResolution(masterRecordDefinition.identityResolution, masterRecordDefinition.modelClass, context)); pureMasteryMetamodelMasterRecordDefinition._sources(HelperMasterRecordDefinitionBuilder.buildRecordSources(masterRecordDefinition.sources, context)); pureMasteryMetamodelMasterRecordDefinition._postCurationEnrichmentService(BuilderUtil.buildService(masterRecordDefinition.postCurationEnrichmentService, context, masterRecordDefinition.sourceInformation)); pureMasteryMetamodelMasterRecordDefinition._exceptionWorkflowTransformService(BuilderUtil.buildService(masterRecordDefinition.exceptionWorkflowTransformService, context, masterRecordDefinition.sourceInformation)); diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/from/MasteryParseTreeWalker.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/from/MasteryParseTreeWalker.java index 594ddc98acd..60f8b298ce1 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/from/MasteryParseTreeWalker.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/from/MasteryParseTreeWalker.java @@ -736,6 +736,13 @@ private ResolutionQuery visitResolutionQuery(MasteryParserGrammar.ResolutionQuer MasteryParserGrammar.ResolutionQueryPrecedenceContext resolutionQueryPrecedenceContext = PureGrammarParserUtility.validateAndExtractRequiredField(ctx.resolutionQueryPrecedence(), "precedence", sourceInformation); resolutionQuery.precedence = Integer.parseInt(resolutionQueryPrecedenceContext.INTEGER().getText()); + //filter + MasteryParserGrammar.ResolutionQueryFilterContext resolutionQueryFilterContext = PureGrammarParserUtility.validateAndExtractOptionalField(ctx.resolutionQueryFilter(), "filter", sourceInformation); + if (resolutionQueryFilterContext != null) + { + resolutionQuery.filter = visitLambda(resolutionQueryFilterContext.lambdaFunction()); + } + return resolutionQuery; } diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/to/HelperMasteryGrammarComposer.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/to/HelperMasteryGrammarComposer.java index 93894d23615..2de0956f546 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/to/HelperMasteryGrammarComposer.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/main/java/org/finos/legend/engine/language/pure/dsl/mastery/grammar/to/HelperMasteryGrammarComposer.java @@ -458,6 +458,10 @@ private static String renderResolutionQueries(IdentityResolution identityResolut builder.append(getTabString(indentLevel + 4)).append("optional: ").append(resolutionQuery.optional).append(";\n"); } builder.append(getTabString(indentLevel + 4)).append("precedence: ").append(resolutionQuery.precedence).append(";\n"); + if (resolutionQuery.filter != null) + { + builder.append(getTabString(indentLevel + 4)).append("filter: ").append(lambdaToString(resolutionQuery.filter, context)).append(";\n"); + } builder.append(getTabString(indentLevel + 3)).append("}"); }); builder.append("\n").append(getTabString(indentLevel + 2)).append("]"); diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/test/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/test/TestMasteryCompilationFromGrammar.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/test/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/test/TestMasteryCompilationFromGrammar.java index 850329abd7c..1b0d9b788fa 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/test/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/test/TestMasteryCompilationFromGrammar.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-grammar/src/test/java/org/finos/legend/engine/language/pure/dsl/mastery/compiler/test/TestMasteryCompilationFromGrammar.java @@ -128,6 +128,15 @@ public class TestMasteryCompilationFromGrammar extends TestCompilationFromGramma " keyType: AlternateKey;\n" + " optional: true;\n" + " precedence: 2;\n" + + " filter: {input: org::dataeng::Widget[1]|$input.trigger == 'A'};\n" + + " },\n" + + " {\n" + + " queries: [ {input: org::dataeng::Widget[1],EFFECTIVE_DATE: StrictDate[1]|org::dataeng::Widget.all()->filter(widget|((($widget.identifiers.identifierType == 'CUSIP') && ($input.identifiers->filter(idType|$idType.identifierType == 'CUSIP').identifier == $widget.identifiers->filter(idType|$idType.identifierType == 'CUSIP').identifier)) && ($widget.identifiers.FROM_Z->toOne() <= $EFFECTIVE_DATE)) && ($widget.identifiers.THRU_Z->toOne() > $EFFECTIVE_DATE))}\n" + + " ];\n" + + " keyType: AlternateKey;\n" + + " optional: true;\n" + + " precedence: 2;\n" + + " filter: {input: org::dataeng::Widget[1]|$input.trigger == 'B'};\n" + " },\n" + " {\n" + " queries: [ {input: org::dataeng::Widget[1]|org::dataeng::Widget.all()->filter(widget|$widget.trigger == $input.trigger)}\n" + @@ -1398,6 +1407,126 @@ public void testCompilationErrorWhenConditionalRuleHasScopeDefined() TestCompilationFromGrammar.TestCompilationFromGrammarTestSuite.test(model, "COMPILATION error at [23:5-29:5]: ConditionalRule with ruleScope is currently unsupported"); } + @Test + public void testCompilationErrorWhenResolutionFilterHasMoreThanOneParameter() + { + String model = "###Pure\n" + + "Class org::dataeng::Widget\n" + + "{\n" + + " widgetId: String[0..1];\n" + + "}\n\n" + + "###Mastery\n" + "MasterRecordDefinition alloy::mastery::WidgetMasterRecord" + + "\n" + + "{\n" + + " modelClass: org::dataeng::Widget;\n" + + " identityResolution: \n" + + " {\n" + + " resolutionQueries:\n" + + " [\n" + + " {\n" + + " queries: [ {input: org::dataeng::Widget[1]|org::dataeng::Widget.all()->filter(widget|$widget.widgetId == $input.widgetId)}\n" + + " ];\n" + + " precedence: 1;\n" + + " filter: {input:org::dataeng::Widget[1],current:org::dataeng::Widget[1]| $input.widgetId == $current.widget};\n" + + " }\n" + + " ]\n" + + " }\n" + + " recordSources:\n" + + " [\n" + + " widget-producer: {\n" + + " description: 'REST Acquisition source.';\n" + + " status: Development;\n" + + " recordService: {\n" + + " acquisitionProtocol: REST;\n" + + " };\n" + + " trigger: Manual;\n" + + " }\n" + + " ]\n" + + "}\n\n"; + + TestCompilationFromGrammar.TestCompilationFromGrammarTestSuite.test(model, "COMPILATION error at [8:1-34:1]: Error in 'alloy::mastery::WidgetMasterRecord': The resolution query filter must have exactly one parameter specified in the lambda function - found 2"); + } + + @Test + public void testCompilationErrorWhenResolutionFilterHasWrongParameterType() + { + String model = "###Pure\n" + + "Class org::dataeng::Widget\n" + + "{\n" + + " widgetId: String[0..1];\n" + + "}\n\n" + + "###Mastery\n" + "MasterRecordDefinition alloy::mastery::WidgetMasterRecord" + + "\n" + + "{\n" + + " modelClass: org::dataeng::Widget;\n" + + " identityResolution: \n" + + " {\n" + + " resolutionQueries:\n" + + " [\n" + + " {\n" + + " queries: [ {input: org::dataeng::Widget[1]|org::dataeng::Widget.all()->filter(widget|$widget.widgetId == $input.widgetId)}\n" + + " ];\n" + + " precedence: 1;\n" + + " filter: {input:String[1]| $input == 'A'};\n" + + " }\n" + + " ]\n" + + " }\n" + + " recordSources:\n" + + " [\n" + + " widget-producer: {\n" + + " description: 'REST Acquisition source.';\n" + + " status: Development;\n" + + " recordService: {\n" + + " acquisitionProtocol: REST;\n" + + " };\n" + + " trigger: Manual;\n" + + " }\n" + + " ]\n" + + "}\n\n"; + + TestCompilationFromGrammar.TestCompilationFromGrammarTestSuite.test(model, "COMPILATION error at [8:1-34:1]: Error in 'alloy::mastery::WidgetMasterRecord': Input Class for the resolution key filter should be org::dataeng::Widget, however found String"); + } + + @Test + public void testCompilationErrorWhenResolutionFilterHasWrongParameterMultiplicity() + { + String model = "###Pure\n" + + "Class org::dataeng::Widget\n" + + "{\n" + + " widgetId: String[0..1];\n" + + "}\n\n" + + "###Mastery\n" + "MasterRecordDefinition alloy::mastery::WidgetMasterRecord" + + "\n" + + "{\n" + + " modelClass: org::dataeng::Widget;\n" + + " identityResolution: \n" + + " {\n" + + " resolutionQueries:\n" + + " [\n" + + " {\n" + + " queries: [ {input: org::dataeng::Widget[1]|org::dataeng::Widget.all()->filter(widget|$widget.widgetId == $input.widgetId)}\n" + + " ];\n" + + " precedence: 1;\n" + + " filter: {input:org::dataeng::Widget[0..1]| $input.widgetId == 'A'};\n" + + " }\n" + + " ]\n" + + " }\n" + + " recordSources:\n" + + " [\n" + + " widget-producer: {\n" + + " description: 'REST Acquisition source.';\n" + + " status: Development;\n" + + " recordService: {\n" + + " acquisitionProtocol: REST;\n" + + " };\n" + + " trigger: Manual;\n" + + " }\n" + + " ]\n" + + "}\n\n"; + + TestCompilationFromGrammar.TestCompilationFromGrammarTestSuite.test(model, "COMPILATION error at [8:1-34:1]: Error in 'alloy::mastery::WidgetMasterRecord': Expected input for resolution key filter to have multiplicity 1"); + } + private void assertDataProviders(PureModel model) { PackageableElement lseDataProvider = model.getPackageableElement("alloy::mastery::dataprovider::LSE"); diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-protocol/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/mastery/identity/ResolutionQuery.java b/legend-engine-xts-mastery/legend-engine-xt-mastery-protocol/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/mastery/identity/ResolutionQuery.java index f2e0b634dfc..0b690393b55 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-protocol/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/mastery/identity/ResolutionQuery.java +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-protocol/src/main/java/org/finos/legend/engine/protocol/pure/v1/model/packageableElement/mastery/identity/ResolutionQuery.java @@ -24,4 +24,5 @@ public class ResolutionQuery public ResolutionKeyType keyType; public Boolean optional; public Integer precedence; + public Lambda filter; } diff --git a/legend-engine-xts-mastery/legend-engine-xt-mastery-pure/src/main/resources/core_mastery/mastery/metamodel.pure b/legend-engine-xts-mastery/legend-engine-xt-mastery-pure/src/main/resources/core_mastery/mastery/metamodel.pure index f989941b7b4..52885f906ad 100644 --- a/legend-engine-xts-mastery/legend-engine-xt-mastery-pure/src/main/resources/core_mastery/mastery/metamodel.pure +++ b/legend-engine-xts-mastery/legend-engine-xt-mastery-pure/src/main/resources/core_mastery/mastery/metamodel.pure @@ -178,6 +178,9 @@ meta::pure::mastery::metamodel::identity::ResolutionQuery {doc.doc='The query precedence applied when there are more than one ResoultionQuery definitions on an IdentityResolution, 1 is hiughest.'} precedence : Integer[1]; + + {doc.doc='An optional filter that when specified will determine whether the input should execute this resolution query or not.'} + filter: meta::pure::metamodel::function::LambdaFunction<{Any[*]->Boolean[1]}>[0..1]; } Enum {doc.doc = 'Types of resolution keys.'}