This is an automated email from the ASF dual-hosted git repository.
tzimanyi pushed a commit to branch 8.40.x
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/8.40.x by this push:
new f4ef82c4d0 [kie-issues#986] Coerce object to String in executable
model codegen (#5761) (#5769)
f4ef82c4d0 is described below
commit f4ef82c4d0cfa3bf9f98ca7a00c983ce2716d602
Author: Tibor Zimányi <[email protected]>
AuthorDate: Thu Mar 7 08:45:37 2024 +0100
[kie-issues#986] Coerce object to String in executable model codegen
(#5761) (#5769)
---
...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 65%
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 dfd241615f..8af6d87813 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
@@ -19,6 +19,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;
@@ -27,6 +28,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;
@@ -37,35 +39,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;
@@ -89,65 +100,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 ce4e8f9133..0a951354ca 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
@@ -71,7 +71,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;
@@ -95,6 +95,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;
@@ -223,18 +224,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 8123d6ec26..e7f11dbb95 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
@@ -24,9 +24,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 1e9921709b..c69e249cbf 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
@@ -610,4 +610,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]