You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by gi...@apache.org on 2025/02/11 12:36:26 UTC
(incubator-kie-kogito-apps) branch main updated: [incubator-kie-issues#1805] Fix serialization/deserialization inside JITExecutor (#2190)
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-kogito-apps.git
The following commit(s) were added to refs/heads/main by this push:
new ae4b1971c [incubator-kie-issues#1805] Fix serialization/deserialization inside JITExecutor (#2190)
ae4b1971c is described below
commit ae4b1971cfa674b1d325ecc9307740ee4f7d83ea
Author: Gabriele Cardosi <ga...@gmail.com>
AuthorDate: Tue Feb 11 13:36:22 2025 +0100
[incubator-kie-issues#1805] Fix serialization/deserialization inside JITExecutor (#2190)
* [incubator-kie-issues#1805] Fix serialization/deserialization inside JITExecutor
* [incubator-kie-issues#1805] Cleanup
* [incubator-kie-issues#1805] Add multiple hit test on multiple model payload
* [incubator-kie-issues#1805] Fix formatting
---------
Co-authored-by: Gabriele-Cardosi <ga...@ibm.com>
---
.../kie/kogito/jitexecutor/dmn/DMNEvaluator.java | 3 +-
.../kie/kogito/jitexecutor/dmn/JITDMNListener.java | 4 +-
.../kogito/jitexecutor/dmn/JITDMNServiceImpl.java | 20 ++--
.../dmn/responses/JITDMNDecisionResult.java | 61 ++++++++---
.../jitexecutor/dmn/responses/JITDMNMessage.java | 25 +++++
.../jitexecutor/dmn/responses/JITDMNResult.java | 88 +++++++++------
.../jitexecutor/dmn/api/JITDMNResourceTest.java | 45 ++++----
.../jitexecutor/dmn/api/MultipleModelsTest.java | 122 ++++++++++++++++++---
.../dmn/responses/JITDMNResultTest.java | 8 +-
9 files changed, 276 insertions(+), 100 deletions(-)
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
index 841e8d40a..0f364d000 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/DMNEvaluator.java
@@ -71,6 +71,7 @@ public class DMNEvaluator {
.buildConfiguration()
.fromResources(resources.values())
.getOrElseThrow(RuntimeException::new);
+ dmnRuntime.addListener(new JITDMNListener());
DMNModel mainModel = null;
for (DMNModel m : dmnRuntime.getModels()) {
if (m.getResource().getSourcePath().equals(payload.getMainURI())) {
@@ -125,7 +126,7 @@ public class DMNEvaluator {
.findFirst()
.map(JITDMNListener.class::cast)
.map(JITDMNListener::getDecisionEvaluationHitIdsMap);
- return new JITDMNResult(getNamespace(), getName(), dmnResult,
+ return JITDMNResult.of(getNamespace(), getName(), dmnResult,
decisionEvaluationHitIdsMap.orElse(Collections.emptyMap()));
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNListener.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNListener.java
index 6b1fc2572..46ca40651 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNListener.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNListener.java
@@ -100,11 +100,11 @@ public class JITDMNListener implements DMNRuntimeEventListener {
}
private void logEvent(DMNEvent toLog) {
- LOGGER.info("{} event {}", toLog.getClass().getSimpleName(), toLog);
+ LOGGER.debug("{} event {}", toLog.getClass().getSimpleName(), toLog);
}
private void logEvent(AfterConditionalEvaluationEvent toLog) {
- LOGGER.info("{} event {}", toLog.getClass().getSimpleName(), toLog);
+ LOGGER.debug("{} event {}", toLog.getClass().getSimpleName(), toLog);
}
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNServiceImpl.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNServiceImpl.java
index bb0b6513c..13f71b24d 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNServiceImpl.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/JITDMNServiceImpl.java
@@ -19,6 +19,7 @@
package org.kie.kogito.jitexecutor.dmn;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -29,7 +30,6 @@ import java.util.stream.Collectors;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.kie.dmn.api.core.DMNModel;
-import org.kie.dmn.api.core.DMNResult;
import org.kie.dmn.api.core.ast.DecisionNode;
import org.kie.kogito.explainability.Config;
import org.kie.kogito.explainability.api.FeatureImportanceModel;
@@ -79,6 +79,12 @@ public class JITDMNServiceImpl implements JITDMNService {
return dmnEvaluator.evaluate(context);
}
+ @Override
+ public JITDMNResult evaluateModel(MultipleResourcesPayload payload, Map<String, Object> context) {
+ DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
+ return dmnEvaluator.evaluate(context);
+ }
+
@Override
public DMNResultWithExplanation evaluateModelAndExplain(String modelXML, Map<String, Object> context) {
DMNEvaluator dmnEvaluator = DMNEvaluator.fromXML(modelXML);
@@ -94,7 +100,7 @@ public class JITDMNServiceImpl implements JITDMNService {
public DMNResultWithExplanation evaluateModelAndExplain(DMNEvaluator dmnEvaluator, Map<String, Object> context) {
LocalDMNPredictionProvider localDMNPredictionProvider = new LocalDMNPredictionProvider(dmnEvaluator);
- DMNResult dmnResult = dmnEvaluator.evaluate(context);
+ JITDMNResult dmnResult = dmnEvaluator.evaluate(context);
Prediction prediction = new SimplePrediction(LocalDMNPredictionProvider.toPredictionInput(context),
LocalDMNPredictionProvider.toPredictionOutput(dmnResult));
@@ -113,14 +119,14 @@ public class JITDMNServiceImpl implements JITDMNService {
Thread.currentThread().interrupt();
}
return new DMNResultWithExplanation(
- new JITDMNResult(dmnEvaluator.getNamespace(), dmnEvaluator.getName(), dmnResult),
+ JITDMNResult.of(dmnEvaluator.getNamespace(), dmnEvaluator.getName(), dmnResult, Collections.emptyMap()),
new SalienciesResponse(EXPLAINABILITY_FAILED, EXPLAINABILITY_FAILED_MESSAGE, null));
}
List<SaliencyResponse> saliencyModelResponse = buildSalienciesResponse(dmnEvaluator.getDmnModel(), saliencyMap);
return new DMNResultWithExplanation(
- new JITDMNResult(dmnEvaluator.getNamespace(), dmnEvaluator.getName(), dmnResult),
+ JITDMNResult.of(dmnEvaluator.getNamespace(), dmnEvaluator.getName(), dmnResult, Collections.emptyMap()),
new SalienciesResponse(EXPLAINABILITY_SUCCEEDED, null, saliencyModelResponse));
}
@@ -145,10 +151,4 @@ public class JITDMNServiceImpl implements JITDMNService {
return new FeatureImportanceModel(model.getFeature().getName(), model.getScore());
}
- @Override
- public JITDMNResult evaluateModel(MultipleResourcesPayload payload, Map<String, Object> context) {
- DMNEvaluator dmnEvaluator = DMNEvaluator.fromMultiple(payload);
- DMNResult dmnResult = dmnEvaluator.evaluate(context);
- return new JITDMNResult(dmnEvaluator.getNamespace(), dmnEvaluator.getName(), dmnResult);
- }
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNDecisionResult.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNDecisionResult.java
index 5ff45c7ba..4093de947 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNDecisionResult.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNDecisionResult.java
@@ -23,6 +23,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
import org.kie.dmn.api.core.DMNDecisionResult;
import org.kie.dmn.api.core.DMNMessage;
@@ -52,14 +54,14 @@ public class JITDMNDecisionResult implements Serializable,
}
public static JITDMNDecisionResult of(DMNDecisionResult value, Map<String, Integer> decisionEvaluationHitIdsMap) {
- JITDMNDecisionResult res = new JITDMNDecisionResult();
- res.decisionId = value.getDecisionId();
- res.decisionName = value.getDecisionName();
- res.setResult(value.getResult());
- res.setMessages(value.getMessages());
- res.status = value.getEvaluationStatus();
- res.evaluationHitIds = decisionEvaluationHitIdsMap;
- return res;
+ JITDMNDecisionResult toReturn = new JITDMNDecisionResult();
+ toReturn.decisionId = value.getDecisionId();
+ toReturn.decisionName = value.getDecisionName();
+ toReturn.result = internalGetResult(value.getResult());
+ toReturn.messages = internalGetMessages(value.getMessages());
+ toReturn.status = value.getEvaluationStatus();
+ toReturn.evaluationHitIds = decisionEvaluationHitIdsMap;
+ return toReturn;
}
@Override
@@ -95,18 +97,15 @@ public class JITDMNDecisionResult implements Serializable,
}
public void setResult(Object result) {
- this.result = MarshallingStubUtils.stubDMNResult(result, String::valueOf);
+ this.result = result;
}
public List<DMNMessage> getMessages() {
return (List) messages;
}
- public void setMessages(List<DMNMessage> messages) {
- this.messages = new ArrayList<>();
- for (DMNMessage m : messages) {
- this.messages.add(JITDMNMessage.of(m));
- }
+ public void setMessages(List<JITDMNMessage> messages) {
+ this.messages = messages;
}
public Map<String, Integer> getEvaluationHitIds() {
@@ -121,4 +120,38 @@ public class JITDMNDecisionResult implements Serializable,
public boolean hasErrors() {
return messages != null && messages.stream().anyMatch(m -> m.getSeverity() == DMNMessage.Severity.ERROR);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof JITDMNDecisionResult that)) {
+ return false;
+ }
+ return Objects.equals(decisionId, that.decisionId) && Objects.equals(decisionName, that.decisionName) && Objects.equals(result, that.result) && Objects.equals(messages, that.messages)
+ && status == that.status && Objects.equals(evaluationHitIds, that.evaluationHitIds);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(decisionId, decisionName, result, messages, status, evaluationHitIds);
+ }
+
+ @Override
+ public String toString() {
+ return "JITDMNDecisionResult{" +
+ "decisionId='" + decisionId + '\'' +
+ ", decisionName='" + decisionName + '\'' +
+ ", result=" + result +
+ ", messages=" + messages +
+ ", status=" + status +
+ ", evaluationHitIds=" + evaluationHitIds +
+ '}';
+ }
+
+ private static Object internalGetResult(Object result) {
+ return MarshallingStubUtils.stubDMNResult(result, String::valueOf);
+ }
+
+ private static List<JITDMNMessage> internalGetMessages(List<DMNMessage> messages) {
+ return messages.stream().map(JITDMNMessage::of).collect(Collectors.toList());
+ }
}
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNMessage.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNMessage.java
index fb90a077a..c6ffd042d 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNMessage.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNMessage.java
@@ -19,6 +19,7 @@
package org.kie.kogito.jitexecutor.dmn.responses;
import java.io.Serializable;
+import java.util.Objects;
import org.kie.dmn.api.core.DMNMessage;
import org.kie.dmn.api.core.DMNMessageType;
@@ -175,4 +176,28 @@ public class JITDMNMessage implements Serializable, DMNMessage {
public String getText() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof JITDMNMessage that)) {
+ return false;
+ }
+ return severity == that.severity && Objects.equals(message, that.message) && messageType == that.messageType && Objects.equals(sourceId, that.sourceId) && Objects.equals(path, that.path);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(severity, message, messageType, sourceId, path);
+ }
+
+ @Override
+ public String toString() {
+ return "JITDMNMessage{" +
+ "severity=" + severity +
+ ", message='" + message + '\'' +
+ ", messageType=" + messageType +
+ ", sourceId='" + sourceId + '\'' +
+ ", path='" + path + '\'' +
+ '}';
+ }
}
\ No newline at end of file
diff --git a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResult.java b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResult.java
index 9d388b172..2466c238a 100644
--- a/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResult.java
+++ b/jitexecutor/jitexecutor-dmn/src/main/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResult.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.stream.Collectors;
import org.kie.dmn.api.core.DMNContext;
@@ -48,22 +49,20 @@ public class JITDMNResult implements Serializable,
private List<JITDMNMessage> messages = new ArrayList<>();
- private Map<String, JITDMNDecisionResult> decisionResults = new HashMap<>();
+ private List<DMNDecisionResult> decisionResults;
- public JITDMNResult() {
- // Intentionally blank.
- }
-
- public JITDMNResult(String namespace, String modelName, org.kie.dmn.api.core.DMNResult dmnResult) {
- this(namespace, modelName, dmnResult, Collections.emptyMap());
+ public static JITDMNResult of(String namespace, String modelName, org.kie.dmn.api.core.DMNResult dmnResult, Map<String, Map<String, Integer>> decisionEvaluationHitIdsMap) {
+ JITDMNResult toReturn = new JITDMNResult();
+ toReturn.namespace = namespace;
+ toReturn.modelName = modelName;
+ toReturn.dmnContext = internalGetContext(dmnResult.getContext().getAll());
+ toReturn.messages = internalGetMessages(dmnResult.getMessages());
+ toReturn.decisionResults = internalGetDecisionResults(dmnResult.getDecisionResults(), decisionEvaluationHitIdsMap);
+ return toReturn;
}
- public JITDMNResult(String namespace, String modelName, org.kie.dmn.api.core.DMNResult dmnResult, Map<String, Map<String, Integer>> decisionEvaluationHitIdsMap) {
- this.namespace = namespace;
- this.modelName = modelName;
- this.setDmnContext(dmnResult.getContext().getAll());
- this.setMessages(dmnResult.getMessages());
- this.internalSetDecisionResults(dmnResult.getDecisionResults(), decisionEvaluationHitIdsMap);
+ public JITDMNResult() {
+ // Intentionally blank.
}
public String getNamespace() {
@@ -87,24 +86,11 @@ public class JITDMNResult implements Serializable,
}
public void setDmnContext(Map<String, Object> dmnContext) {
- this.dmnContext = new HashMap<>();
- for (Entry<String, Object> kv : dmnContext.entrySet()) {
- this.dmnContext.put(kv.getKey(), MarshallingStubUtils.stubDMNResult(kv.getValue(), String::valueOf));
- }
+ this.dmnContext = dmnContext;
}
- public void setMessages(List<? extends DMNMessage> messages) {
- this.messages = new ArrayList<>();
- for (DMNMessage m : messages) {
- this.messages.add(JITDMNMessage.of(m));
- }
- }
-
- public void setDecisionResults(List<? extends DMNDecisionResult> decisionResults) {
- this.decisionResults = new HashMap<>();
- for (DMNDecisionResult dr : decisionResults) {
- this.decisionResults.put(dr.getDecisionId(), JITDMNDecisionResult.of(dr));
- }
+ public void setMessages(List<JITDMNMessage> messages) {
+ this.messages = messages;
}
@JsonIgnore
@@ -130,14 +116,18 @@ public class JITDMNResult implements Serializable,
return messages.stream().anyMatch(m -> DMNMessage.Severity.ERROR.equals(m.getSeverity()));
}
+ public void setDecisionResults(List<DMNDecisionResult> decisionResults) {
+ this.decisionResults = decisionResults;
+ }
+
@Override
public List<DMNDecisionResult> getDecisionResults() {
- return new ArrayList<>(decisionResults.values());
+ return decisionResults;
}
@Override
public DMNDecisionResult getDecisionResultByName(String name) {
- return decisionResults.values().stream()
+ return decisionResults.stream()
.filter(dr -> dr.getDecisionName().equals(name))
.findFirst()
.orElseThrow(() -> new RuntimeException("Unknown decision result name."));
@@ -145,7 +135,24 @@ public class JITDMNResult implements Serializable,
@Override
public DMNDecisionResult getDecisionResultById(String id) {
- return decisionResults.get(id);
+ return decisionResults.stream()
+ .filter(dr -> dr.getDecisionId().equals(id))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Unknown decision result id."));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof JITDMNResult that)) {
+ return false;
+ }
+ return Objects.equals(namespace, that.namespace) && Objects.equals(modelName, that.modelName) && Objects.equals(dmnContext, that.dmnContext) && Objects.equals(messages, that.messages)
+ && Objects.equals(decisionResults, that.decisionResults);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(namespace, modelName, dmnContext, messages, decisionResults);
}
@Override
@@ -159,10 +166,19 @@ public class JITDMNResult implements Serializable,
.append("]").toString();
}
- private void internalSetDecisionResults(List<? extends DMNDecisionResult> decisionResults, Map<String, Map<String, Integer>> decisionEvaluationHitIdsMap) {
- this.decisionResults = new HashMap<>();
- for (DMNDecisionResult dr : decisionResults) {
- this.decisionResults.put(dr.getDecisionId(), JITDMNDecisionResult.of(dr, decisionEvaluationHitIdsMap.getOrDefault(dr.getDecisionName(), Collections.emptyMap())));
+ private static Map<String, Object> internalGetContext(Map<String, Object> source) {
+ Map<String, Object> toReturn = new HashMap<>();
+ for (Entry<String, Object> kv : source.entrySet()) {
+ toReturn.put(kv.getKey(), MarshallingStubUtils.stubDMNResult(kv.getValue(), String::valueOf));
}
+ return toReturn;
+ }
+
+ private static List<JITDMNMessage> internalGetMessages(List<? extends DMNMessage> messages) {
+ return messages.stream().map(JITDMNMessage::of).collect(Collectors.toList());
+ }
+
+ private static List<DMNDecisionResult> internalGetDecisionResults(List<? extends DMNDecisionResult> decisionResults, Map<String, Map<String, Integer>> decisionEvaluationHitIdsMap) {
+ return decisionResults.stream().map(dr -> JITDMNDecisionResult.of(dr, decisionEvaluationHitIdsMap.getOrDefault(dr.getDecisionName(), Collections.emptyMap()))).collect(Collectors.toList());
}
}
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
index 4f6be26da..b14a775c3 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/JITDMNResourceTest.java
@@ -51,14 +51,15 @@ import static org.kie.kogito.jitexecutor.dmn.TestingUtils.getModelFromIoUtils;
@QuarkusTest
public class JITDMNResourceTest {
- private static String model;
- private static String invalidModel;
+ private static String invalidModel1x;
+ private static String invalidModel15;
+ private static String validModel15;
private static String modelWithExtensionElements;
private static String modelWithMultipleEvaluationHitIds;
private static final ObjectMapper MAPPER = new ObjectMapper();
- private static final String EVALUATION_HIT_IDS_FIELD_NAME = "evaluationHitIds";
+ static final String EVALUATION_HIT_IDS_FIELD_NAME = "evaluationHitIds";
static {
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -66,15 +67,16 @@ public class JITDMNResourceTest {
@BeforeAll
public static void setup() throws IOException {
- model = getModelFromIoUtils("invalid_models/DMNv1_x/test.dmn");
- invalidModel = getModelFromIoUtils("invalid_models/DMNv1_5/DMN-Invalid.dmn");
+ invalidModel1x = getModelFromIoUtils("invalid_models/DMNv1_x/test.dmn");
+ invalidModel15 = getModelFromIoUtils("invalid_models/DMNv1_5/DMN-Invalid.dmn");
+ validModel15 = getModelFromIoUtils("valid_models/DMNv1_5/RiskScore_Simple.dmn");
modelWithExtensionElements = getModelFromIoUtils("valid_models/DMNv1_x/testWithExtensionElements.dmn");
modelWithMultipleEvaluationHitIds = getModelFromIoUtils("valid_models/DMNv1_5/MultipleHitRules.dmn");
}
@Test
void testjitEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(model, buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel1x, buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -182,14 +184,17 @@ public class JITDMNResourceTest {
@Test
void testjitExplainabilityEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(model, buildContext());
+ Map<String, Object> context = new HashMap<>();
+ context.put("Credit Score", "Poor");
+ context.put("DTI", 33);
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(validModel15, context);
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
.when().post("/jitdmn/evaluateAndExplain")
.then()
.statusCode(200)
- .body(containsString("dmnResult"), containsString("saliencies"), containsString("xls2dmn"),
+ .body(containsString("dmnResult"), containsString("saliencies"), containsString("DMN_A77074C1-21FE-4F7E-9753-F84661569AFC"),
containsString("featureName"));
}
@@ -211,7 +216,7 @@ public class JITDMNResourceTest {
@Test
void testjitEndpointFailure() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel15, buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -223,7 +228,7 @@ public class JITDMNResourceTest {
@Test
void testjitdmnEvaluateInvalidModel() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildInvalidModelContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel15, buildInvalidModelContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -235,7 +240,7 @@ public class JITDMNResourceTest {
@Test
void testjitdmnEvaluateAndExplainInvalidModel() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel, buildInvalidModelContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(invalidModel15, buildInvalidModelContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -245,15 +250,7 @@ public class JITDMNResourceTest {
.body(containsString("Error compiling FEEL expression 'Person Age >= 18' for name 'Can Drive?' on node 'Can Drive?': syntax error near 'Age'"));
}
- private Map<String, Object> buildContext() {
- Map<String, Object> context = new HashMap<>();
- context.put("FICO Score", 800);
- context.put("DTI Ratio", .1);
- context.put("PITI Ratio", .1);
- return context;
- }
-
- private Map<String, Object> buildMultipleHitContext() {
+ static Map<String, Object> buildMultipleHitContext() {
final List<BigDecimal> numbers = new ArrayList<>();
numbers.add(BigDecimal.valueOf(10));
numbers.add(BigDecimal.valueOf(2));
@@ -263,6 +260,14 @@ public class JITDMNResourceTest {
return context;
}
+ private Map<String, Object> buildContext() {
+ Map<String, Object> context = new HashMap<>();
+ context.put("FICO Score", 800);
+ context.put("DTI Ratio", .1);
+ context.put("PITI Ratio", .1);
+ return context;
+ }
+
private Map<String, Object> buildInvalidModelContext() {
Map<String, Object> context = new HashMap<>();
context.put("Can Drive?", false);
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/MultipleModelsTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/MultipleModelsTest.java
index e0405f538..cd4fa8b8b 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/MultipleModelsTest.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/api/MultipleModelsTest.java
@@ -22,7 +22,10 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.kie.dmn.api.core.DMNDecisionResult;
@@ -37,15 +40,21 @@ import org.kie.kogito.jitexecutor.dmn.responses.JITDMNResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
+import io.restassured.response.Response;
+import io.restassured.response.ResponseBody;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
@@ -54,15 +63,21 @@ import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.kie.kogito.jitexecutor.dmn.TestingUtils.getModelFromIoUtils;
+import static org.kie.kogito.jitexecutor.dmn.api.JITDMNResourceTest.EVALUATION_HIT_IDS_FIELD_NAME;
+import static org.kie.kogito.jitexecutor.dmn.api.JITDMNResourceTest.buildMultipleHitContext;
@QuarkusTest
public class MultipleModelsTest {
private static final Logger LOG = LoggerFactory.getLogger(MultipleModelsTest.class);
- private static final String URI1 = "invalid_models/DMNv1_x/multiple/importing.dmn";
- private static final String URI2 = "valid_models/DMNv1_x/multiple/stdlib.dmn";
- private static ResourceWithURI model1;
- private static ResourceWithURI model2;
+ private static final String IMPORTING_MODEL_URI = "invalid_models/DMNv1_x/multiple/importing.dmn";
+ private static final String STDLIB_MODEL_URI = "valid_models/DMNv1_x/multiple/stdlib.dmn";
+ private static final String SAMPLE_MODEL_URI = "valid_models/DMNv1_5/Sample.dmn";
+ private static final String MULTIPLE_HIT_MODEL_URI = "valid_models/DMNv1_5/MultipleHitRules.dmn";
+ private static ResourceWithURI importingModel;
+ private static ResourceWithURI stdLibModel;
+ private static ResourceWithURI sampleModel;
+ private static ResourceWithURI multipleHitModel;
private static final String XAIURI1 = "invalid_models/DMNv1_x/test.dmn";
private static ResourceWithURI xaimodel1;
@@ -90,8 +105,10 @@ public class MultipleModelsTest {
@BeforeAll
public static void setup() throws IOException {
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
- model1 = new ResourceWithURI(URI1, getModelFromIoUtils(URI1));
- model2 = new ResourceWithURI(URI2, getModelFromIoUtils(URI2));
+ importingModel = new ResourceWithURI(IMPORTING_MODEL_URI, getModelFromIoUtils(IMPORTING_MODEL_URI));
+ stdLibModel = new ResourceWithURI(STDLIB_MODEL_URI, getModelFromIoUtils(STDLIB_MODEL_URI));
+ sampleModel = new ResourceWithURI(SAMPLE_MODEL_URI, getModelFromIoUtils(SAMPLE_MODEL_URI));
+ multipleHitModel = new ResourceWithURI(MULTIPLE_HIT_MODEL_URI, getModelFromIoUtils(MULTIPLE_HIT_MODEL_URI));
xaimodel1 = new ResourceWithURI(XAIURI1, getModelFromIoUtils(XAIURI1));
ch11model1 = new ResourceWithURI(CH11URI1, getModelFromIoUtils(CH11URI1));
ch11model2 = new ResourceWithURI(CH11URI2, getModelFromIoUtils(CH11URI2));
@@ -101,7 +118,7 @@ public class MultipleModelsTest {
void testForm() {
given()
.contentType(ContentType.JSON)
- .body(new MultipleResourcesPayload(URI1, List.of(model1, model2)))
+ .body(new MultipleResourcesPayload(IMPORTING_MODEL_URI, List.of(importingModel, stdLibModel)))
.when().post("/jitdmn/schema/form")
.then()
.statusCode(200)
@@ -112,7 +129,7 @@ public class MultipleModelsTest {
void testSchema() {
given()
.contentType(ContentType.JSON)
- .body(new MultipleResourcesPayload(URI1, List.of(model1, model2)))
+ .body(new MultipleResourcesPayload(IMPORTING_MODEL_URI, List.of(importingModel, stdLibModel)))
.when().post("/jitdmn/schema")
.then()
.statusCode(200)
@@ -121,7 +138,7 @@ public class MultipleModelsTest {
@Test
void testjitEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(URI1, List.of(model1, model2), buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(IMPORTING_MODEL_URI, List.of(importingModel, stdLibModel), buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -133,7 +150,7 @@ public class MultipleModelsTest {
@Test
void testjitdmnResultEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(URI1, List.of(model1, model2), buildContext());
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(IMPORTING_MODEL_URI, List.of(importingModel, stdLibModel), buildContext());
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
@@ -143,11 +160,90 @@ public class MultipleModelsTest {
.body("dmnContext.'my decision'", is("Ciao, John Doe (age:47)."));
}
+ @Test
+ void testEvaluationHitIds() throws IOException {
+ final String ruleId0 = "_1FA12B9F-288C-42E8-B77F-BE2D3702B7B6";
+ final String ruleId1 = "_C8FA33B1-AF6E-4A59-B7B9-6FDF1F495C44";
+ Map<String, Object> context = new HashMap<>();
+ context.put("Credit Score", Map.of("FICO", 700));
+ Map<String, Object> monthly = new HashMap<>();
+ monthly.put("Income", 121233);
+ monthly.put("Repayments", 33);
+ monthly.put("Expenses", 123);
+ monthly.put("Tax", 32);
+ monthly.put("Insurance", 55);
+ Map<String, Object> applicantData = new HashMap<>();
+ applicantData.put("Age", 32);
+ applicantData.put("Marital Status", "S");
+ applicantData.put("Employment Status", "Employed");
+ applicantData.put("Monthly", monthly);
+ context.put("Applicant Data", applicantData);
+ Map<String, Object> requestedProduct = new HashMap<>();
+ requestedProduct.put("Type", "Special Loan");
+ requestedProduct.put("Rate", 1);
+ requestedProduct.put("Term", 2);
+ requestedProduct.put("Amount", 333);
+ context.put("Requested Product", requestedProduct);
+ context.put("id", "_0A185BAC-7692-45FA-B722-7C86C626BD51");
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(SAMPLE_MODEL_URI, List.of(sampleModel), context);
+
+ Response response = given().contentType(ContentType.JSON)
+ .body(jitdmnpayload)
+ .when().post("/jitdmn/dmnresult");
+
+ ResponseBody body = response.getBody();
+ String responseString = body.asString();
+ JsonNode retrieved = MAPPER.readTree(responseString);
+ ArrayNode decisionResultsNode = (ArrayNode) retrieved.get("decisionResults");
+ Iterable<JsonNode> iterable = () -> decisionResultsNode.elements();
+ Stream<JsonNode> targetStream = StreamSupport.stream(iterable.spliterator(), false);
+ ObjectNode decisionNode = (ObjectNode) targetStream.filter(node -> node.get("decisionName").asText().equals("Credit Score Rating")).findFirst().get();
+ ObjectNode evaluationHitIdsNode = (ObjectNode) decisionNode.get(EVALUATION_HIT_IDS_FIELD_NAME);
+ Assertions.assertThat(evaluationHitIdsNode).hasSize(1);
+ Map<String, Integer> expectedEvaluationHitIds0 = Map.of(ruleId0, 1);
+ evaluationHitIdsNode.fields().forEachRemaining(entry -> Assertions.assertThat(expectedEvaluationHitIds0).containsEntry(entry.getKey(), entry.getValue().asInt()));
+
+ targetStream = StreamSupport.stream(iterable.spliterator(), false);
+ decisionNode = (ObjectNode) targetStream.filter(node -> node.get("decisionName").asText().equals("Loan Pre-Qualification")).findFirst().get();
+ evaluationHitIdsNode = (ObjectNode) decisionNode.get(EVALUATION_HIT_IDS_FIELD_NAME);
+ Assertions.assertThat(evaluationHitIdsNode).hasSize(1);
+ Map<String, Integer> expectedEvaluationHitIds1 = Map.of(ruleId1, 1);
+ evaluationHitIdsNode.fields().forEachRemaining(entry -> Assertions.assertThat(expectedEvaluationHitIds1).containsEntry(entry.getKey(), entry.getValue().asInt()));
+ }
+
+ @Test
+ void testjitdmnResultEndpointWithEvaluationHitIds() throws JsonProcessingException {
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(MULTIPLE_HIT_MODEL_URI, List.of(multipleHitModel), buildMultipleHitContext());
+ final String rule0 = "_E5C380DA-AF7B-4401-9804-C58296EC09DD";
+ final String rule1 = "_DFD65E8B-5648-4BFD-840F-8C76B8DDBD1A";
+ final String rule2 = "_E80EE7F7-1C0C-4050-B560-F33611F16B05";
+ String response = given().contentType(ContentType.JSON)
+ .body(jitdmnpayload)
+ .when().post("/jitdmn/dmnresult")
+ .then()
+ .statusCode(200)
+ .body(containsString("Statistics"),
+ containsString(EVALUATION_HIT_IDS_FIELD_NAME),
+ containsString(rule0),
+ containsString(rule1),
+ containsString(rule2))
+ .extract()
+ .asString();
+ JsonNode retrieved = MAPPER.readTree(response);
+ ArrayNode decisionResultsNode = (ArrayNode) retrieved.get("decisionResults");
+ ObjectNode decisionNode = (ObjectNode) decisionResultsNode.get(0);
+ ObjectNode evaluationHitIdsNode = (ObjectNode) decisionNode.get(EVALUATION_HIT_IDS_FIELD_NAME);
+ Assertions.assertThat(evaluationHitIdsNode).hasSize(3);
+
+ final Map<String, Integer> expectedEvaluationHitIds = Map.of(rule0, 3, rule1, 2, rule2, 1);
+ evaluationHitIdsNode.fields().forEachRemaining(entry -> Assertions.assertThat(expectedEvaluationHitIds).containsEntry(entry.getKey(), entry.getValue().asInt()));
+ }
+
@Test
void testValidation() throws IOException {
String response = given()
.contentType(ContentType.JSON)
- .body(new MultipleResourcesPayload(URI1, List.of(model1, model2)))
+ .body(new MultipleResourcesPayload(IMPORTING_MODEL_URI, List.of(importingModel, stdLibModel)))
.when()
.post("/jitdmn/validate")
.then()
@@ -158,12 +254,12 @@ public class MultipleModelsTest {
LOG.info("Validate response: {}", response);
List<JITDMNMessage> messages = MAPPER.readValue(response, LIST_OF_MSGS);
assertEquals(1, messages.size());
- assertThat(messages.get(0)).hasFieldOrPropertyWithValue("path", URI1);
+ assertThat(messages.get(0)).hasFieldOrPropertyWithValue("path", IMPORTING_MODEL_URI);
}
@Test
void testjitExplainabilityEndpoint() {
- JITDMNPayload jitdmnpayload = new JITDMNPayload(XAIURI1, List.of(xaimodel1, model1, model2), Map.of("FICO Score", 800, "DTI Ratio", .1, "PITI Ratio", .1));
+ JITDMNPayload jitdmnpayload = new JITDMNPayload(XAIURI1, List.of(xaimodel1, importingModel, stdLibModel), Map.of("FICO Score", 800, "DTI Ratio", .1, "PITI Ratio", .1));
given()
.contentType(ContentType.JSON)
.body(jitdmnpayload)
diff --git a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResultTest.java b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResultTest.java
index f14d8b3a1..aeb8d5365 100644
--- a/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResultTest.java
+++ b/jitexecutor/jitexecutor-dmn/src/test/java/org/kie/kogito/jitexecutor/dmn/responses/JITDMNResultTest.java
@@ -78,12 +78,12 @@ class JITDMNResultTest {
dmnResult.setContext(createContext());
dmnResult.addDecisionResult(decisionResult);
- JITDMNResult jitdmnResult = new JITDMNResult("http://www.trisotech.com/definitions/_9d01a0c4-f529-4ad8-ad8e-ec5fb5d96ad4", "Chapter 11 Example", dmnResult);
+ JITDMNResult jitdmnResult = JITDMNResult.of("http://www.trisotech.com/definitions/_9d01a0c4-f529-4ad8-ad8e-ec5fb5d96ad4", "Chapter 11 Example", dmnResult, Collections.emptyMap());
String retrieved = MAPPER.writeValueAsString(jitdmnResult);
assertThat(retrieved).isNotNull().isNotBlank();
- System.out.println(retrieved);
JITDMNResult result = MAPPER.readValue(retrieved, JITDMNResult.class);
- assertThat(result).isNotNull();
+ assertThat(result).isNotNull().isEqualTo(jitdmnResult);
+
}
@Test
@@ -459,7 +459,7 @@ class JITDMNResultTest {
" \"decisionName\": \"Required monthly installment\",\n" +
" \"result\": 333.3636546143084985132842970339110,\n" +
" \"messages\": [],\n" +
- " \"evaluationHitIds\": {},\n" +
+ " \"evaluationHitIds\": {\"_1FA12B9F-288C-42E8-B77F-BE2D3702B7B6\": 1},\n" +
" \"evaluationStatus\": \"SUCCEEDED\"\n" +
" },\n" +
" {\n" +
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org