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 0af05e67b6 [KIE-1085] avoid wasteful creation of a custom operator per 
constraint at runtime when using the executable model (#5844)
0af05e67b6 is described below

commit 0af05e67b6e3c5aad14dd5b4cbb9f363cab932b5
Author: Mario Fusco <[email protected]>
AuthorDate: Mon Apr 15 08:26:05 2024 +0200

    [KIE-1085] avoid wasteful creation of a custom operator per constraint at 
runtime when using the executable model (#5844)
---
 .../model/codegen/execmodel/PackageModel.java      |  9 +++++++
 .../generator/expressiontyper/ExpressionTyper.java |  7 +++--
 .../generator/operatorspec/CustomOperatorSpec.java | 30 +++++++++++++++++-----
 .../integrationtests/CustomOperatorTest.java       | 21 +++++++++++++++
 4 files changed, 57 insertions(+), 10 deletions(-)

diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/PackageModel.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/PackageModel.java
index 254ddbb8e5..b3e157b96e 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/PackageModel.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/PackageModel.java
@@ -87,6 +87,7 @@ import 
org.drools.model.codegen.execmodel.generator.QueryGenerator;
 import org.drools.model.codegen.execmodel.generator.QueryParameter;
 import org.drools.model.codegen.execmodel.generator.TypedExpression;
 import org.drools.model.codegen.execmodel.generator.WindowReferenceGenerator;
+import 
org.drools.model.codegen.execmodel.generator.operatorspec.CustomOperatorSpec;
 import org.drools.model.codegen.execmodel.util.lambdareplace.CreatedClass;
 import org.drools.model.functions.PredicateInformation;
 import org.drools.modelcompiler.util.StringUtil;
@@ -187,6 +188,8 @@ public class PackageModel {
 
     private final boolean prototypesAllowed;
 
+    private final CustomOperatorSpec customOperatorSpec = new 
CustomOperatorSpec();
+
     private PackageModel( ReleaseId releaseId, String name, 
KnowledgeBuilderConfigurationImpl configuration, DialectCompiletimeRegistry 
dialectCompiletimeRegistry, DRLIdGenerator exprIdGenerator) {
         this(name, configuration, dialectCompiletimeRegistry, exprIdGenerator, 
getPkgUUID(configuration, releaseId, name));
     }
@@ -293,6 +296,10 @@ public class PackageModel {
         return exprIdGenerator;
     }
 
+    public CustomOperatorSpec getCustomOperatorSpec() {
+        return customOperatorSpec;
+    }
+
     public void addImports(Collection<String> imports) {
         this.imports.addAll(imports);
     }
@@ -612,6 +619,8 @@ public class PackageModel {
 
         rulesClass.addMember( generateListField("org.drools.model.Global", 
"globals", globals.isEmpty() && !hasRuleUnit) );
 
+        customOperatorSpec.getOperatorDeclarations().forEach( op -> 
rulesClass.addMember( parseBodyDeclaration( op ) ) );
+
         if ( !typeMetaDataExpressions.isEmpty() ) {
             BodyDeclaration<?> typeMetaDatasList = 
parseBodyDeclaration("java.util.List<org.drools.model.TypeMetaData> 
typeMetaDatas = new java.util.ArrayList<>();");
             rulesClass.addMember(typeMetaDatasList);
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 62795cec94..928ca3f62a 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
@@ -66,14 +66,13 @@ import com.github.javaparser.ast.type.ReferenceType;
 import com.github.javaparser.ast.type.Type;
 import org.drools.model.codegen.execmodel.errors.InvalidExpressionErrorResult;
 import org.drools.model.codegen.execmodel.errors.ParseExpressionErrorResult;
-import org.drools.model.codegen.execmodel.generator.TypedDeclarationSpec;
 import org.drools.model.codegen.execmodel.generator.DrlxParseUtil;
 import org.drools.model.codegen.execmodel.generator.ModelGenerator;
 import org.drools.model.codegen.execmodel.generator.RuleContext;
+import org.drools.model.codegen.execmodel.generator.TypedDeclarationSpec;
 import org.drools.model.codegen.execmodel.generator.TypedExpression;
 import org.drools.model.codegen.execmodel.generator.UnificationTypedExpression;
 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;
 import 
org.drools.model.codegen.execmodel.generator.operatorspec.TemporalOperatorSpec;
@@ -126,8 +125,8 @@ import static 
org.drools.model.codegen.execmodel.generator.expressiontyper.Flatt
 import static org.drools.mvel.parser.MvelParser.parseType;
 import static org.drools.mvel.parser.printer.PrintUtil.printNode;
 import static org.drools.util.ClassUtils.extractGenericType;
-import static org.drools.util.ClassUtils.getter2property;
 import static org.drools.util.ClassUtils.getTypeArgument;
+import static org.drools.util.ClassUtils.getter2property;
 import static org.drools.util.ClassUtils.toRawClass;
 import static org.kie.internal.ruleunit.RuleUnitUtil.isDataSource;
 
@@ -482,7 +481,7 @@ public class ExpressionTyper {
         if ( org.drools.model.functions.Operator.Register.hasOperator( 
operator ) ) {
             return NativeOperatorSpec.INSTANCE;
         }
-        return CustomOperatorSpec.INSTANCE;
+        return ruleContext.getPackageModel().getCustomOperatorSpec();
     }
 
     private TypedExpressionResult 
toTypedExpressionFromMethodCallOrField(Expression drlxExpr) {
diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/CustomOperatorSpec.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/CustomOperatorSpec.java
index d484855c23..a5d2578bdd 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/CustomOperatorSpec.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/CustomOperatorSpec.java
@@ -18,14 +18,22 @@
  */
 package org.drools.model.codegen.execmodel.generator.operatorspec;
 
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.github.javaparser.ast.expr.MethodCallExpr;
 import org.drools.base.base.ValueType;
 import org.drools.compiler.rule.builder.EvaluatorDefinition;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import org.drools.model.functions.Operator;
 import org.drools.model.codegen.execmodel.generator.RuleContext;
+import org.drools.model.functions.Operator;
 
 public class CustomOperatorSpec extends NativeOperatorSpec {
-    public static final CustomOperatorSpec INSTANCE = new CustomOperatorSpec();
+
+    private Set<String> generatedOperators = new HashSet<>();
+
+    private List<String> operatorDeclarations = new ArrayList<>();
 
     @Override
     protected Operator addOperatorArgument( RuleContext context, 
MethodCallExpr methodCallExpr, String opName ) {
@@ -34,10 +42,20 @@ public class CustomOperatorSpec extends NativeOperatorSpec {
             throw new RuntimeException( "Unknown custom operator: " + opName );
         }
 
-        String arg = "new " + CustomOperatorWrapper.class.getCanonicalName() + 
"( new " + evalDef.getClass().getCanonicalName() + "().getEvaluator(" +
-                ValueType.class.getCanonicalName() + ".OBJECT_TYPE, \"" + 
opName + "\", false, null), \"" + opName + "\")";
+        String operatorInstance = "OPERATOR_" + opName + "_INSTANCE";
+
+        if (generatedOperators.add(opName)) {
+            String operatorFieldDeclaration = "public static final " + 
Operator.class.getCanonicalName() + ".SingleValue<Object, Object> " + 
operatorInstance +
+                    " = new " + CustomOperatorWrapper.class.getCanonicalName() 
+ "( new " + evalDef.getClass().getCanonicalName() + "().getEvaluator(" +
+                    ValueType.class.getCanonicalName() + ".OBJECT_TYPE, \"" + 
opName + "\", false, null), \"" + opName + "\");";
+            operatorDeclarations.add(operatorFieldDeclaration);
+        }
 
-        methodCallExpr.addArgument( arg );
+        methodCallExpr.addArgument( 
context.getPackageModel().getRulesFileNameWithPackage() + "." + 
operatorInstance );
         return null;
     }
+
+    public List<String> getOperatorDeclarations() {
+        return operatorDeclarations;
+    }
 }
diff --git 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/CustomOperatorTest.java
 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/CustomOperatorTest.java
index 1ffeee7c02..8f7c8ef7aa 100644
--- 
a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/CustomOperatorTest.java
+++ 
b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/CustomOperatorTest.java
@@ -69,6 +69,18 @@ public class CustomOperatorTest {
         customOperatorUsingCollections(constraints);
     }
 
+    @Test
+    public void testNoOperatorInstancesCreatedAtRuntime() {
+        String constraints =
+                "    $alice : Person(name == \"Alice\")\n" +
+                "    $bob : Person(name == \"Bob\", addresses supersetOf 
$alice.addresses)\n" +
+                "    Person(name == \"Bob\", addresses supersetOf 
$alice.addresses)\n";
+
+        customOperatorUsingCollections(constraints);
+
+        
assertThat(SupersetOfEvaluatorDefinition.INSTANCES_COUNTER).isEqualTo(0);
+    }
+
     @Test
     public void testCustomOperatorUsingCollectionsInverted() {
         // DROOLS-6983
@@ -90,6 +102,9 @@ public class CustomOperatorTest {
         System.setProperty(EvaluatorOption.PROPERTY_NAME + "supersetOf", 
SupersetOfEvaluatorDefinition.class.getName());
         try {
             final KieBase kbase = 
KieBaseUtil.getKieBaseFromKieModuleFromDrl("custom-operator-test", 
kieBaseTestConfiguration, drl);
+
+            SupersetOfEvaluatorDefinition.INSTANCES_COUNTER = 0;
+
             final KieSession ksession = kbase.newKieSession();
             try {
                 final Person alice = new Person("Alice", 30);
@@ -118,6 +133,12 @@ public class CustomOperatorTest {
 
         private Evaluator[] evaluator;
 
+        static int INSTANCES_COUNTER = 0;
+
+        public SupersetOfEvaluatorDefinition() {
+            INSTANCES_COUNTER++;
+        }
+
         public String[] getEvaluatorIds() {
             return SupersetOfEvaluatorDefinition.SUPPORTED_IDS;
         }


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

Reply via email to