This is an automated email from the ASF dual-hosted git repository.

yamer 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 6f9ca2645c [kie-issues#2210] Fix DMN TCK unary test 005 returning null 
instead of expected success (#6556)
6f9ca2645c is described below

commit 6f9ca2645ca7506f2b61e1828ee9c03f471a2c78
Author: ChinchuAjith <[email protected]>
AuthorDate: Tue Jan 27 20:44:30 2026 +0530

    [kie-issues#2210] Fix DMN TCK unary test 005 returning null instead of 
expected success (#6556)
    
    * Code changes based on lenient/strict mode
    
    * passing default as lenient
    
    * Lenient/strict code changes
    
    * Lenient/strict code changes
    
    * Lenient/strict code changes
    
    * Lenient/strict default implementation
    
    * Fix for downstream breaks
    
    * Fixing test cases for Lenient/Strict implementation
    
    * Test fixes Lenient/Strict implementation
    
    * Lenient/Strict implementation changes
    
    * Review comments and test fixes
    
    * Correcting Strict mode test
    
    * fixing test case
    
    * Review comments fix
    
    * Refactoring EvaluationContextImpl class
---
 .../core/jsr223/JSR223DTExpressionEvaluator.java   |  5 +--
 .../kie/dmn/core/ast/DMNDTExpressionEvaluator.java | 10 ++---
 .../kie/dmn/core/ast/DMNInvocationEvaluator.java   |  6 +--
 .../core/ast/DMNLiteralExpressionEvaluator.java    |  4 +-
 .../org/kie/dmn/core/compiler/DMNFEELHelper.java   |  5 ++-
 .../java/org/kie/dmn/core/impl/DMNRuntimeImpl.java | 13 +++---
 .../dmn/core/DMNDecisionTableHitPolicyTest.java    |  9 ++--
 .../kie/dmn/core/DMNDecisionTableRuntimeTest.java  | 41 ++++++++++++++++--
 .../core/impl/DMNContextFEELCtxWrapperTest.java    |  1 +
 .../org/kie/dmn/feel/lang/EvaluationContext.java   | 13 +++++-
 .../dmn/feel/lang/impl/EvaluationContextImpl.java  | 50 +++++++++++++---------
 .../java/org/kie/dmn/feel/lang/impl/FEELImpl.java  | 23 ++++++++--
 .../impl/SilentWrappingEvaluationContextImpl.java  | 15 +++++++
 .../runtime/decisiontables/DecisionTableImpl.java  | 19 +++++---
 .../core/v1_1/DMNDecisionTableHitPolicyTest.java   | 32 +++++++++++++-
 .../core/v1_1/DMNDecisionTableRuntimeTest.java     | 14 +++++-
 16 files changed, 196 insertions(+), 64 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-core-jsr223/src/main/java/org/kie/dmn/core/jsr223/JSR223DTExpressionEvaluator.java
 
b/kie-dmn/kie-dmn-core-jsr223/src/main/java/org/kie/dmn/core/jsr223/JSR223DTExpressionEvaluator.java
index 94f39b0368..d22c9c08b1 100644
--- 
a/kie-dmn/kie-dmn-core-jsr223/src/main/java/org/kie/dmn/core/jsr223/JSR223DTExpressionEvaluator.java
+++ 
b/kie-dmn/kie-dmn-core-jsr223/src/main/java/org/kie/dmn/core/jsr223/JSR223DTExpressionEvaluator.java
@@ -31,14 +31,13 @@ import org.drools.model.functions.Function1;
 import org.kie.dmn.api.core.DMNResult;
 import org.kie.dmn.api.core.DMNRuntime;
 import org.kie.dmn.api.core.DMNVersion;
+import org.kie.dmn.api.core.EvaluatorResult;
+import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.api.core.ast.DMNNode;
-import org.kie.dmn.api.core.ast.DecisionNode;
 import org.kie.dmn.api.core.event.DMNRuntimeEventManager;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.api.feel.runtime.events.FEELEventListener;
 import org.kie.dmn.core.api.DMNExpressionEvaluator;
-import org.kie.dmn.api.core.EvaluatorResult;
-import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.core.ast.DMNDTExpressionEvaluator;
 import org.kie.dmn.core.ast.DMNDTExpressionEvaluator.EventResults;
 import org.kie.dmn.core.ast.EvaluatorResultImpl;
diff --git 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNDTExpressionEvaluator.java
 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNDTExpressionEvaluator.java
index de2993bbb9..835f3db660 100644
--- 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNDTExpressionEvaluator.java
+++ 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNDTExpressionEvaluator.java
@@ -26,13 +26,13 @@ import java.util.function.Function;
 
 import org.kie.dmn.api.core.DMNMessage;
 import org.kie.dmn.api.core.DMNResult;
+import org.kie.dmn.api.core.EvaluatorResult;
+import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.api.core.ast.DMNNode;
-import org.kie.dmn.api.core.ast.DecisionNode;
 import org.kie.dmn.api.core.event.DMNRuntimeEventManager;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.core.api.DMNExpressionEvaluator;
-import org.kie.dmn.api.core.EvaluatorResult;
-import org.kie.dmn.api.core.EvaluatorResult.ResultType;
+import org.kie.dmn.core.compiler.RuntimeModeOption;
 import org.kie.dmn.core.impl.DMNResultImpl;
 import org.kie.dmn.core.impl.DMNRuntimeEventManagerUtils;
 import org.kie.dmn.core.impl.DMNRuntimeImpl;
@@ -40,7 +40,6 @@ import org.kie.dmn.core.util.Msg;
 import org.kie.dmn.core.util.MsgUtil;
 import org.kie.dmn.feel.FEEL;
 import org.kie.dmn.feel.lang.EvaluationContext;
-import org.kie.dmn.feel.lang.impl.EvaluationContextImpl;
 import org.kie.dmn.feel.lang.impl.FEELImpl;
 import org.kie.dmn.feel.runtime.FEELFunction.Param;
 import org.kie.dmn.feel.runtime.events.DecisionTableRulesMatchedEvent;
@@ -78,7 +77,8 @@ public class DMNDTExpressionEvaluator
             DMNRuntimeEventManagerUtils.fireBeforeEvaluateDecisionTable( 
dmrem, node.getName(), dt.getName(), dtNodeId, result );
             List<String> paramNames = 
dt.getParameters().get(0).stream().map(Param::getName).toList();
             Object[] params = new Object[paramNames.size()];
-            EvaluationContextImpl ctx = 
feel.newEvaluationContext(List.of(events::add), Collections.emptyMap());
+            boolean isLenient = RuntimeModeOption.MODE.LENIENT == 
((DMNRuntimeImpl) dmrem.getRuntime()).getRuntimeModeOption();
+            EvaluationContext ctx = 
feel.newEvaluationContext(List.of(events::add), Collections.emptyMap(), 
isLenient);
             ctx.setPerformRuntimeTypeCheck(((DMNRuntimeImpl) 
dmrem.getRuntime()).performRuntimeTypeCheck(result.getModel()));
 
             Map<String, Object> contextValues = result.getContext().getAll();
diff --git 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNInvocationEvaluator.java
 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNInvocationEvaluator.java
index 5370103ee2..7eb122543b 100644
--- 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNInvocationEvaluator.java
+++ 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNInvocationEvaluator.java
@@ -26,15 +26,15 @@ import java.util.function.BiFunction;
 import javax.xml.namespace.QName;
 
 import org.kie.dmn.api.core.DMNContext;
+import org.kie.dmn.api.core.DMNMessage;
 import org.kie.dmn.api.core.DMNResult;
 import org.kie.dmn.api.core.DMNType;
-import org.kie.dmn.api.core.EvaluatorResult;
-import org.kie.dmn.api.core.DMNMessage;
 import org.kie.dmn.api.core.DMNVersion;
+import org.kie.dmn.api.core.EvaluatorResult;
+import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.api.core.event.DMNRuntimeEventManager;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.core.api.DMNExpressionEvaluator;
-import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.core.impl.DMNModelImpl;
 import org.kie.dmn.core.impl.DMNResultImpl;
 import org.kie.dmn.core.util.Msg;
diff --git 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNLiteralExpressionEvaluator.java
 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNLiteralExpressionEvaluator.java
index 33c80b4c15..012fe2e9a7 100644
--- 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNLiteralExpressionEvaluator.java
+++ 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/ast/DMNLiteralExpressionEvaluator.java
@@ -26,13 +26,13 @@ import java.util.stream.Collectors;
 
 import org.kie.dmn.api.core.DMNMessage;
 import org.kie.dmn.api.core.DMNResult;
+import org.kie.dmn.api.core.EvaluatorResult;
+import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.api.core.event.DMNRuntimeEventManager;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
 import org.kie.dmn.api.feel.runtime.events.FEELEventListener;
 import org.kie.dmn.core.api.DMNExpressionEvaluator;
-import org.kie.dmn.api.core.EvaluatorResult;
-import org.kie.dmn.api.core.EvaluatorResult.ResultType;
 import org.kie.dmn.core.impl.DMNResultImpl;
 import org.kie.dmn.core.util.Msg;
 import org.kie.dmn.core.util.MsgUtil;
diff --git 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/DMNFEELHelper.java
 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/DMNFEELHelper.java
index 33187ab0a9..001204cdcf 100644
--- 
a/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/DMNFEELHelper.java
+++ 
b/kie-dmn/kie-dmn-core/src/main/java/org/kie/dmn/core/compiler/DMNFEELHelper.java
@@ -29,8 +29,6 @@ import java.util.Queue;
 
 import javax.xml.namespace.QName;
 
-import com.github.javaparser.ast.CompilationUnit;
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import org.antlr.v4.runtime.CommonToken;
 import org.kie.dmn.api.core.DMNContext;
 import org.kie.dmn.api.core.DMNMessage;
@@ -65,6 +63,9 @@ import org.kie.dmn.model.api.ItemDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+
 
 public class DMNFEELHelper {
 
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 5930f08f10..3789c799be 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
@@ -18,17 +18,15 @@
  */
 package org.kie.dmn.core.impl;
 
-import javax.xml.namespace.QName;
-
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
+
+import javax.xml.namespace.QName;
+
 import org.drools.kiesession.rulebase.InternalKnowledgeBase;
 import org.kie.dmn.api.core.DMNContext;
 import org.kie.dmn.api.core.DMNDecisionResult;
@@ -84,6 +82,7 @@ public class DMNRuntimeImpl
     private final DMNRuntimeKB runtimeKB;
 
     private boolean overrideRuntimeTypeCheck = false;
+
     private RuntimeModeOption.MODE runtimeModeOption = 
RuntimeModeOption.MODE.LENIENT;
 
     private DMNResultImplFactory dmnResultFactory = new DMNResultImplFactory();
@@ -854,4 +853,8 @@ public class DMNRuntimeImpl
     public DMNRuntimeKB getRuntimeKB() {
         return runtimeKB;
     }
+
+    public RuntimeModeOption.MODE getRuntimeModeOption() {
+        return runtimeModeOption;
+    }
 }
diff --git 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableHitPolicyTest.java
 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableHitPolicyTest.java
index ee649b9e84..1e5e5b7cc2 100644
--- 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableHitPolicyTest.java
+++ 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableHitPolicyTest.java
@@ -66,14 +66,15 @@ public class DMNDecisionTableHitPolicyTest extends 
BaseInterpretedVsCompiledTest
         assertThat(dmnModel).isNotNull();
 
         // Risk Category is constrained to "High", "Low", "Medium" and "ASD" 
is not allowed
+        // In lenient mode (default), invalid input is set to null and 
evaluation continues
         final DMNContext context = 
getSimpleTableContext(BigDecimal.valueOf(18), "ASD", false);
         final DMNResult dmnResult = runtime.evaluateAll(dmnModel, context);
         final DMNContext result = dmnResult.getContext();
 
-        assertThat(result.get("Approval Status")).isNull();
-        assertThat(dmnResult.getMessages()).hasSizeGreaterThan(0);
-        DMNMessage message = dmnResult.getMessages().iterator().next();
-        assertThat(message.getText()).isEqualTo("DMN: RiskCategory='ASD' does 
not match any of the valid values \"High\", \"Low\", \"Medium\" for decision 
table '_0004-simpletable-U'. (DMN id: _0004-simpletable-U, FEEL expression 
evaluation error) ");
+        // In lenient mode, the decision table evaluates with null parameter 
and returns a result
+        assertThat(result.get("Approval Status")).isEqualTo("Declined");
+        // No error messages in lenient mode
+        assertThat(dmnResult.getMessages()).isEmpty();
     }
 
     @ParameterizedTest
diff --git 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableRuntimeTest.java
 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableRuntimeTest.java
index d53b372861..92a8d99c69 100644
--- 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableRuntimeTest.java
+++ 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/DMNDecisionTableRuntimeTest.java
@@ -186,7 +186,7 @@ public class DMNDecisionTableRuntimeTest extends 
BaseInterpretedVsCompiledTest {
         context.set( "Branches dispersion", "Province" );
         context.set( "Number of Branches", BigDecimal.valueOf( 10 ) );
 
-        testDecisionTableInvalidInput( context );
+        testDecisionTableInvalidInputLenient( context );
     }
 
     @ParameterizedTest
@@ -197,7 +197,7 @@ public class DMNDecisionTableRuntimeTest extends 
BaseInterpretedVsCompiledTest {
         context.set( "Branches dispersion", 1 );
         context.set( "Number of Branches", BigDecimal.valueOf( 10 ) );
 
-        testDecisionTableInvalidInput( context );
+        testDecisionTableInvalidInputType( context );
     }
 
     @ParameterizedTest
@@ -208,18 +208,51 @@ public class DMNDecisionTableRuntimeTest extends 
BaseInterpretedVsCompiledTest {
         context.set( "Not exists", "Province" );
         context.set( "Number of Branches", BigDecimal.valueOf( 10 ) );
 
-        testDecisionTableInvalidInput( context );
+        testDecisionTableMissingDependency( context );
     }
 
-    private void testDecisionTableInvalidInput(final DMNContext inputContext) {
+    private void testDecisionTableInvalidInputLenient(final DMNContext 
inputContext) {
         final DMNRuntime runtime = DMNRuntimeUtil.createRuntime( 
"InvalidInput.dmn", this.getClass() );
         final DMNModel dmnModel = runtime.getModel( 
"http://www.trisotech.com/dmn/definitions/_cdf29af2-959b-4004-8271-82a9f5a62147";,
 "Dessin 1" );
         assertThat(dmnModel).isNotNull();
 
         final DMNResult dmnResult = runtime.evaluateAll( dmnModel, 
inputContext );
+        // In lenient mode (default), invalid input values don't generate 
errors
+        // The invalid value is set to null and evaluation continues
+        assertThat( dmnResult.hasErrors()).isFalse();
+
+        final DMNContext result = dmnResult.getContext();
+        // Result is defined - evaluation continues with null for invalid input
+        assertThat( result.isDefined( "Branches distribution" 
)).isEqualTo(Boolean.TRUE);
+    }
+
+    private void testDecisionTableInvalidInputType(final DMNContext 
inputContext) {
+        final DMNRuntime runtime = DMNRuntimeUtil.createRuntime( 
"InvalidInput.dmn", this.getClass() );
+        final DMNModel dmnModel = runtime.getModel( 
"http://www.trisotech.com/dmn/definitions/_cdf29af2-959b-4004-8271-82a9f5a62147";,
 "Dessin 1" );
+        assertThat(dmnModel).isNotNull();
+
+        final DMNResult dmnResult = runtime.evaluateAll( dmnModel, 
inputContext );
+        // Type errors generate errors regardless of lenient/strict mode
+        // Wrong type (integer instead of string) is a type mismatch error
+        assertThat( dmnResult.hasErrors()).isTrue();
+
+        final DMNContext result = dmnResult.getContext();
+        // With type error, the result cannot be evaluated
+        assertThat( result.isDefined( "Branches distribution" 
)).isEqualTo(Boolean.FALSE);
+    }
+
+    private void testDecisionTableMissingDependency(final DMNContext 
inputContext) {
+        final DMNRuntime runtime = DMNRuntimeUtil.createRuntime( 
"InvalidInput.dmn", this.getClass() );
+        final DMNModel dmnModel = runtime.getModel( 
"http://www.trisotech.com/dmn/definitions/_cdf29af2-959b-4004-8271-82a9f5a62147";,
 "Dessin 1" );
+        assertThat(dmnModel).isNotNull();
+
+        final DMNResult dmnResult = runtime.evaluateAll( dmnModel, 
inputContext );
+        // Missing required dependency generates errors regardless of 
lenient/strict mode
+        // This is a structural error, not an input validation error
         assertThat( dmnResult.hasErrors()).isTrue();
 
         final DMNContext result = dmnResult.getContext();
+        // With missing required dependency, the result cannot be evaluated
         assertThat( result.isDefined( "Branches distribution" 
)).isEqualTo(Boolean.FALSE);
     }
 
diff --git 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/impl/DMNContextFEELCtxWrapperTest.java
 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/impl/DMNContextFEELCtxWrapperTest.java
index d5322832cf..319cf7f9ea 100644
--- 
a/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/impl/DMNContextFEELCtxWrapperTest.java
+++ 
b/kie-dmn/kie-dmn-core/src/test/java/org/kie/dmn/core/impl/DMNContextFEELCtxWrapperTest.java
@@ -173,6 +173,7 @@ class DMNContextFEELCtxWrapperTest extends 
BaseDMNContextTest {
         public DMNVersion getDMNVersion() {
             return DMNVersion.getLatest();
         }
+
     }
 
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/EvaluationContext.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/EvaluationContext.java
index b521f0dcf0..6ba949b8d0 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/EvaluationContext.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/EvaluationContext.java
@@ -53,7 +53,6 @@ public interface EvaluationContext {
 
     void notifyEvt(Supplier<FEELEvent> event);
 
-
     Collection<FEELEventListener> getListeners();
 
     void setRootObject(Object v);
@@ -63,4 +62,16 @@ public interface EvaluationContext {
     FEELDialect getFEELDialect();
 
     DMNVersion getDMNVersion();
+
+    default boolean isLenient() {
+        return true; // Default to lenient mode
+    }
+
+    default void setPerformRuntimeTypeCheck(boolean performRuntimeTypeCheck) {
+        // Default implementation does nothing
+    }
+
+    default void enterFrame(int size) {
+        // Default implementation does nothing
+    }
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
index 6e1d7c36fe..211597b541 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/EvaluationContextImpl.java
@@ -41,23 +41,27 @@ public class EvaluationContextImpl implements 
EvaluationContext {
     private static final Logger LOG = 
LoggerFactory.getLogger(EvaluationContextImpl.class);
 
     private final FEELEventListenersManager eventsManager;
-    private ArrayDeque<ExecutionFrame> stack;
-    private DMNRuntime dmnRuntime;
-    private boolean performRuntimeTypeCheck = false;
-    private ClassLoader rootClassLoader;
+    private final ArrayDeque<ExecutionFrame> stack;
+        private final ClassLoader rootClassLoader;
     private final FEELDialect feelDialect;
     private final DMNVersion dmnVersion;
+    private final boolean isLenient;
 
-    private EvaluationContextImpl(ClassLoader cl, FEELEventListenersManager 
eventsManager, Deque<ExecutionFrame> stack, FEELDialect feelDialect, DMNVersion 
dmnVersion) {
+    private DMNRuntime dmnRuntime;
+    private boolean performRuntimeTypeCheck = false;
+
+    private EvaluationContextImpl(ClassLoader cl, FEELEventListenersManager 
eventsManager, Deque<ExecutionFrame> stack, FEELDialect feelDialect, DMNVersion 
dmnVersion, boolean isLenient) {
         this.eventsManager = eventsManager;
         this.rootClassLoader = cl;
         this.stack = new ArrayDeque<>(stack);
         this.feelDialect = feelDialect;
         this.dmnVersion = dmnVersion;
+        this.isLenient = isLenient;
     }
 
     public EvaluationContextImpl(ClassLoader cl, FEELEventListenersManager 
eventsManager, FEELDialect feelDialect, DMNVersion dmnVersion) {
-        this(cl, eventsManager, 32, feelDialect, dmnVersion);
+        this(cl, eventsManager, new ArrayDeque<>(), feelDialect, dmnVersion, 
true);
+        initializeFrames(32);
     }
 
     /**
@@ -68,32 +72,31 @@ public class EvaluationContextImpl implements 
EvaluationContext {
     }
 
     public EvaluationContextImpl(ClassLoader cl, FEELEventListenersManager 
eventsManager, int size, FEELDialect feelDialect, DMNVersion dmnVersion) {
-        this(cl, eventsManager, new ArrayDeque<>(), feelDialect, dmnVersion);
-        // we create a rootFrame to hold all the built in functions
-        push( RootExecutionFrame.INSTANCE );
-        // and then create a global frame to be the starting frame
-        // for function evaluation
-        ExecutionFrameImpl global = new 
ExecutionFrameImpl(RootExecutionFrame.INSTANCE, size);
-        push( global );
+        this(cl, eventsManager, new ArrayDeque<>(), feelDialect, dmnVersion, 
true);
+        initializeFrames(size);
+    }
+
+    public EvaluationContextImpl(ClassLoader cl, FEELEventListenersManager 
eventsManager, int size, FEELDialect feelDialect, DMNVersion dmnVersion, 
boolean isLenient) {
+        this(cl, eventsManager, new ArrayDeque<>(), feelDialect, dmnVersion, 
isLenient);
+        initializeFrames(size);
     }
 
     @Deprecated
     public EvaluationContextImpl(FEELEventListenersManager eventsManager, 
DMNRuntime dmnRuntime, FEELDialect feelDialect, DMNVersion dmnVersion) {
-        this(dmnRuntime.getRootClassLoader(), eventsManager, feelDialect, 
dmnVersion);
+        this(dmnRuntime.getRootClassLoader(), eventsManager, new 
ArrayDeque<>(), feelDialect, dmnVersion, true);
         this.dmnRuntime = dmnRuntime;
+        initializeFrames(32);
     }
 
-    private EvaluationContextImpl(FEELEventListenersManager eventsManager, 
FEELDialect feelDialect, DMNVersion dmnVersion) {
-        this.eventsManager = eventsManager;
-        this.feelDialect = feelDialect;
-        this.dmnVersion = dmnVersion;
+    private void initializeFrames(int size) {
+        push(RootExecutionFrame.INSTANCE);
+        push(new ExecutionFrameImpl(RootExecutionFrame.INSTANCE, size));
     }
 
+
     @Override
     public EvaluationContext current() {
-        EvaluationContextImpl ec = new EvaluationContextImpl(eventsManager, 
feelDialect, dmnVersion);
-        ec.stack = stack.clone();
-        ec.rootClassLoader = this.rootClassLoader;
+        EvaluationContextImpl ec = new EvaluationContextImpl( 
this.rootClassLoader, this.eventsManager, this.stack.clone(), this.feelDialect, 
this.dmnVersion, this.isLenient);
         ec.dmnRuntime = this.dmnRuntime;
         ec.performRuntimeTypeCheck = this.performRuntimeTypeCheck;
         return ec;
@@ -254,4 +257,9 @@ public class EvaluationContextImpl implements 
EvaluationContext {
     public DMNVersion getDMNVersion() {
         return dmnVersion;
     }
+
+    @Override
+    public boolean isLenient() {
+        return isLenient;
+    }
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/FEELImpl.java 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/FEELImpl.java
index aadea6e4c4..d8bf1fc5a7 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/FEELImpl.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/FEELImpl.java
@@ -168,16 +168,33 @@ public class FEELImpl
     /**
      * Creates a new EvaluationContext using this FEEL instance classloader, 
and the supplied parameters listeners and inputVariables
      */
-    public EvaluationContextImpl 
newEvaluationContext(Collection<FEELEventListener> listeners, Map<String, 
Object> inputVariables) {
+    public EvaluationContextImpl 
newEvaluationContext(Collection<FEELEventListener> listeners, Map<String, 
Object> inputVariables ) {
         return newEvaluationContext(this.classLoader, listeners, 
inputVariables);
     }
 
     /**
      * Creates a new EvaluationContext with the supplied classloader, and the 
supplied parameters listeners and inputVariables
      */
-    public EvaluationContextImpl newEvaluationContext(ClassLoader cl, 
Collection<FEELEventListener> listeners, Map<String, Object> inputVariables) {
+    public EvaluationContextImpl newEvaluationContext(ClassLoader cl, 
Collection<FEELEventListener> listeners, Map<String, Object> inputVariables ) {
         FEELEventListenersManager eventsManager = getEventsManager(listeners);
         EvaluationContextImpl ctx = new EvaluationContextImpl(cl, 
eventsManager, inputVariables.size(), feelDialect, dmnVersion);
+        setupCustomFrame(ctx);
+        ctx.setValues(inputVariables);
+        return ctx;
+    }
+
+    /**
+     * Creates a new EvaluationContext with the supplied classloader, and the 
supplied parameters listeners and inputVariables and isLenient
+     */
+    public EvaluationContextImpl 
newEvaluationContext(Collection<FEELEventListener> listeners, Map<String, 
Object> inputVariables, boolean isLenient ) {
+        FEELEventListenersManager eventsManager = getEventsManager(listeners);
+        EvaluationContextImpl ctx = new 
EvaluationContextImpl(this.classLoader, eventsManager, inputVariables.size(), 
feelDialect, dmnVersion, isLenient);
+        setupCustomFrame(ctx);
+        ctx.setValues(inputVariables);
+        return ctx;
+    }
+
+    private void setupCustomFrame(EvaluationContextImpl ctx) {
         if (customFrame.isPresent()) {
             ExecutionFrameImpl globalFrame = (ExecutionFrameImpl) ctx.pop();
             ExecutionFrameImpl interveawedFrame = customFrame.get();
@@ -186,8 +203,6 @@ public class FEELImpl
             ctx.push(interveawedFrame);
             ctx.push(globalFrame);
         }
-        ctx.setValues(inputVariables);
-        return ctx;
     }
 
     @Override
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/SilentWrappingEvaluationContextImpl.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/SilentWrappingEvaluationContextImpl.java
index 621b45948f..edb5a77c57 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/SilentWrappingEvaluationContextImpl.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/impl/SilentWrappingEvaluationContextImpl.java
@@ -128,4 +128,19 @@ public class SilentWrappingEvaluationContextImpl 
implements EvaluationContext {
     public DMNVersion getDMNVersion() {
         return wrapped.getDMNVersion();
     }
+
+    @Override
+    public void enterFrame(int size) {
+        wrapped.enterFrame(size);
+    }
+
+    @Override
+    public boolean isLenient() {
+        return wrapped.isLenient();
+    }
+
+    @Override
+    public void setPerformRuntimeTypeCheck(boolean performRuntimeTypeCheck) {
+        wrapped.setPerformRuntimeTypeCheck(performRuntimeTypeCheck);
+    }
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/decisiontables/DecisionTableImpl.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/decisiontables/DecisionTableImpl.java
index c75f1b2a06..b6131f2469 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/decisiontables/DecisionTableImpl.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/decisiontables/DecisionTableImpl.java
@@ -229,13 +229,18 @@ public class DecisionTableImpl implements DecisionTable {
                 }
 
                 if ( !satisfies ) {
-                    String values = input.getInputValuesText();
-                    return Either.ofLeft(new InvalidInputEvent( 
FEELEvent.Severity.ERROR,
-                                                  
input.getInputExpression()+"='" + parameter + "' does not match any of the 
valid values " + values + " for decision table '" + getName() + "'.",
-                                                  getName(),
-                                                  null,
-                                                  values )
-                            );
+                    // Return error if context is not Lenient
+                    if (!ctx.isLenient()) {
+                        String values = input.getInputValuesText();
+                        return Either.ofLeft(new InvalidInputEvent( 
FEELEvent.Severity.ERROR,
+                                                      
input.getInputExpression()+"='" + parameter + "' does not match any of the 
valid values " + values + " for decision table '" + getName() + "'.",
+                                                      getName(),
+                                                      null,
+                                                      values )
+                                );
+                    } else {
+                        params[i] = null;
+                    }
                 }
             }
         }
diff --git 
a/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableHitPolicyTest.java
 
b/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableHitPolicyTest.java
index f40d445c42..db8d8f7e57 100644
--- 
a/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableHitPolicyTest.java
+++ 
b/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableHitPolicyTest.java
@@ -31,6 +31,7 @@ import org.kie.dmn.api.core.DMNResult;
 import org.kie.dmn.api.core.DMNRuntime;
 import org.kie.dmn.api.feel.runtime.events.FEELEvent;
 import org.kie.dmn.core.api.DMNFactory;
+import org.kie.dmn.core.compiler.RuntimeModeOption;
 import org.kie.dmn.core.util.DMNRuntimeUtil;
 import org.kie.dmn.feel.runtime.events.HitPolicyViolationEvent;
 import org.slf4j.Logger;
@@ -66,9 +67,36 @@ public class DMNDecisionTableHitPolicyTest extends 
BaseDMN1_1VariantTest {
         final DMNContext context = 
getSimpleTableContext(BigDecimal.valueOf(18), "ASD", false);
         final DMNResult dmnResult = runtime.evaluateAll(dmnModel, context);
         final DMNContext result = dmnResult.getContext();
+        
+        // In lenient mode, invalid input value "ASD" is set to null and 
evaluation continues
+        // Rule 4 matches: Age=any(-), RiskCategory=any(-), isAffordable=false 
-> "Declined"
+        assertThat(result.get("Approval Status")).isEqualTo("Declined");
 
-        assertThat(result.get("Approval Status")).isNull();
-        assertThat(dmnResult.getMessages()).hasSizeGreaterThan(0);
+        assertThat(dmnResult.getDecisionResults()).hasSize(1);
+        
assertThat(dmnResult.getDecisionResultByName("_0004-simpletable-U")).isNotNull();
+        
assertThat(dmnResult.getDecisionResultByName("_0004-simpletable-U").getResult()).isEqualTo("Declined");
+        
assertThat(dmnResult.getDecisionResultByName("_0004-simpletable-U").getEvaluationStatus())
+                
.isEqualTo(org.kie.dmn.api.core.DMNDecisionResult.DecisionEvaluationStatus.SUCCEEDED);
+    }
+
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("params")
+    void simpleDecisionTableHitPolicyUniqueSatisfiesStrictMode(VariantTestConf 
conf) {
+        testConfig = conf;
+        System.setProperty(RuntimeModeOption.PROPERTY_NAME, 
RuntimeModeOption.MODE.STRICT.getMode());
+        try {
+            final DMNRuntime runtime = 
DMNRuntimeUtil.createRuntime("0004-simpletable-U.dmn", this.getClass());
+            final DMNModel dmnModel = 
runtime.getModel("https://github.com/kiegroup/kie-dmn";, "0004-simpletable-U");
+            assertThat(dmnModel).isNotNull();
+
+            final DMNContext context = 
getSimpleTableContext(BigDecimal.valueOf(18), "Medium", true);
+            final DMNResult dmnResult = runtime.evaluateAll(dmnModel, context);
+
+            assertThat(dmnResult.hasErrors()).isFalse();
+            assertThat(dmnResult.getContext().get("Approval 
Status")).isEqualTo("Approved");
+        } finally {
+            System.clearProperty(RuntimeModeOption.PROPERTY_NAME);
+        }
     }
 
     @ParameterizedTest(name = "{0}")
diff --git 
a/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableRuntimeTest.java
 
b/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableRuntimeTest.java
index a160371d0e..dbf06a82ab 100644
--- 
a/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableRuntimeTest.java
+++ 
b/kie-dmn/kie-dmn-legacy-tests/src/test/java/org/kie/dmn/legacy/tests/core/v1_1/DMNDecisionTableRuntimeTest.java
@@ -163,7 +163,17 @@ public class DMNDecisionTableRuntimeTest extends 
BaseDMN1_1VariantTest {
         context.set( "Branches dispersion", "Province" );
         context.set( "Number of Branches", BigDecimal.valueOf( 10 ) );
 
-        testDecisionTableInvalidInput( context );
+        final DMNRuntime runtime = DMNRuntimeUtil.createRuntime( 
"InvalidInput.dmn", this.getClass() );
+        final DMNModel dmnModel = runtime.getModel( 
"http://www.trisotech.com/dmn/definitions/_cdf29af2-959b-4004-8271-82a9f5a62147";,
 "Dessin 1" );
+        assertThat(dmnModel).isNotNull();
+
+        final DMNResult dmnResult = runtime.evaluateAll( dmnModel, context );
+        // In lenient mode, invalid input value is set to null and evaluation 
continues
+        assertThat( dmnResult.hasErrors()).isFalse();
+
+        final DMNContext result = dmnResult.getContext();
+        assertThat(result.get("Branches distribution")).isNull();
+        assertThat(result.isDefined( "Branches 
distribution")).isEqualTo(Boolean.TRUE);
     }
 
     @ParameterizedTest(name = "{0}")
@@ -194,9 +204,11 @@ public class DMNDecisionTableRuntimeTest extends 
BaseDMN1_1VariantTest {
         assertThat(dmnModel).isNotNull();
 
         final DMNResult dmnResult = runtime.evaluateAll( dmnModel, 
inputContext );
+        // Type mismatch or missing required input causes errors
         assertThat( dmnResult.hasErrors()).isTrue();
 
         final DMNContext result = dmnResult.getContext();
+        // Result is not defined due to errors
         assertThat(result.isDefined( "Branches 
distribution")).isEqualTo(Boolean.FALSE);
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to