Copilot commented on code in PR #6519:
URL: 
https://github.com/apache/incubator-kie-drools/pull/6519#discussion_r2540888936


##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        map.putAll(getCommonAddOperations(ctx));

Review Comment:
   The `getAndOperations` method calls `getCommonAddOperations(ctx)` instead of 
`getCommonAndOperations(ctx)`. This is a copy-paste error that will cause the 
AND operations to incorrectly include addition operation logic.
   
   Should be:
   ```java
   map.putAll(getCommonAndOperations(ctx));
   ```
   ```suggestion
           map.putAll(getCommonAndOperations(ctx));
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE

Review Comment:
   The predicate for "Special case: otherwise AND true → false" is checking if 
`leftBool == null && Boolean.TRUE.equals(rightBool)` and returning 
`Boolean.FALSE`. However, according to standard FEEL semantics, `null AND true` 
should return `null`, not `false`. This override for BFEEL needs verification 
against the BFEEL specification.
   ```suggestion
                   (left, right) -> null
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java:
##########
@@ -0,0 +1,716 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import ch.obermuhlner.math.big.BigDecimalMath;
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+import org.kie.dmn.feel.util.Msg;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAmount;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+import static org.kie.dmn.feel.util.NumberEvalHelper.getBigDecimalOrNull;
+
+/**
+ *  Base implementation of the DialectHandler interface providing common
+ *  functionality for all dialects.
+ */
+public abstract class DefaultDialectHandler implements DialectHandler {
+
+    /**
+     * Builds the common 'Addition' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Addition' operations
+     */
+    protected Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getCommonAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // Number + Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimalOrNull(left);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.add(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Duration + LocalDate
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof LocalDate, false),
+                (left, right) -> addLocalDateAndDuration((LocalDate) right, 
(Duration) left)
+        );
+
+        // LocalDate + Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Duration, false),
+                (left, right) -> addLocalDateAndDuration((LocalDate) left, 
(Duration) right)
+        );
+
+        // Duration + Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left, right) -> ((Duration) left).plus((Duration) right)
+        );
+
+        // Temporal + TemporalAmount
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof TemporalAmount, false),
+                (left, right) -> ((Temporal) left).plus((TemporalAmount) right)
+        );
+
+        // TemporalAmount + Temporal
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
TemporalAmount && right instanceof Temporal, false),
+                (left, right) -> ((Temporal) right).plus((TemporalAmount) left)
+        );
+
+        // TemporalAmount + ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
TemporalAmount && right instanceof ChronoPeriod, false),
+                (left, right) -> ((ChronoPeriod) right).plus((TemporalAmount) 
left)
+        );
+
+        // left or right -> null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+        return map;
+    }
+
+
+    /**
+     * Builds the common 'And' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'And' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // false AND anything → false (short‑circuit)
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // true AND true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // true AND false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // true AND otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        // otherwise AND true → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> null
+        );
+
+        // otherwise AND false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // otherwise AND otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Equal' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Equal' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonEqualOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.isEqual(left, right, 
dialect)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Greater than Or EqualTo' operation map used by the 
dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Greater than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonGteOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left > right OR left == right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> InfixExecutorUtils.or(
+                        BooleanEvalHelper.compare(left, right, dialect, 
(leftNum, rightNum) -> leftNum.compareTo(rightNum) > 0),
+                        BooleanEvalHelper.isEqual(left, right, dialect),
+                        ctx
+                )
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Greater than' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Greater than' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonGtOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left > right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.compare(left, right, 
dialect, (leftNum, rightNum) -> leftNum.compareTo(rightNum) > 0)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Less than Or EqualTo' operation map used by the 
dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Less than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonLteOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left < right OR left == right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> InfixExecutorUtils.or(
+                        BooleanEvalHelper.compare(left, right, dialect, 
(leftNum, rightNum) -> leftNum.compareTo(rightNum) < 0),
+                        BooleanEvalHelper.isEqual(left, right, dialect),
+                        ctx
+                )
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Less than' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Less than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonLtOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left < right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.compare(left, right, 
dialect, (leftNum, rightNum) -> leftNum.compareTo(rightNum) < 0)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Not EqualTo' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Not EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonNotEqualOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> {
+                    Boolean result = BooleanEvalHelper.isEqual(left, right, 
dialect);
+                    return result != null ? !result : null;
+                }
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Or' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Or operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonOrOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // true OR anything → true (short‑circuit)
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // false OR true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // false OR false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // false OR otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        // otherwise OR true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // otherwise OR false → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> null
+        );
+
+        // otherwise OR otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Power of' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Power of' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonPowOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> math(left, right, ctx,
+                        (l, r) -> BigDecimalMath.pow(l, r, 
MathContext.DECIMAL128))
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Substraction' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Substraction' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonSubOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        // null - Number
+        map.put(
+                new CheckedPredicate((left, right) ->
+                        (left == null && right instanceof Number) || (right == 
null && left instanceof Number), false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimal(left, ctx);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.subtract(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Number - Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimal(left, ctx);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.subtract(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // LocalDate - Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Duration, false),
+                (left, right) -> {
+                    LocalDateTime leftLDT = LocalDateTime.of((LocalDate) left, 
LocalTime.MIDNIGHT);
+                    LocalDateTime evaluated = leftLDT.minus((Duration) right);
+                    return LocalDate.of(evaluated.getYear(), 
evaluated.getMonth(), evaluated.getDayOfMonth());
+                }
+        );
+
+        // Duration - Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left, right) -> ((Duration) left).minus((Duration) right)
+        );
+
+        // Temporal - Temporal
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof Temporal, false),
+                (left, right) -> subtractTemporals((Temporal) left, (Temporal) 
right, ctx)
+        );
+
+        // Temporal - TemporalAmount
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof TemporalAmount, false),
+                (left, right) -> ((Temporal) left).minus((TemporalAmount) 
right)
+        );
+
+        // ChronoPeriod - ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
ChronoPeriod && right instanceof ChronoPeriod, false),
+                (left, right) -> new ComparablePeriod(((ChronoPeriod) 
left).minus((ChronoPeriod) right))
+        );
+
+
+        // left == null || right == null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Multiplication' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Multiplication operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonMultOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Number * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimalOrNull(left);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.multiply(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Number * Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Duration, false),
+                (left, right) -> Duration.ofSeconds(
+                        getBigDecimalOrNull(left)
+                                .multiply(BigDecimal.valueOf(((Duration) 
right).getSeconds()), MathContext.DECIMAL128)
+                                .longValue()
+                )
+        );
+
+        // Number * ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof ChronoPeriod, false),
+                (left, right) -> ComparablePeriod.ofMonths(
+                        getBigDecimalOrNull(left)
+                                
.multiply(getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
right)), MathContext.DECIMAL128)
+                                .intValue()
+                )
+        );
+
+        // Duration * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) left).toNanos());
+                    BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
right).doubleValue());
+                    return 
Duration.ofNanos(durationNumericValue.multiply(rightDecimal).longValue());
+                }
+        );
+        // ChronoPeriod * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
ChronoPeriod && right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal rightNumber = getBigDecimal(right, ctx);
+                    return ComparablePeriod.ofMonths(
+                            
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left))
+                                    .multiply(rightNumber, 
MathContext.DECIMAL128)
+                                    .intValue()
+                    );
+                }
+        );
+
+
+        // left or right == null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+
+       return map;
+    }
+
+    /**
+     * Builds the common 'Division' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Division' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonDivisionOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // Number ÷ Number
+        map.put(
+                new CheckedPredicate((left,right) -> left instanceof Number && 
right instanceof Number
+                        && getBigDecimalOrNull(right) != null
+                        && 
getBigDecimalOrNull(right).compareTo(BigDecimal.ZERO) != 0,
+                        false),
+                (left,right) -> {
+                    BigDecimal leftBD = getBigDecimalOrNull(left);
+                    BigDecimal rightBD = getBigDecimalOrNull(right);
+                    return leftBD.divide(rightBD, MathContext.DECIMAL128);
+                }
+        );
+
+        // Number ÷ Number , Division by zero case → notify
+        map.put(
+                new CheckedPredicate((left,right) -> left instanceof Number && 
right instanceof Number
+                        && getBigDecimalOrNull(right) != null
+                        && 
getBigDecimalOrNull(right).compareTo(BigDecimal.ZERO) == 0,
+                        true),
+                (left,right) -> null
+        );
+
+        // duration ÷ number
+        map.put(new CheckedPredicate((left,right) -> left instanceof Duration 
&& right instanceof Number, false),
+                (left,right) -> {
+                    Duration dur = (Duration) left;
+                    BigDecimal nanos = BigDecimal.valueOf(dur.toNanos());
+                    BigDecimal divisor = getBigDecimalOrNull(right);
+                    if (divisor==null || 
divisor.compareTo(BigDecimal.ZERO)==0) return null;
+                    BigDecimal scaled = nanos.divide(divisor, 0, 
RoundingMode.HALF_EVEN);
+                    return Duration.ofNanos(scaled.longValue());
+                }
+        );
+
+        // duration ÷ duration → number
+        map.put(new CheckedPredicate((left,right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left,right) -> {
+                    BigDecimal leftSecs = getBigDecimalOrNull(((Duration) 
left).getSeconds());
+                    BigDecimal rightSecs = getBigDecimalOrNull(((Duration) 
right).getSeconds());
+                    if (leftSecs==null || rightSecs==null || 
rightSecs.compareTo(BigDecimal.ZERO)==0) return null;
+                    return leftSecs.divide(rightSecs, MathContext.DECIMAL128);
+                }
+        );
+
+        // period ÷ number
+        map.put(new CheckedPredicate((left,right) -> left instanceof 
ChronoPeriod && right instanceof Number, true),
+                (left,right) -> {
+                    BigDecimal months = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left));
+                    BigDecimal divisor = getBigDecimalOrNull(right);
+                    if (months==null || divisor==null || 
divisor.compareTo(BigDecimal.ZERO)==0) return null;
+                    BigDecimal scaled = months.divide(divisor, 
MathContext.DECIMAL128);
+                    return ComparablePeriod.ofMonths(scaled.intValue());
+                }
+        );
+
+        // period ÷ period → number
+        map.put(new CheckedPredicate((left,right) -> left instanceof 
ChronoPeriod && right instanceof ChronoPeriod, false),
+                (left,right) -> {
+                    BigDecimal leftMonths = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left));
+                    BigDecimal rightMonths = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) right));
+                    if (leftMonths==null || rightMonths==null || 
rightMonths.compareTo(BigDecimal.ZERO)==0) return null;
+                    return leftMonths.divide(rightMonths, 
MathContext.DECIMAL128);
+                }
+        );
+
+        // left or right == null --> null
+        map.put(new CheckedPredicate((left,right) -> left==null || 
right==null, false), (left,right) -> null);
+
+        return map;
+    }
+
+    /**
+     * A wrapper around a BiPredicate used to determine whether a given pair 
of operands
+     *  Matches a particular operation rule, with an additional flag 
indicating whether an error
+     *  notification should be raised when the operation result is null.
+     */
+    public static class CheckedPredicate {
+        final BiPredicate<Object, Object> predicate;
+        final boolean toNotify;
+
+        CheckedPredicate(BiPredicate<Object, Object> predicate, boolean 
toNotify) {
+            this.predicate = predicate;
+            this.toNotify = toNotify;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (!(obj instanceof CheckedPredicate))
+                return false;
+            CheckedPredicate other = (CheckedPredicate) obj;
+            return Objects.equals(this.predicate, other.predicate);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(predicate);
+        }
+    }
+
+    @Override
+    public Object executeAdd(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getAddOperations(ctx));
+    }
+
+    @Override
+    public Object executeAnd(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getAndOperations(ctx));
+    }
+
+    @Override
+    public Object executeEqual(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getEqualOperations(ctx));
+    }
+
+    @Override
+    public Object executeGte(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getGteOperations(ctx));
+    }
+
+    @Override
+    public Object executeGt(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getGtOperations(ctx));
+    }
+
+    @Override
+    public Object executeLte(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getLteOperations(ctx));
+    }
+
+    @Override
+    public Object executeLt(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getLtOperations(ctx));
+    }
+
+    @Override
+    public Object executeNotEqual(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getNotEqualOperations(ctx));
+    }
+
+    @Override
+    public Object executeOr(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getOrOperations(ctx));
+    }
+
+    @Override
+    public Object executePow(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getPowOperations(ctx));
+    }
+
+    @Override
+    public Object executeSub(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getSubOperations(ctx));
+    }
+
+    @Override
+    public Object executeMult(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getMultOperations(ctx));
+    }
+
+    @Override
+    public Object executeDivision(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getDivisionOperations(ctx));
+    }
+
+    /**
+     * Executes a binary operation defined in the given operation map against 
the provided operands.
+     * @param left : the left operand of the operation;
+     * @param right : the right operand of the operation;
+     * @param ctx : the current EvaluationContext
+     * @param operationMap : the map of CheckedPredicate to BiFunction 
defining available operations
+     * @return : the result of applying the matched operation, or null if the 
operation is undefined or produces no result
+     */
+    private Object executeOperation(
+            Object left,
+            Object right,
+            EvaluationContext ctx,
+            Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
operationMap
+    ) {
+        Optional<Map.Entry<CheckedPredicate, BiFunction<Object, Object, 
Object>>> match =
+                operationMap.entrySet().stream()
+                        .filter(entry -> entry.getKey().predicate.test(left, 
right))
+                        .findFirst();
+
+        if (match.isPresent()) {
+            Object result = match.get().getValue().apply(left, right);
+            if (result == null && match.get().getKey().toNotify) {
+                ctx.notifyEvt(() -> new InvalidParametersEvent(
+                        FEELEvent.Severity.ERROR,
+                        Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()
+                ));
+            }
+            return result;
+        }
+
+        ctx.notifyEvt(() -> new InvalidParametersEvent(
+                FEELEvent.Severity.ERROR,
+                Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()
+        ));
+        return null;

Review Comment:
   The `executeOperation` method in `DefaultDialectHandler` notifies with 
`FEELEvent.Severity.ERROR` when no operation matches (line 710-713), but this 
doesn't respect the BFEEL dialect which should use `WARN` severity. The method 
should use `commonManageInvalidParameters(ctx)` instead to handle 
dialect-specific severity.
   
   Should be:
   ```java
   commonManageInvalidParameters(ctx);
   ```
   ```suggestion
           commonManageInvalidParameters(ctx);
           return null;
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java:
##########
@@ -0,0 +1,716 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import ch.obermuhlner.math.big.BigDecimalMath;
+import org.kie.dmn.api.feel.runtime.events.FEELEvent;
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+import org.kie.dmn.feel.util.Msg;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAmount;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.BiPredicate;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+import static org.kie.dmn.feel.util.NumberEvalHelper.getBigDecimalOrNull;
+
+/**
+ *  Base implementation of the DialectHandler interface providing common
+ *  functionality for all dialects.
+ */
+public abstract class DefaultDialectHandler implements DialectHandler {
+
+    /**
+     * Builds the common 'Addition' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Addition' operations
+     */
+    protected Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getCommonAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // Number + Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimalOrNull(left);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.add(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Duration + LocalDate
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof LocalDate, false),
+                (left, right) -> addLocalDateAndDuration((LocalDate) right, 
(Duration) left)
+        );
+
+        // LocalDate + Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Duration, false),
+                (left, right) -> addLocalDateAndDuration((LocalDate) left, 
(Duration) right)
+        );
+
+        // Duration + Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left, right) -> ((Duration) left).plus((Duration) right)
+        );
+
+        // Temporal + TemporalAmount
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof TemporalAmount, false),
+                (left, right) -> ((Temporal) left).plus((TemporalAmount) right)
+        );
+
+        // TemporalAmount + Temporal
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
TemporalAmount && right instanceof Temporal, false),
+                (left, right) -> ((Temporal) right).plus((TemporalAmount) left)
+        );
+
+        // TemporalAmount + ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
TemporalAmount && right instanceof ChronoPeriod, false),
+                (left, right) -> ((ChronoPeriod) right).plus((TemporalAmount) 
left)
+        );
+
+        // left or right -> null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+        return map;
+    }
+
+
+    /**
+     * Builds the common 'And' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'And' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // false AND anything → false (short‑circuit)
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // true AND true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // true AND false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // true AND otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect))
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        // otherwise AND true → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> null
+        );
+
+        // otherwise AND false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // otherwise AND otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Equal' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Equal' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonEqualOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.isEqual(left, right, 
dialect)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Greater than Or EqualTo' operation map used by the 
dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Greater than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonGteOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left > right OR left == right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> InfixExecutorUtils.or(
+                        BooleanEvalHelper.compare(left, right, dialect, 
(leftNum, rightNum) -> leftNum.compareTo(rightNum) > 0),
+                        BooleanEvalHelper.isEqual(left, right, dialect),
+                        ctx
+                )
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Greater than' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Greater than' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonGtOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left > right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.compare(left, right, 
dialect, (leftNum, rightNum) -> leftNum.compareTo(rightNum) > 0)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Less than Or EqualTo' operation map used by the 
dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Less than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonLteOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left < right OR left == right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> InfixExecutorUtils.or(
+                        BooleanEvalHelper.compare(left, right, dialect, 
(leftNum, rightNum) -> leftNum.compareTo(rightNum) < 0),
+                        BooleanEvalHelper.isEqual(left, right, dialect),
+                        ctx
+                )
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Less than' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Less than Or EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonLtOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // left < right
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> BooleanEvalHelper.compare(left, right, 
dialect, (leftNum, rightNum) -> leftNum.compareTo(rightNum) < 0)
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Not EqualTo' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Not EqualTo' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonNotEqualOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> {
+                    Boolean result = BooleanEvalHelper.isEqual(left, right, 
dialect);
+                    return result != null ? !result : null;
+                }
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Or' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Or operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonOrOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // true OR anything → true (short‑circuit)
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.TRUE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // false OR true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // false OR false → false
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // false OR otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
Boolean.FALSE.equals(BooleanEvalHelper.getBooleanOrDialectDefault(left, 
dialect))
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        // otherwise OR true → true
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.TRUE.equals(evalRight(right, ctx)), false),
+                (left, right) -> Boolean.TRUE
+        );
+
+        // otherwise OR false → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && Boolean.FALSE.equals(evalRight(right, ctx)), false),
+                (left, right) -> null
+        );
+
+        // otherwise OR otherwise → null
+        map.put(
+                new CheckedPredicate((left, right) -> 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect) == null
+                        && evalRight(right, ctx) == null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Power of' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Power of' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonPowOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        map.put(
+                new CheckedPredicate((left, right) -> true, false),
+                (left, right) -> math(left, right, ctx,
+                        (l, r) -> BigDecimalMath.pow(l, r, 
MathContext.DECIMAL128))
+        );
+        return map;
+    }
+
+    /**
+     * Builds the common 'Substraction' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Substraction' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonSubOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        // null - Number
+        map.put(
+                new CheckedPredicate((left, right) ->
+                        (left == null && right instanceof Number) || (right == 
null && left instanceof Number), false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimal(left, ctx);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.subtract(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Number - Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimal(left, ctx);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.subtract(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // LocalDate - Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Duration, false),
+                (left, right) -> {
+                    LocalDateTime leftLDT = LocalDateTime.of((LocalDate) left, 
LocalTime.MIDNIGHT);
+                    LocalDateTime evaluated = leftLDT.minus((Duration) right);
+                    return LocalDate.of(evaluated.getYear(), 
evaluated.getMonth(), evaluated.getDayOfMonth());
+                }
+        );
+
+        // Duration - Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left, right) -> ((Duration) left).minus((Duration) right)
+        );
+
+        // Temporal - Temporal
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof Temporal, false),
+                (left, right) -> subtractTemporals((Temporal) left, (Temporal) 
right, ctx)
+        );
+
+        // Temporal - TemporalAmount
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Temporal 
&& right instanceof TemporalAmount, false),
+                (left, right) -> ((Temporal) left).minus((TemporalAmount) 
right)
+        );
+
+        // ChronoPeriod - ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
ChronoPeriod && right instanceof ChronoPeriod, false),
+                (left, right) -> new ComparablePeriod(((ChronoPeriod) 
left).minus((ChronoPeriod) right))
+        );
+
+
+        // left == null || right == null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+
+        return map;
+    }
+
+    /**
+     * Builds the common 'Multiplication' operation map used by the dialect 
handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Multiplication operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonMultOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Number * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal leftNum = getBigDecimalOrNull(left);
+                    BigDecimal rightNum = getBigDecimal(right, ctx);
+                    return leftNum != null && rightNum != null ? 
leftNum.multiply(rightNum, MathContext.DECIMAL128) : null;
+                }
+        );
+
+        // Number * Duration
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof Duration, false),
+                (left, right) -> Duration.ofSeconds(
+                        getBigDecimalOrNull(left)
+                                .multiply(BigDecimal.valueOf(((Duration) 
right).getSeconds()), MathContext.DECIMAL128)
+                                .longValue()
+                )
+        );
+
+        // Number * ChronoPeriod
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof ChronoPeriod, false),
+                (left, right) -> ComparablePeriod.ofMonths(
+                        getBigDecimalOrNull(left)
+                                
.multiply(getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) 
right)), MathContext.DECIMAL128)
+                                .intValue()
+                )
+        );
+
+        // Duration * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Duration 
&& right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal durationNumericValue = 
BigDecimal.valueOf(((Duration) left).toNanos());
+                    BigDecimal rightDecimal = BigDecimal.valueOf(((Number) 
right).doubleValue());
+                    return 
Duration.ofNanos(durationNumericValue.multiply(rightDecimal).longValue());
+                }
+        );
+        // ChronoPeriod * Number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
ChronoPeriod && right instanceof Number, false),
+                (left, right) -> {
+                    BigDecimal rightNumber = getBigDecimal(right, ctx);
+                    return ComparablePeriod.ofMonths(
+                            
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left))
+                                    .multiply(rightNumber, 
MathContext.DECIMAL128)
+                                    .intValue()
+                    );
+                }
+        );
+
+
+        // left or right == null
+        map.put(
+                new CheckedPredicate((left, right) -> left == null || right == 
null, false),
+                (left, right) -> null
+        );
+
+       return map;
+    }
+
+    /**
+     * Builds the common 'Division' operation map used by the dialect handlers.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
common 'Division' operations
+     */
+    Map<DefaultDialectHandler.CheckedPredicate, BiFunction<Object, Object, 
Object>> getCommonDivisionOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // Number ÷ Number
+        map.put(
+                new CheckedPredicate((left,right) -> left instanceof Number && 
right instanceof Number
+                        && getBigDecimalOrNull(right) != null
+                        && 
getBigDecimalOrNull(right).compareTo(BigDecimal.ZERO) != 0,
+                        false),
+                (left,right) -> {
+                    BigDecimal leftBD = getBigDecimalOrNull(left);
+                    BigDecimal rightBD = getBigDecimalOrNull(right);
+                    return leftBD.divide(rightBD, MathContext.DECIMAL128);
+                }
+        );
+
+        // Number ÷ Number , Division by zero case → notify
+        map.put(
+                new CheckedPredicate((left,right) -> left instanceof Number && 
right instanceof Number
+                        && getBigDecimalOrNull(right) != null
+                        && 
getBigDecimalOrNull(right).compareTo(BigDecimal.ZERO) == 0,
+                        true),
+                (left,right) -> null
+        );
+
+        // duration ÷ number
+        map.put(new CheckedPredicate((left,right) -> left instanceof Duration 
&& right instanceof Number, false),
+                (left,right) -> {
+                    Duration dur = (Duration) left;
+                    BigDecimal nanos = BigDecimal.valueOf(dur.toNanos());
+                    BigDecimal divisor = getBigDecimalOrNull(right);
+                    if (divisor==null || 
divisor.compareTo(BigDecimal.ZERO)==0) return null;
+                    BigDecimal scaled = nanos.divide(divisor, 0, 
RoundingMode.HALF_EVEN);
+                    return Duration.ofNanos(scaled.longValue());
+                }
+        );
+
+        // duration ÷ duration → number
+        map.put(new CheckedPredicate((left,right) -> left instanceof Duration 
&& right instanceof Duration, false),
+                (left,right) -> {
+                    BigDecimal leftSecs = getBigDecimalOrNull(((Duration) 
left).getSeconds());
+                    BigDecimal rightSecs = getBigDecimalOrNull(((Duration) 
right).getSeconds());
+                    if (leftSecs==null || rightSecs==null || 
rightSecs.compareTo(BigDecimal.ZERO)==0) return null;
+                    return leftSecs.divide(rightSecs, MathContext.DECIMAL128);
+                }
+        );
+
+        // period ÷ number
+        map.put(new CheckedPredicate((left,right) -> left instanceof 
ChronoPeriod && right instanceof Number, true),
+                (left,right) -> {
+                    BigDecimal months = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left));
+                    BigDecimal divisor = getBigDecimalOrNull(right);
+                    if (months==null || divisor==null || 
divisor.compareTo(BigDecimal.ZERO)==0) return null;
+                    BigDecimal scaled = months.divide(divisor, 
MathContext.DECIMAL128);
+                    return ComparablePeriod.ofMonths(scaled.intValue());
+                }
+        );
+
+        // period ÷ period → number
+        map.put(new CheckedPredicate((left,right) -> left instanceof 
ChronoPeriod && right instanceof ChronoPeriod, false),
+                (left,right) -> {
+                    BigDecimal leftMonths = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) left));
+                    BigDecimal rightMonths = 
getBigDecimalOrNull(ComparablePeriod.toTotalMonths((ChronoPeriod) right));
+                    if (leftMonths==null || rightMonths==null || 
rightMonths.compareTo(BigDecimal.ZERO)==0) return null;
+                    return leftMonths.divide(rightMonths, 
MathContext.DECIMAL128);
+                }
+        );
+
+        // left or right == null --> null
+        map.put(new CheckedPredicate((left,right) -> left==null || 
right==null, false), (left,right) -> null);
+
+        return map;
+    }
+
+    /**
+     * A wrapper around a BiPredicate used to determine whether a given pair 
of operands
+     *  Matches a particular operation rule, with an additional flag 
indicating whether an error
+     *  notification should be raised when the operation result is null.
+     */
+    public static class CheckedPredicate {
+        final BiPredicate<Object, Object> predicate;
+        final boolean toNotify;
+
+        CheckedPredicate(BiPredicate<Object, Object> predicate, boolean 
toNotify) {
+            this.predicate = predicate;
+            this.toNotify = toNotify;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (!(obj instanceof CheckedPredicate))
+                return false;
+            CheckedPredicate other = (CheckedPredicate) obj;
+            return Objects.equals(this.predicate, other.predicate);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(predicate);
+        }
+    }
+
+    @Override
+    public Object executeAdd(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getAddOperations(ctx));
+    }
+
+    @Override
+    public Object executeAnd(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getAndOperations(ctx));
+    }
+
+    @Override
+    public Object executeEqual(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getEqualOperations(ctx));
+    }
+
+    @Override
+    public Object executeGte(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getGteOperations(ctx));
+    }
+
+    @Override
+    public Object executeGt(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getGtOperations(ctx));
+    }
+
+    @Override
+    public Object executeLte(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getLteOperations(ctx));
+    }
+
+    @Override
+    public Object executeLt(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getLtOperations(ctx));
+    }
+
+    @Override
+    public Object executeNotEqual(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getNotEqualOperations(ctx));
+    }
+
+    @Override
+    public Object executeOr(Object left, Object right, EvaluationContext ctx) {
+        return executeOperation(left, right, ctx, getOrOperations(ctx));
+    }
+
+    @Override
+    public Object executePow(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getPowOperations(ctx));
+    }
+
+    @Override
+    public Object executeSub(Object left, Object right, EvaluationContext ctx) 
{
+        return executeOperation(left, right, ctx, getSubOperations(ctx));
+    }
+
+    @Override
+    public Object executeMult(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getMultOperations(ctx));
+    }
+
+    @Override
+    public Object executeDivision(Object left, Object right, EvaluationContext 
ctx) {
+        return executeOperation(left, right, ctx, getDivisionOperations(ctx));
+    }
+
+    /**
+     * Executes a binary operation defined in the given operation map against 
the provided operands.
+     * @param left : the left operand of the operation;
+     * @param right : the right operand of the operation;
+     * @param ctx : the current EvaluationContext
+     * @param operationMap : the map of CheckedPredicate to BiFunction 
defining available operations
+     * @return : the result of applying the matched operation, or null if the 
operation is undefined or produces no result
+     */
+    private Object executeOperation(
+            Object left,
+            Object right,
+            EvaluationContext ctx,
+            Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
operationMap
+    ) {
+        Optional<Map.Entry<CheckedPredicate, BiFunction<Object, Object, 
Object>>> match =
+                operationMap.entrySet().stream()
+                        .filter(entry -> entry.getKey().predicate.test(left, 
right))
+                        .findFirst();
+
+        if (match.isPresent()) {
+            Object result = match.get().getValue().apply(left, right);
+            if (result == null && match.get().getKey().toNotify) {
+                ctx.notifyEvt(() -> new InvalidParametersEvent(
+                        FEELEvent.Severity.ERROR,
+                        Msg.OPERATION_IS_UNDEFINED_FOR_PARAMETERS.getMask()
+                ));

Review Comment:
   In the `executeOperation` method, when `result == null && 
match.get().getKey().toNotify`, it always uses `FEELEvent.Severity.ERROR` (line 
703). This doesn't respect the BFEEL dialect. The notification should use 
`commonManageInvalidParameters(ctx)` to handle dialect-specific severity.
   
   Should use:
   ```java
   if (result == null && match.get().getKey().toNotify) {
       commonManageInvalidParameters(ctx);
   }
   ```
   ```suggestion
                   commonManageInvalidParameters(ctx);
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonEqualOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getNotEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonNotEqualOperations(ctx));
+    }
+
+    /**
+     * Builds the BFeel specific 'OR' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'OR' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getOrOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // Special case: false OR null/otherwise → false (BFEEL override)
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.FALSE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        // Fall back to FEEL semantics for all other cases
+        map.putAll(getCommonOrOperations(ctx));
+        return map;
+    }
+
+    /**
+     * Builds the BFeel specific 'Power' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Power' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getPowOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        //TODO Change pow behaviour for BFeel
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> Boolean.FALSE

Review Comment:
   The comment on line 191 says "TODO Change pow behaviour for BFeel" but the 
code returns `Boolean.FALSE` which is incorrect. This TODO should be resolved 
before merging - power operations should return numeric values, not booleans.
   ```suggestion
                   (left, right) -> null
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/infixexecutors/AndExecutor.java:
##########
@@ -37,23 +36,13 @@ public static AndExecutor instance() {
 
     @Override
     public Object evaluate(Object left, Object right, EvaluationContext ctx) {
-        return and(left, right, ctx);
+        DialectHandler handler = DialectHandlerFactory.getHandler(ctx);
+        return handler.executeAnd(left, right, ctx);
     }
 

Review Comment:
   [nitpick] In `AndExecutor` and `OrExecutor`, the `evaluate(InfixOpNode, 
EvaluationContext)` method now passes `infixNode.getRight()` (the AST node) 
instead of `infixNode.getRight().evaluate(ctx)` (the evaluated value). While 
this enables short-circuit evaluation, it changes the contract and the handlers 
must now handle both evaluated values and AST nodes. This inconsistency should 
be documented or the handler interface should explicitly support this pattern.
   ```suggestion
   
       /**
        * Evaluates the AND operation with short-circuit logic.
        * <p>
        * Note: The right-hand side is passed as an AST node (not an evaluated 
value)
        * to enable short-circuit evaluation. The handler must be able to 
handle both
        * evaluated values and AST nodes for the right argument.
        *
        * @param infixNode the infix operation node
        * @param ctx the evaluation context
        * @return the result of the AND operation
        */
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonEqualOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getNotEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonNotEqualOperations(ctx));
+    }
+
+    /**
+     * Builds the BFeel specific 'OR' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'OR' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getOrOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // Special case: false OR null/otherwise → false (BFEEL override)
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.FALSE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        // Fall back to FEEL semantics for all other cases
+        map.putAll(getCommonOrOperations(ctx));
+        return map;
+    }
+
+    /**
+     * Builds the BFeel specific 'Power' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Power' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getPowOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        //TODO Change pow behaviour for BFeel
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        map.putAll(getCommonPowOperations(ctx));
+        return map;
+    }
+
+    /**
+     * Builds the BFeel specific 'Substraction' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Substraction' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getSubOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        //subtraction with Strings → empty string
+        map.put(
+                new CheckedPredicate((left, right) ->
+                                (left instanceof String || right instanceof 
String), false),
+                (left, right) -> ""

Review Comment:
   [nitpick] In the `getSubOperations` method, the comment says "subtraction 
with Strings → empty string", but this behavior seems inconsistent with BFEEL 
addition operations where strings are concatenated. Consider if this is the 
correct default value for BFEEL or if it should return `BigDecimal.ZERO` for 
consistency with other numeric operations.
   ```suggestion
           // subtraction with Strings → BigDecimal.ZERO for consistency with 
numeric operations
           map.put(
                   new CheckedPredicate((left, right) ->
                                   (left instanceof String || right instanceof 
String), false),
                   (left, right) -> BigDecimal.ZERO
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.FALSE.equals(rightBool);

Review Comment:
   The predicate for "otherwise AND otherwise → false" is checking 
`Boolean.FALSE.equals(rightBool)`, but the comment says "otherwise AND 
otherwise". This logic appears incorrect - it should check if `rightBool == 
null` to match "otherwise" values.
   
   The predicate should be:
   ```java
   return leftBool == null && rightBool == null;
   ```
   ```suggestion
                       return leftBool == null && rightBool == null;
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java:
##########
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.kie.dmn.feel.lang.ast.dialectHandlers;
+
+import org.kie.dmn.feel.lang.EvaluationContext;
+import org.kie.dmn.feel.lang.FEELDialect;
+import org.kie.dmn.feel.lang.types.impl.ComparablePeriod;
+import org.kie.dmn.feel.util.BooleanEvalHelper;
+
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+import static org.kie.dmn.feel.lang.ast.infixexecutors.InfixExecutorUtils.*;
+import static org.kie.dmn.feel.util.BooleanEvalHelper.evalRight;
+
+/**
+ *  Handler implementation of the DialectHandler interface providing BFEEL 
specific
+ *  functionalities
+ */
+public class BFEELDialectHandler extends DefaultDialectHandler implements 
DialectHandler {
+
+    /**
+     * Builds the BFeel specific 'Addition' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Addition' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAddOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+
+        // any String operand → concatenate both as strings
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> {
+                    String leftNum = getString(left);
+                    String rightNum = getString(right);
+                    return leftNum + rightNum;
+                }
+        );
+
+        // date + number → return the number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof 
LocalDate && right instanceof Number, false),
+                (left, right) -> right
+        );
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right instanceof LocalDate, false),
+                (left, right) -> left
+        );
+
+        // Number + null → number
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof Number 
&& right == null, false),
+                (left, right) -> left
+        );
+
+        // null + Number → number
+        map.put(
+                new CheckedPredicate((left, right) -> left == null && right 
instanceof Number, false),
+                (left, right) -> right
+        );
+
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getAndOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+        // Special case: true AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.TRUE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND true → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.TRUE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+
+        // Special case: otherwise AND otherwise → false
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return leftBool == null && Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        map.putAll(getCommonAddOperations(ctx));
+        return map;
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonEqualOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getGtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonGtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLteOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLteOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getLtOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonLtOperations(ctx));
+    }
+
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getNotEqualOperations(EvaluationContext ctx) {
+        return new LinkedHashMap<>(getCommonNotEqualOperations(ctx));
+    }
+
+    /**
+     * Builds the BFeel specific 'OR' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'OR' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getOrOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        FEELDialect dialect = ctx.getFEELDialect();
+
+        // Special case: false OR null/otherwise → false (BFEEL override)
+        map.put(
+                new CheckedPredicate((left, right) -> {
+                    Boolean leftBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(left, dialect);
+                    Object rightValue = evalRight(right, ctx);
+                    Boolean rightBool = 
BooleanEvalHelper.getBooleanOrDialectDefault(rightValue, dialect);
+                    return Boolean.FALSE.equals(leftBool) && 
Boolean.FALSE.equals(rightBool);
+                }, false),
+                (left, right) -> Boolean.FALSE
+        );
+        // Fall back to FEEL semantics for all other cases
+        map.putAll(getCommonOrOperations(ctx));
+        return map;
+    }
+
+    /**
+     * Builds the BFeel specific 'Power' operations.
+     * @param ctx : Current Evaluation context
+     * @return : a Map of CheckedPredicate to BiFunction representing the 
BFeel specific 'Power' operations
+     */
+    @Override
+    public Map<CheckedPredicate, BiFunction<Object, Object, Object>> 
getPowOperations(EvaluationContext ctx) {
+        Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new 
LinkedHashMap<>();
+        //TODO Change pow behaviour for BFeel
+        map.put(
+                new CheckedPredicate((left, right) -> left instanceof String 
|| right instanceof String, false),
+                (left, right) -> Boolean.FALSE

Review Comment:
   The `getPowOperations` method returns `Boolean.FALSE` for string operands. 
However, power operations should return numeric types (BigDecimal) or null, not 
Boolean values. This type mismatch will likely cause issues.
   
   Should return `BigDecimal.ZERO` or `null` instead of `Boolean.FALSE`.
   ```suggestion
                   (left, right) -> null
   ```



##########
kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/util/BooleanEvalHelper.java:
##########
@@ -286,4 +289,15 @@ static Boolean isEqualObject(Object l, Object r) {
         return true;
     }
 
+    // Evaluate right operand if it’s a node
+    public static Object evalRight(Object right, EvaluationContext ctx) {
+        if (right instanceof InfixOpNode) {
+            return ((InfixOpNode) right).evaluate(ctx);
+        } else if (right instanceof BaseNode) {
+            return ((BaseNode) right).evaluate(ctx);
+        } else {
+            return right;
+        }
+    }

Review Comment:
   [nitpick] The `evalRight` helper method is added to `BooleanEvalHelper` but 
is used specifically for evaluating AST nodes in dialect handlers. This creates 
a circular dependency concern and mixes evaluation logic with boolean helper 
utilities. Consider moving this to a more appropriate utility class or directly 
into the dialect handlers where it's used.
   ```suggestion
   
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to