This is an automated email from the ASF dual-hosted git repository.
gitgabrio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/main by this push:
new 06d9380f74 [incubator-kie-issues#2048] DMN Model Validation failed -
Getting Index 0 out of bounds for length 0 (#6413)
06d9380f74 is described below
commit 06d9380f74ce10d0204c8219c72252e2faab73a1
Author: ChinchuAjith <[email protected]>
AuthorDate: Fri Aug 8 14:36:53 2025 +0530
[incubator-kie-issues#2048] DMN Model Validation failed - Getting Index 0
out of bounds for length 0 (#6413)
* Fixing index out of bound and Required input not foubd issues
* Fixing review comments
* Fixing review comments
* Adding license header to test dmn files
* unit tests
* Fixing review comments. adding check to verify source and target classes
* removing unused dmn files
---
.../kie/dmn/core/compiler/UnnamedImportUtils.java | 48 ++++++++---
.../dmn/core/compiler/UnnamedImportUtilsTest.java | 92 ++++++++++++++++++----
.../DMNv1_3/dmn-validation-rules-dmndi.drl | 2 +-
3 files changed, 112 insertions(+), 30 deletions(-)
diff --git
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/UnnamedImportUtils.java
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/UnnamedImportUtils.java
index e47a6e10a3..5e460cab2e 100644
---
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/UnnamedImportUtils.java
+++
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/UnnamedImportUtils.java
@@ -20,12 +20,11 @@ package org.kie.dmn.core.compiler;
import java.util.Collection;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.kie.dmn.api.core.ast.DMNNode;
import org.kie.dmn.core.impl.DMNModelImpl;
-import org.kie.dmn.model.api.Definitions;
-import org.kie.dmn.model.api.Import;
-import org.kie.dmn.model.api.NamedElement;
+import org.kie.dmn.model.api.*;
/**
* Class meant to provide helper methods to deal with unnamed model imports
@@ -65,22 +64,45 @@ public class UnnamedImportUtils {
// incubator-kie-issues#852: The idea is to not treat the anonymous
models as import, but to "merge" them with original one,
// Here we try to put all the definitions from the "imported" model
inside the parent one
parentDefinitions.getArtifact().addAll(mergedDefinitions.getArtifact());
-
- addIfNotPresent(parentDefinitions.getDecisionService(),
mergedDefinitions.getDecisionService());
- addIfNotPresent(parentDefinitions.getBusinessContextElement(),
mergedDefinitions.getBusinessContextElement());
- addIfNotPresent(parentDefinitions.getDrgElement(),
mergedDefinitions.getDrgElement());
- addIfNotPresent(parentDefinitions.getImport(),
mergedDefinitions.getImport());
- addIfNotPresent(parentDefinitions.getItemDefinition(),
mergedDefinitions.getItemDefinition());
+ addIfNotPresent(parentDefinitions.getDecisionService(),
mergedDefinitions.getDecisionService(), DecisionService.class);
+ addIfNotPresent(parentDefinitions.getBusinessContextElement(),
mergedDefinitions.getBusinessContextElement(), BusinessContextElement.class);
+ addIfNotPresent(parentDefinitions.getDrgElement(),
mergedDefinitions.getDrgElement(), DRGElement.class);
+ addIfNotPresent(parentDefinitions.getImport(),
mergedDefinitions.getImport(), Import.class);
+ addIfNotPresent(parentDefinitions.getItemDefinition(),
mergedDefinitions.getItemDefinition(), ItemDefinition.class);
mergedDefinitions.getChildren().forEach(parentDefinitions::addChildren);
}
- static <T extends NamedElement> void addIfNotPresent(Collection<T> target,
Collection<T> source) {
- source.forEach(sourceElement -> addIfNotPresent(target,
sourceElement));
+ static <T extends NamedElement> void addIfNotPresent(Collection<T> target,
Collection<T> source, Class expectedClass) {
+ source.forEach(sourceElement -> {
+ if(!expectedClass.isAssignableFrom(sourceElement.getClass())) {
+ throw new IllegalStateException("type mismatch : " + "Expected
" + expectedClass.getName() + ", but found " +
sourceElement.getClass().getName());
+ }
+ addIfNotPresent(target, sourceElement, expectedClass);
+ });
+
}
- static <T extends NamedElement> void addIfNotPresent(Collection<T> target,
T source) {
- if (target.stream().noneMatch(namedElement ->
Objects.equals(namedElement.getName(), source.getName()))) {
+ static <T extends NamedElement> void addIfNotPresent(Collection<T> target,
T source, Class expectedClass) {
+ if (checkIfNotPresent(target, source, expectedClass)) {
target.add(source);
}
}
+
+ static <T extends NamedElement> boolean checkIfNotPresent(Collection<T>
target, T source, Class expectedClass) {
+ for (T namedElement : target) {
+ if(!expectedClass.isAssignableFrom(namedElement.getClass()) ) {
+ throw new IllegalStateException("type mismatch : " + "Expected
" + expectedClass.getName() + ", but found " +
namedElement.getClass().getName());
+ }
+ if (Objects.equals(namedElement.getName(), source.getName())) {
+ if (!(namedElement instanceof Import &&
+ namedElement.getName() != null &&
+ namedElement.getName().isEmpty())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
}
\ No newline at end of file
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 34898662b2..043e64a725 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
@@ -25,6 +25,7 @@ import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import org.junit.jupiter.api.Test;
import org.kie.dmn.api.core.DMNModel;
@@ -32,12 +33,15 @@ import org.kie.dmn.api.core.DMNRuntime;
import org.kie.dmn.backend.marshalling.v1x.DMNMarshallerFactory;
import org.kie.dmn.core.impl.DMNModelImpl;
import org.kie.dmn.core.util.DMNRuntimeUtil;
-import org.kie.dmn.model.api.Definitions;
-import org.kie.dmn.model.api.NamedElement;
+import org.kie.dmn.model.api.*;
+import org.kie.dmn.model.v1_5.TImport;
+import org.kie.dmn.model.v1_5.TInputData;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.kie.dmn.core.compiler.UnnamedImportUtils.addIfNotPresent;
import static org.kie.dmn.core.compiler.UnnamedImportUtils.isInUnnamedImport;
+import static org.kie.dmn.core.compiler.UnnamedImportUtils.checkIfNotPresent;
class UnnamedImportUtilsTest {
@@ -80,11 +84,11 @@ class UnnamedImportUtilsTest {
try (InputStream is = importedModelFileResource.openStream()) {
String xml = new String(is.readAllBytes(), StandardCharsets.UTF_8);
Definitions definitions =
DMNMarshallerFactory.newDefaultMarshaller().unmarshal(xml);
- assertThat(definitions.getDecisionService()).allMatch(this::added);
-
assertThat(definitions.getBusinessContextElement()).allMatch(this::added);
- assertThat(definitions.getDrgElement()).allMatch(this::added);
- assertThat(definitions.getImport()).allMatch(this::added);
- assertThat(definitions.getItemDefinition()).allMatch(this::added);
+ assertThat(definitions.getDecisionService()).allMatch(source ->
added(source, DecisionService.class));
+
assertThat(definitions.getBusinessContextElement()).allMatch(source ->
added(source, BusinessContextElement.class));
+ assertThat(definitions.getDrgElement()).allMatch(source ->
added(source, DRGElement.class));
+ assertThat(definitions.getImport()).allMatch(source ->
added(source, Import.class));
+ assertThat(definitions.getItemDefinition()).allMatch(source ->
added(source, ItemDefinition.class));
}
}
@@ -100,6 +104,58 @@ class UnnamedImportUtilsTest {
"valid_models/DMNv1_5/Imported_Model_Unamed.dmn");
}
+ @Test
+ void checkIfNotPresentWithMatchingName() {
+ TInputData targetElement = new TInputData();
+ targetElement.setName("modelName");
+ TInputData sourceElement = new TInputData();
+ sourceElement.setName("modelName");
+ boolean result =
UnnamedImportUtils.checkIfNotPresent(List.of(targetElement), sourceElement,
TInputData.class);
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ void checkIfNotPresentWithNonMatchingName() {
+ TInputData targetElement = new TInputData();
+ targetElement.setName("targetName");
+ TInputData sourceElement = new TInputData();
+ sourceElement.setName("sourceName");
+ boolean result =
UnnamedImportUtils.checkIfNotPresent(List.of(targetElement), sourceElement,
TInputData.class);
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ void checkIfNotPresentWithNamedImport() {
+ TImport unnamedImport = new TImport();
+ unnamedImport.setName("targetName");
+ TImport source = new TImport();
+ source.setName("sourceName");
+ boolean result =
UnnamedImportUtils.checkIfNotPresent(List.of(unnamedImport), source,
TImport.class);
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ void checkIfNotPresentWithEmptyNamedImport() {
+ TImport unnamedImport = new TImport();
+ unnamedImport.setName("");
+ TImport source = new TImport();
+ source.setName("");
+ boolean result =
UnnamedImportUtils.checkIfNotPresent(List.of(unnamedImport), source,
TImport.class);
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ void checkIfNotPresentWithDifferentTargetClass() {
+ TInputData targetElement = new TInputData();
+ targetElement.setName("modelName");
+ TImport source = new TImport();
+ source.setName("modelName");
+ assertThatThrownBy(() ->
UnnamedImportUtils.checkIfNotPresent(List.of(targetElement), source,
DecisionService.class))
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessageContaining("type mismatch");
+ }
+
+
private void commonIsInUnnamedImportTrue(String importingModelRef, String
importedModelRef) {
final DMNRuntime runtime =
DMNRuntimeUtil.createRuntimeWithAdditionalResources(importingModelRef,
this.getClass(),
@@ -136,21 +192,25 @@ class UnnamedImportUtilsTest {
try (InputStream is = importedModelFileResource.openStream()) {
String importedXml = new String(is.readAllBytes(),
StandardCharsets.UTF_8);
Definitions importedDefinitions =
DMNMarshallerFactory.newDefaultMarshaller().unmarshal(importedXml);
-
assertThat(importedDefinitions.getDecisionService()).noneMatch(definition ->
added(importingDefinitions.getDecisionService(), definition));
-
assertThat(importedDefinitions.getBusinessContextElement()).noneMatch(definition
-> added(importingDefinitions.getBusinessContextElement(), definition));
-
assertThat(importedDefinitions.getDrgElement()).noneMatch(definition ->
added(importingDefinitions.getDrgElement(), definition));
- assertThat(importedDefinitions.getImport()).noneMatch(definition
-> added(importingDefinitions.getImport(), definition));
-
assertThat(importedDefinitions.getItemDefinition()).noneMatch(definition ->
added(importingDefinitions.getItemDefinition(), definition));
+
assertThat(importedDefinitions.getDecisionService()).noneMatch(definition ->
added(importingDefinitions.getDecisionService(), definition,
DecisionService.class));
+
assertThat(importedDefinitions.getBusinessContextElement()).noneMatch(definition
-> added(importingDefinitions.getBusinessContextElement(), definition,
BusinessContextElement.class));
+
assertThat(importedDefinitions.getDrgElement()).noneMatch(definition ->
added(importingDefinitions.getDrgElement(), definition, DRGElement.class));
+ assertThat(importedDefinitions.getImport()).noneMatch(definition
-> added(importingDefinitions.getImport(), definition, Import.class));
+
assertThat(importedDefinitions.getItemDefinition()).noneMatch(definition ->
added(importingDefinitions.getItemDefinition(), definition,
ItemDefinition.class));
}
}
- private <T extends NamedElement> boolean added(T source) {
- return added(new ArrayList<>(), source);
+ private <T extends NamedElement> boolean added(T source, Class
expectedClass) {
+ return added(new ArrayList<>(), source, expectedClass);
}
- private <T extends NamedElement> boolean added(Collection<T> target, T
source) {
- addIfNotPresent(target, source);
+ private <T extends NamedElement> boolean added(Collection<T> target, T
source, Class expectedClass) {
+ addIfNotPresent(target, source, expectedClass);
return target.contains(source);
}
+ private <T extends NamedElement> boolean checkIfNotPresent(Collection<T>
target, T source, Class expectedClass) {
+ return UnnamedImportUtils.checkIfNotPresent(target, source,
expectedClass);
+ }
+
}
\ No newline at end of file
diff --git
a/kie-dmn/kie-dmn-validation/src/main/resources/org/kie/dmn/validation/DMNv1_3/dmn-validation-rules-dmndi.drl
b/kie-dmn/kie-dmn-validation/src/main/resources/org/kie/dmn/validation/DMNv1_3/dmn-validation-rules-dmndi.drl
index 9f535472de..ffafacec06 100644
---
a/kie-dmn/kie-dmn-validation/src/main/resources/org/kie/dmn/validation/DMNv1_3/dmn-validation-rules-dmndi.drl
+++
b/kie-dmn/kie-dmn-validation/src/main/resources/org/kie/dmn/validation/DMNv1_3/dmn-validation-rules-dmndi.drl
@@ -102,7 +102,7 @@ when
$definitions : Definitions($nsContext : nsContext)
$import : Import(DMNImportsUtil.whichImportType(this) ==
DMNImportsUtil.ImportType.DMN, namespace == $nsContext[$prefix])
$importDef : Definitions(namespace == $import.namespace) from entry-point
"DMNImports"
- $importRelatedDefinitions : Definitions(drgElement[0].id == $localPart)
from entry-point "RelatedImports"
+ $importRelatedDefinitions : Definitions(drgElement.empty == false,
drgElement[0].id == $localPart) from entry-point "RelatedImports"
not DRGElement(id == $localPart) from $importDef.drgElement
not DRGElement(id == $localPart) from $importRelatedDefinitions.drgElement
not DRGElement(id == $localPart)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]