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

mariofusco pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new 30e2da3dde [kie-issues#986] Coerce object to String in executable 
model codegen (#5761)
30e2da3dde is described below

commit 30e2da3dde39fd1d6f14aa51867b8a3f5bbc76fe
Author: Tibor Zimányi <[email protected]>
AuthorDate: Wed Mar 6 09:53:37 2024 +0100

    [kie-issues#986] Coerce object to String in executable model codegen (#5761)
    
    * [kie-issues#986] Coerce object to String in executable model code 
generation.
    
    * [kie-issues#986] Simplify check for need of coercion.
    
    * Extract the check for coercion.
    
    * Update names of the classes for number and string arithmetic coercion.
---
 ...umberAndStringArithmeticOperationCoercion.java} | 88 ++++++++--------------
 .../generator/expressiontyper/ExpressionTyper.java | 23 +++---
 ...rAndStringArithmeticOperationCoercionTest.java} |  4 +-
 .../model/codegen/execmodel/TypeCoercionTest.java  | 26 +++++++
 .../src/main/java/org/drools/util/Pair.java        | 28 +++++++
 5 files changed, 97 insertions(+), 72 deletions(-)

diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/ArithmeticCoercedExpression.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/NumberAndStringArithmeticOperationCoercion.java
similarity index 66%
rename from 
drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/ArithmeticCoercedExpression.java
rename to 
drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/NumberAndStringArithmeticOperationCoercion.java
index 765a6b313e..82d7c8c854 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/ArithmeticCoercedExpression.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/drlxparse/NumberAndStringArithmeticOperationCoercion.java
@@ -20,6 +20,7 @@ package 
org.drools.model.codegen.execmodel.generator.drlxparse;
 
 import java.math.BigDecimal;
 import java.util.HashSet;
+import java.util.Optional;
 import java.util.Set;
 
 import com.github.javaparser.ast.expr.BinaryExpr.Operator;
@@ -28,6 +29,7 @@ import com.github.javaparser.ast.expr.MethodCallExpr;
 import com.github.javaparser.ast.expr.NameExpr;
 import org.drools.model.codegen.execmodel.errors.InvalidExpressionErrorResult;
 import org.drools.model.codegen.execmodel.generator.TypedExpression;
+import org.drools.util.Pair;
 
 import static com.github.javaparser.ast.NodeList.nodeList;
 import static com.github.javaparser.ast.expr.BinaryExpr.Operator.DIVIDE;
@@ -38,35 +40,44 @@ import static 
com.github.javaparser.ast.expr.BinaryExpr.Operator.REMAINDER;
 import static java.util.Arrays.asList;
 import static org.drools.util.ClassUtils.isNumericClass;
 
-public class ArithmeticCoercedExpression {
+public final class NumberAndStringArithmeticOperationCoercion {
 
-    private final TypedExpression left;
-    private final TypedExpression right;
-    private final Operator operator;
+    private NumberAndStringArithmeticOperationCoercion() {
+    }
 
     private static final Set<Operator> arithmeticOperators = new 
HashSet<>(asList(PLUS, MINUS, MULTIPLY, DIVIDE, REMAINDER));
 
-    public ArithmeticCoercedExpression(TypedExpression left, TypedExpression 
right, Operator operator) {
-        this.left = left;
-        this.right = right;
-        this.operator = operator;
+    public static Pair<TypedExpression, TypedExpression> coerceIfNeeded(final 
Operator operator, final TypedExpression left, final TypedExpression right) {
+        if (requiresCoercion(operator, left, right)) {
+            return coerce(operator, left, right);
+        } else {
+            return new Pair<>(null, null);
+        }
+    }
+
+    public static boolean requiresCoercion(final Operator operator, final 
TypedExpression left, final TypedExpression right) {
+        if (!arithmeticOperators.contains(operator)) {
+            return false;
+        }
+        return canCoerce(left.getRawClass(), right.getRawClass());
+    }
+
+    private static boolean canCoerce(Class<?> leftClass, Class<?> rightClass) {
+        return leftClass == String.class && isNumericClass(rightClass) ||
+                rightClass == String.class && isNumericClass(leftClass);
     }
 
     /*
      * This coercion only deals with String vs Numeric types.
      * BigDecimal arithmetic operation is handled by 
ExpressionTyper.convertArithmeticBinaryToMethodCall()
      */
-    public ArithmeticCoercedExpressionResult coerce() {
-
-        if (!requiresCoercion()) {
-            return new ArithmeticCoercedExpressionResult(left, right); // do 
not coerce
-        }
+    private static Pair<TypedExpression, TypedExpression> coerce(final 
Operator operator, final TypedExpression left, final TypedExpression right) {
 
         final Class<?> leftClass = left.getRawClass();
         final Class<?> rightClass = right.getRawClass();
 
         if (!canCoerce(leftClass, rightClass)) {
-            throw new ArithmeticCoercedExpressionException(new 
InvalidExpressionErrorResult("Arithmetic operation requires compatible types. 
Found " + leftClass + " and " + rightClass));
+            throw new NumberAndStringArithmeticOperationCoercionException(new 
InvalidExpressionErrorResult("Arithmetic operation requires compatible types. 
Found " + leftClass + " and " + rightClass));
         }
 
         TypedExpression coercedLeft = left;
@@ -90,65 +101,26 @@ public class ArithmeticCoercedExpression {
             }
         }
 
-        return new ArithmeticCoercedExpressionResult(coercedLeft, 
coercedRight);
+        return new Pair<>(coercedLeft, coercedRight);
     }
 
-    private boolean requiresCoercion() {
-        if (!arithmeticOperators.contains(operator)) {
-            return false;
-        }
-        final Class<?> leftClass = left.getRawClass();
-        final Class<?> rightClass = right.getRawClass();
-        if (leftClass == rightClass) {
-            return false;
-        }
-        if (isNumericClass(leftClass) && isNumericClass(rightClass)) {
-            return false;
-        }
-        return true;
-    }
-
-    private boolean canCoerce(Class<?> leftClass, Class<?> rightClass) {
-        return leftClass == String.class && isNumericClass(rightClass) ||
-               rightClass == String.class && isNumericClass(leftClass);
-    }
-
-    private TypedExpression coerceToDouble(TypedExpression typedExpression) {
+    private static TypedExpression coerceToDouble(TypedExpression 
typedExpression) {
         final Expression expression = typedExpression.getExpression();
         TypedExpression coercedExpression = 
typedExpression.cloneWithNewExpression(new MethodCallExpr(new 
NameExpr("Double"), "valueOf", nodeList(expression)));
         return coercedExpression.setType(BigDecimal.class);
     }
 
-    private TypedExpression coerceToString(TypedExpression typedExpression) {
+    private static TypedExpression coerceToString(TypedExpression 
typedExpression) {
         final Expression expression = typedExpression.getExpression();
         TypedExpression coercedExpression = 
typedExpression.cloneWithNewExpression(new MethodCallExpr(new 
NameExpr("String"), "valueOf", nodeList(expression)));
         return coercedExpression.setType(String.class);
     }
 
-    public static class ArithmeticCoercedExpressionResult {
-
-        private final TypedExpression coercedLeft;
-        private final TypedExpression coercedRight;
-
-        public ArithmeticCoercedExpressionResult(TypedExpression left, 
TypedExpression coercedRight) {
-            this.coercedLeft = left;
-            this.coercedRight = coercedRight;
-        }
-
-        public TypedExpression getCoercedLeft() {
-            return coercedLeft;
-        }
-
-        public TypedExpression getCoercedRight() {
-            return coercedRight;
-        }
-    }
-
-    public static class ArithmeticCoercedExpressionException extends 
RuntimeException {
+    public static class NumberAndStringArithmeticOperationCoercionException 
extends RuntimeException {
 
         private final transient InvalidExpressionErrorResult 
invalidExpressionErrorResult;
 
-        ArithmeticCoercedExpressionException(InvalidExpressionErrorResult 
invalidExpressionErrorResult) {
+        
NumberAndStringArithmeticOperationCoercionException(InvalidExpressionErrorResult
 invalidExpressionErrorResult) {
             this.invalidExpressionErrorResult = invalidExpressionErrorResult;
         }
 
diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/expressiontyper/ExpressionTyper.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/expressiontyper/ExpressionTyper.java
index 79db23e1c1..f95c603792 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/expressiontyper/ExpressionTyper.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/expressiontyper/ExpressionTyper.java
@@ -72,7 +72,7 @@ import 
org.drools.model.codegen.execmodel.generator.ModelGenerator;
 import org.drools.model.codegen.execmodel.generator.RuleContext;
 import org.drools.model.codegen.execmodel.generator.TypedExpression;
 import org.drools.model.codegen.execmodel.generator.UnificationTypedExpression;
-import 
org.drools.model.codegen.execmodel.generator.drlxparse.ArithmeticCoercedExpression;
+import 
org.drools.model.codegen.execmodel.generator.drlxparse.NumberAndStringArithmeticOperationCoercion;
 import 
org.drools.model.codegen.execmodel.generator.operatorspec.CustomOperatorSpec;
 import 
org.drools.model.codegen.execmodel.generator.operatorspec.NativeOperatorSpec;
 import org.drools.model.codegen.execmodel.generator.operatorspec.OperatorSpec;
@@ -96,6 +96,7 @@ import org.drools.mvelcompiler.CompiledExpressionResult;
 import org.drools.mvelcompiler.ConstraintCompiler;
 import org.drools.mvelcompiler.util.BigDecimalArgumentCoercion;
 import org.drools.util.MethodUtils;
+import org.drools.util.Pair;
 import org.drools.util.TypeResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -224,18 +225,16 @@ public class ExpressionTyper {
             TypedExpression left = optLeft.get();
             TypedExpression right = optRight.get();
 
-            ArithmeticCoercedExpression.ArithmeticCoercedExpressionResult 
coerced;
-            try {
-                coerced = new ArithmeticCoercedExpression(left, right, 
operator).coerce();
-            } catch 
(ArithmeticCoercedExpression.ArithmeticCoercedExpressionException e) {
-                logger.error("Failed to coerce : {}", 
e.getInvalidExpressionErrorResult());
-                return empty();
+            final BinaryExpr combo;
+            final Pair<TypedExpression, TypedExpression> 
numberAndStringCoercionResult =
+                    
NumberAndStringArithmeticOperationCoercion.coerceIfNeeded(operator, left, 
right);
+            if (numberAndStringCoercionResult.hasLeft()) {
+                left = numberAndStringCoercionResult.getLeft();
             }
-
-            left = coerced.getCoercedLeft();
-            right = coerced.getCoercedRight();
-
-            final BinaryExpr combo = new BinaryExpr(left.getExpression(), 
right.getExpression(), operator);
+            if (numberAndStringCoercionResult.hasRight()) {
+                right = numberAndStringCoercionResult.getRight();
+            }
+            combo = new BinaryExpr(left.getExpression(), 
right.getExpression(), operator);
 
             if (shouldConvertArithmeticBinaryToMethodCall(operator, 
left.getType(), right.getType())) {
                 Expression expression = 
convertArithmeticBinaryToMethodCall(combo, of(typeCursor), ruleContext);
diff --git 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/ArithmeticCoecionTest.java
 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NumberAndStringArithmeticOperationCoercionTest.java
similarity index 97%
rename from 
drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/ArithmeticCoecionTest.java
rename to 
drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NumberAndStringArithmeticOperationCoercionTest.java
index 012a2532ad..b92641ad93 100644
--- 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/ArithmeticCoecionTest.java
+++ 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/NumberAndStringArithmeticOperationCoercionTest.java
@@ -26,9 +26,9 @@ import org.kie.api.runtime.KieSession;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class ArithmeticCoecionTest extends BaseModelTest {
+public class NumberAndStringArithmeticOperationCoercionTest extends 
BaseModelTest {
 
-    public ArithmeticCoecionTest(RUN_TYPE testRunType) {
+    public NumberAndStringArithmeticOperationCoercionTest(RUN_TYPE 
testRunType) {
         super(testRunType);
     }
 
diff --git 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/TypeCoercionTest.java
 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/TypeCoercionTest.java
index 95a49e3ac1..67cd73f3bd 100644
--- 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/TypeCoercionTest.java
+++ 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/TypeCoercionTest.java
@@ -612,4 +612,30 @@ public class TypeCoercionTest extends BaseModelTest {
         assertThat(list.size()).isEqualTo(1);
         assertThat(list.get(0)).isEqualTo("Mario");
     }
+
+    @Test
+    public void testCoerceObjectToString() {
+        String str = "package constraintexpression\n" +
+                "\n" +
+                "import " + Person.class.getCanonicalName() + "\n" +
+                "import java.util.List; \n" +
+                "rule \"r1\"\n" +
+                "when \n" +
+                "    $p: Person() \n" +
+                "    String(this == \"someString\" + $p)\n" +
+                "then \n" +
+                "    System.out.println($p); \n" +
+                "end \n";
+
+        KieSession ksession = getKieSession(str);
+        try {
+            Person person = new Person("someName");
+            ksession.insert(person);
+            ksession.insert(new String("someStringsomeName"));
+            int rulesFired = ksession.fireAllRules();
+            assertThat(rulesFired).isEqualTo(1);
+        } finally {
+            ksession.dispose();
+        }
+    }
 }
\ No newline at end of file
diff --git a/drools-util/src/main/java/org/drools/util/Pair.java 
b/drools-util/src/main/java/org/drools/util/Pair.java
new file mode 100644
index 0000000000..4408263db5
--- /dev/null
+++ b/drools-util/src/main/java/org/drools/util/Pair.java
@@ -0,0 +1,28 @@
+package org.drools.util;
+
+public class Pair<K, V> {
+
+    private final K left;
+    private final V right;
+
+    public Pair(K k, V v) {
+        this.left = k;
+        this.right = v;
+    }
+
+    public K getLeft() {
+        return left;
+    }
+
+    public V getRight() {
+        return right;
+    }
+
+    public boolean hasLeft() {
+        return left != null;
+    }
+
+    public boolean hasRight() {
+        return right != null;
+    }
+}


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

Reply via email to