From 745a23f7fc8bd7a31ed56c3a45ddcf2a9e1184ac Mon Sep 17 00:00:00 2001 From: Gabriele Cardosi Date: Tue, 9 Apr 2024 07:29:46 +0200 Subject: [PATCH] [incubator-kie-issues#1066] Implement usage of namespace inside href for unnamed imports (#5830) * [incubator-kie-issues#1066] Soring both default and imported id for unnamed imports * [incubator-kie-issues#1066] Implementing tests with and without namespace in href --------- Co-authored-by: Gabriele-Cardosi --- .../org/kie/dmn/core/impl/DMNModelImpl.java | 29 ++++---- .../org/kie/dmn/core/impl/DMNRuntimeImpl.java | 5 +- .../org/kie/dmn/core/DMNCompilerTest.java | 55 ++++++++------ .../core/compiler/UnnamedImportUtilsTest.java | 62 +++++++++++----- .../DMNv1_5/Imported_Model_Unamed.dmn | 6 +- ...g_EmptyNamed_Model_With_Href_Namespace.dmn | 74 +++++++++++++++++++ ...ptyNamed_Model_Without_Href_Namespace.dmn} | 5 -- .../validation/v1_5/DMN15ValidationsTest.java | 25 +++++-- 8 files changed, 188 insertions(+), 73 deletions(-) create mode 100644 kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model_With_Href_Namespace.dmn rename kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/{Importing_EmptyNamed_Model.dmn => Importing_EmptyNamed_Model_Without_Href_Namespace.dmn} (94%) diff --git a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNModelImpl.java b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNModelImpl.java index f7a45a44d36..d100cbbc85e 100644 --- a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNModelImpl.java +++ b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNModelImpl.java @@ -23,6 +23,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -167,16 +168,12 @@ public String nameInCurrentModel(DMNNode node) { return node.getName(); } else { Optional lookupAlias = getImportAliasFor(node.getModelNamespace(), node.getModelName()); - if (lookupAlias.isPresent()) { - return lookupAlias.get() + "." + node.getName(); - } else { - return null; - } + return lookupAlias.map(s -> s + "." + node.getName()).orElse(null); } } public void addInput(InputDataNode idn) { - inputs.put(computeDRGElementModelLocalId(idn), idn); + computeDRGElementModelLocalId(idn).forEach(id -> inputs.put(id, idn)); } @Override @@ -199,24 +196,24 @@ public InputDataNode getInputByName(String name) { @Override public Set getInputs() { - return this.inputs.values().stream().collect( Collectors.toCollection(LinkedHashSet::new) ); + return new LinkedHashSet<>(this.inputs.values()); } public void addDecision(DecisionNode dn) { - decisions.put(computeDRGElementModelLocalId(dn), dn); + computeDRGElementModelLocalId(dn).forEach(id -> decisions.put(id, dn)); } - private String computeDRGElementModelLocalId(DMNNode node) { + private List computeDRGElementModelLocalId(DMNNode node) { // incubator-kie-issues#852: The idea is to not treat the anonymous models as import, but to "merge" them with original opne, // Here, if the node comes from an unnamed imported model, then it is stored only with its id, to be looked for // as if defined in the model itself if (node.getModelNamespace().equals(definitions.getNamespace())) { - return node.getId(); + return Collections.singletonList(node.getId()); } else if (isInUnnamedImport(node, this)) { // the node is an unnamed import - return node.getId(); + return Arrays.asList(node.getId(), node.getModelNamespace() + "#" + node.getId()); } else { - return node.getModelNamespace() + "#" + node.getId(); + return Collections.singletonList(node.getModelNamespace() + "#" + node.getId()); } } @@ -241,7 +238,7 @@ public DecisionNode getDecisionByName(String name) { @Override public Set getDecisions() { - return this.decisions.values().stream().collect(Collectors.toCollection(LinkedHashSet::new)); + return new LinkedHashSet<>(this.decisions.values()); } @Override @@ -265,7 +262,7 @@ public Set getRequiredInputsForDecisionId(String decisionId) { } public void addDecisionService(DecisionServiceNode dsn) { - decisionServices.put(computeDRGElementModelLocalId(dsn), dsn); + computeDRGElementModelLocalId(dsn).forEach(id -> decisionServices.put(id, dsn)); } public DecisionServiceNode getDecisionServiceById(String id) { @@ -286,11 +283,11 @@ public DecisionServiceNode getDecisionServiceByName(String name) { @Override public Collection getDecisionServices() { - return this.decisionServices.values().stream().collect(Collectors.toCollection(LinkedHashSet::new)); + return new LinkedHashSet<>(this.decisionServices.values()); } public void addBusinessKnowledgeModel(BusinessKnowledgeModelNode bkm) { - bkms.put(computeDRGElementModelLocalId(bkm), bkm); + computeDRGElementModelLocalId(bkm).forEach(id -> bkms.put(id, bkm)); } @Override diff --git a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNRuntimeImpl.java b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNRuntimeImpl.java index 85ccf42b784..12a3eebea54 100644 --- a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNRuntimeImpl.java +++ b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/impl/DMNRuntimeImpl.java @@ -461,7 +461,10 @@ public static Object coerceUsingType(Object value, DMNType type, boolean typeChe private boolean isNodeValueDefined(DMNResultImpl result, DMNNode callerNode, DMNNode node) { if (node.getModelNamespace().equals(result.getContext().scopeNamespace().orElse(result.getModel().getNamespace()))) { return result.getContext().isDefined(node.getName()); - } else { + } else if (isInUnnamedImport(node, (DMNModelImpl) result.getModel())) { + // the node is an unnamed import + return result.getContext().isDefined(node.getName()); + } else { Optional importAlias = callerNode.getModelImportAliasFor(node.getModelNamespace(), node.getModelName()); if (importAlias.isPresent()) { Object aliasContext = result.getContext().get(importAlias.get()); diff --git a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNCompilerTest.java b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNCompilerTest.java index c52ba8da6d5..55ef34f927e 100644 --- a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNCompilerTest.java +++ b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNCompilerTest.java @@ -273,8 +273,18 @@ public void testImport() { } @Test - public void testEmptyNamedModelImport() { - final DMNRuntime runtime = createRuntimeWithAdditionalResources("valid_models/DMNv1_5/Importing_EmptyNamed_Model.dmn", + public void testEmptyNamedModelImportWithHrefNamespace() { + commonValidateUnnamedImport("valid_models/DMNv1_5/Importing_EmptyNamed_Model_With_Href_Namespace.dmn", "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } + + @Test + public void testEmptyNamedModelImportWithoutHrefNamespace() { + commonValidateUnnamedImport("valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn", "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } + + @Test + public void testOverridingEmptyNamedModelImport() { + final DMNRuntime runtime = createRuntimeWithAdditionalResources("valid_models/DMNv1_5/Importing_OverridingEmptyNamed_Model.dmn", this.getClass(), "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); @@ -286,7 +296,7 @@ public void testEmptyNamedModelImport() { } final DMNModel importingModel = runtime.getModel("http://www.trisotech.com/dmn/definitions/_f79aa7a4-f9a3-410a-ac95-bea496edabgc", - "Importing empty-named Model"); + "Importing empty-named Model"); assertThat(importingModel).isNotNull(); for (final DMNMessage message : importingModel.getMessages()) { LOG.debug("{}", message); @@ -319,10 +329,26 @@ public void testEmptyNamedModelImport() { } @Test - public void testOverridingEmptyNamedModelImport() { - final DMNRuntime runtime = createRuntimeWithAdditionalResources("valid_models/DMNv1_5/Importing_OverridingEmptyNamed_Model.dmn", + public void testWrongComparisonOps() { + final DMNRuntime runtime = createRuntime("WrongComparisonOps.dmn", this.getClass()); + final DMNModel dmnModel = runtime.getModel("http://www.trisotech.com/definitions/_a937d093-86d3-4306-8db8-1e7a33588b68", "Drawing 1"); + assertThat(dmnModel).isNotNull(); + assertThat(dmnModel.hasErrors()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).isFalse(); + assertThat(dmnModel.getMessages()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).hasSize(4); + assertThat(dmnModel.getMessages(DMNMessage.Severity.WARN)).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).hasSize(4); + assertThat(dmnModel.getMessages(DMNMessage.Severity.WARN) + .stream() + .filter(m -> m.getSourceId().equals("_d72d6fab-1e67-4fe7-9c12-54800d6fe294") || + m.getSourceId().equals("_2390dd99-094d-4f97-aecc-9cccb697ce05") || + m.getSourceId().equals("_0c292d34-498e-4b08-ae99-3c694197b69f") || + m.getSourceId().equals("_21c7d800-b806-4b2e-9a10-00828de7f2d2")) + .count()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).isEqualTo(4L); + } + + private void commonValidateUnnamedImport(String importingModelRef, String importedModelRef) { + final DMNRuntime runtime = createRuntimeWithAdditionalResources(importingModelRef, this.getClass(), - "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + importedModelRef); final DMNModel importedModel = runtime.getModel("http://www.trisotech.com/dmn/definitions/_f27bb64b-6fc7-4e1f-9848-11ba35e0df44", "Imported Model"); @@ -363,21 +389,4 @@ public void testOverridingEmptyNamedModelImport() { assertThat(allProperties).containsEntry("Imported Greeting", "Hello John!"); } } - - @Test - public void testWrongComparisonOps() { - final DMNRuntime runtime = createRuntime("WrongComparisonOps.dmn", this.getClass()); - final DMNModel dmnModel = runtime.getModel("http://www.trisotech.com/definitions/_a937d093-86d3-4306-8db8-1e7a33588b68", "Drawing 1"); - assertThat(dmnModel).isNotNull(); - assertThat(dmnModel.hasErrors()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).isFalse(); - assertThat(dmnModel.getMessages()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).hasSize(4); - assertThat(dmnModel.getMessages(DMNMessage.Severity.WARN)).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).hasSize(4); - assertThat(dmnModel.getMessages(DMNMessage.Severity.WARN) - .stream() - .filter(m -> m.getSourceId().equals("_d72d6fab-1e67-4fe7-9c12-54800d6fe294") || - m.getSourceId().equals("_2390dd99-094d-4f97-aecc-9cccb697ce05") || - m.getSourceId().equals("_0c292d34-498e-4b08-ae99-3c694197b69f") || - m.getSourceId().equals("_21c7d800-b806-4b2e-9a10-00828de7f2d2")) - .count()).as(DMNRuntimeUtil.formatMessages(dmnModel.getMessages())).isEqualTo(4L); - } } diff --git a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/compiler/UnnamedImportUtilsTest.java b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/compiler/UnnamedImportUtilsTest.java index e4e9309a970..2f317557a5b 100644 --- a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/compiler/UnnamedImportUtilsTest.java +++ b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/compiler/UnnamedImportUtilsTest.java @@ -26,23 +26,15 @@ public class UnnamedImportUtilsTest { @Test - public void isInUnnamedImportTrue() { - final DMNRuntime runtime = DMNRuntimeUtil.createRuntimeWithAdditionalResources("valid_models/DMNv1_5/Importing_EmptyNamed_Model" + - ".dmn", - this.getClass(), - "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + public void isInUnnamedImportTrueWithHrefNamespace() { + commonIsInUnnamedImportTrue("valid_models/DMNv1_5/Importing_EmptyNamed_Model_With_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } - final DMNModel importedModel = runtime.getModel("http://www.trisotech.com/dmn/definitions/_f27bb64b-6fc7-4e1f-9848-11ba35e0df44", - "Imported Model"); - assertThat(importedModel).isNotNull(); - final DMNModelImpl importingModel = (DMNModelImpl)runtime.getModel("http://www.trisotech.com/dmn/definitions/_f79aa7a4-f9a3-410a-ac95-bea496edabgc", - "Importing empty-named Model"); - assertThat(importingModel).isNotNull(); - importedModel.getDecisions().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); - importedModel.getBusinessKnowledgeModels().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); - importedModel.getDecisionServices().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); - importedModel.getInputs().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); - importedModel.getItemDefinitions().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + @Test + public void isInUnnamedImportTrueWithoutHrefNamespace() { + commonIsInUnnamedImportTrue("valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); } @Test @@ -81,10 +73,42 @@ public void addIfNotPresentTrue() throws IOException { } @Test - public void addIfNotPresentFalse() throws IOException { - final DMNRuntime runtime = DMNRuntimeUtil.createRuntimeWithAdditionalResources("valid_models/DMNv1_5/Importing_EmptyNamed_Model.dmn", + public void addIfNotPresentFalseWithHrefNamespace() throws IOException { + commonAddIfNotPresentFalse("valid_models/DMNv1_5/Importing_EmptyNamed_Model_With_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } + + @Test + public void addIfNotPresentFalseWithoutHrefNamespace() throws IOException { + commonAddIfNotPresentFalse("valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } + + private void commonIsInUnnamedImportTrue(String importingModelRef, String importedModelRef) { + final DMNRuntime runtime = DMNRuntimeUtil.createRuntimeWithAdditionalResources(importingModelRef, this.getClass(), - "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + importedModelRef); + + final DMNModel importedModel = runtime.getModel("http://www.trisotech.com/dmn/definitions/_f27bb64b-6fc7-4e1f" + + "-9848-11ba35e0df44", + "Imported Model"); + assertThat(importedModel).isNotNull(); + final DMNModelImpl importingModel = (DMNModelImpl) runtime.getModel("http://www.trisotech" + + ".com/dmn/definitions/_f79aa7a4" + + "-f9a3-410a-ac95-bea496edabgc", + "Importing empty-named Model"); + assertThat(importingModel).isNotNull(); + importedModel.getDecisions().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + importedModel.getBusinessKnowledgeModels().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + importedModel.getDecisionServices().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + importedModel.getInputs().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + importedModel.getItemDefinitions().forEach(node -> assertTrue(isInUnnamedImport(node, importingModel))); + } + + private void commonAddIfNotPresentFalse(String importingModelRef, String importedModelRef) throws IOException { + final DMNRuntime runtime = DMNRuntimeUtil.createRuntimeWithAdditionalResources(importingModelRef, + this.getClass(), + importedModelRef); final DMNModelImpl importingModel = (DMNModelImpl)runtime.getModel("http://www.trisotech.com/dmn/definitions/_f79aa7a4-f9a3-410a-ac95-bea496edabgc", "Importing empty-named Model"); assertThat(importingModel).isNotNull(); diff --git a/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Imported_Model_Unamed.dmn b/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Imported_Model_Unamed.dmn index 2c900040e20..e8a79c6e53b 100644 --- a/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Imported_Model_Unamed.dmn +++ b/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Imported_Model_Unamed.dmn @@ -23,7 +23,11 @@ number - + + + + + + + + + + + + + + + + + Local Hello( A Person ) + + + + + + + + + + + + + Say Hello( A Person ) + + + + + + + + + "Local Hello " + Person.name + "!" + + + + + diff --git a/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model.dmn b/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn similarity index 94% rename from kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model.dmn rename to kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn index 6bcd6e18387..eb567f30bb3 100644 --- a/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model.dmn +++ b/kie-dmn/kie-dmn-test-resources/src/test/resources/valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn @@ -23,11 +23,6 @@ drools:modelName="Imported Model" triso:fileId="eyJmIjp7InNrdSI6IjEwMmM0MDQ3LTg5NjctNGI3ZS1hODgxLTBhY2ZkNWJjOTAwMiIsIm5hbWUiOiJJbXBvcnRlZCBNb2RlbCJ9fQ==" triso:fileName="Edson Tirelli/Imported Model"/> - - - inputData = Map.of("A Person", prototype(entry("name", "Hugh"), entry("age", 32))); - evaluate(modelNamespace, modelName, importingModelFileName, inputData, importedModelFileName); + public void unnamedImportValidationWithHrefNamespace() { + commonUnnamedImportValidation("valid_models/DMNv1_5/Importing_EmptyNamed_Model_With_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); + } + + @Test + public void unnamedImportValidationWithoutHrefNamespace() { + commonUnnamedImportValidation("valid_models/DMNv1_5/Importing_EmptyNamed_Model_Without_Href_Namespace.dmn", + "valid_models/DMNv1_5/Imported_Model_Unamed.dmn"); } @Test @@ -131,6 +132,14 @@ public void typeConstraintsChecksValidation() { evaluate(modelNamespace, modelName, modelFileName, inputData); } + private void commonUnnamedImportValidation(String importingModelRef, String importedModelRef) { + String modelName = "Importing empty-named Model"; + String modelNamespace = "http://www.trisotech.com/dmn/definitions/_f79aa7a4-f9a3-410a-ac95-bea496edabgc"; + validate(importingModelRef, importedModelRef); + Map inputData = Map.of("A Person", prototype(entry("name", "Hugh"), entry("age", 32))); + evaluate(modelNamespace, modelName, importingModelRef, inputData, importedModelRef); + } + private void validate(String modelFileName, String... otherFileNames) { List allModelsFileNames = new ArrayList<>(); allModelsFileNames.add(modelFileName);