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

tkobayas 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 2c350fd929 Precompile regex pattern for 'matches' operator and make it 
part of the lambda predicate class (#6469)
2c350fd929 is described below

commit 2c350fd929325e56e6131cf85b329c1e06ede234
Author: Dima Solomonov <[email protected]>
AuthorDate: Tue Oct 7 07:14:57 2025 +0300

    Precompile regex pattern for 'matches' operator and make it part of the 
lambda predicate class (#6469)
    
    * Precompile regex pattern for 'matches' operator and make it part of the 
lambda predicate class
    
    * respect dynamic regex expressions on which case fallback to the original 
path: D.eval lambda content with MatchesOperator implementation
    
    * respect more cases like negative checks, explicit cast when invoking 
matches, etc...
    
    * addressing PR comments
    
    ---------
    
    Co-authored-by: dima.solomonov <[email protected]>
---
 .../java/org/drools/model/functions/Operator.java  |   6 +-
 .../generator/expressiontyper/ExpressionTyper.java |   8 +-
 .../generator/operatorspec/NativeOperatorSpec.java |   6 +-
 .../generator/operatorspec/RegexOperatorSpec.java  | 108 +++++++++++++++++++++
 .../lambdareplace/MaterializedLambdaPredicate.java |  38 ++++++--
 .../execmodel/generator/ExpressionTyperTest.java   |  20 ++--
 .../model/codegen/project/RuleCodegenTest.java     |  16 +++
 .../resources/org/drools/simple/cep/cep-regex.drl  |  28 ++++++
 .../org/drools/mvel/parser/ast/expr/RegexExpr.java |  68 +++++++++++++
 9 files changed, 274 insertions(+), 24 deletions(-)

diff --git 
a/drools-model/drools-canonical-model/src/main/java/org/drools/model/functions/Operator.java
 
b/drools-model/drools-canonical-model/src/main/java/org/drools/model/functions/Operator.java
index b0b534f86f..ad30403ccd 100644
--- 
a/drools-model/drools-canonical-model/src/main/java/org/drools/model/functions/Operator.java
+++ 
b/drools-model/drools-canonical-model/src/main/java/org/drools/model/functions/Operator.java
@@ -61,7 +61,7 @@ public interface Operator<A, B> extends Predicate2<A, B[]> {
     String getOperatorName();
 
     class Register {
-        private static final Map<String, Operator> opMap = new HashMap<>();
+        private static final Map<String, Operator<?, ?>> opMap = new 
HashMap<>();
 
         static {
             register( InOperator.INSTANCE );
@@ -75,7 +75,7 @@ public interface Operator<A, B> extends Predicate2<A, B[]> {
             register( StringLengthWithOperator.INSTANCE );
         }
 
-        public static void register(Operator operator) {
+        public static void register(Operator<?, ?> operator) {
             opMap.put( operator.getOperatorName(), operator);
         }
 
@@ -83,7 +83,7 @@ public interface Operator<A, B> extends Predicate2<A, B[]> {
             return opMap.containsKey( opName );
         }
 
-        public static Operator getOperator(String opName) {
+        public static Operator<?, ?> getOperator(String opName) {
             return opMap.get( opName );
         }
 
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 ddfd916f29..b6d7a175eb 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
@@ -75,6 +75,7 @@ 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.NativeOperatorSpec;
 import org.drools.model.codegen.execmodel.generator.operatorspec.OperatorSpec;
+import 
org.drools.model.codegen.execmodel.generator.operatorspec.RegexOperatorSpec;
 import 
org.drools.model.codegen.execmodel.generator.operatorspec.TemporalOperatorSpec;
 import org.drools.mvel.parser.ast.expr.DrlNameExpr;
 import org.drools.mvel.parser.ast.expr.FullyQualifiedInlineCastExpr;
@@ -480,6 +481,9 @@ public class ExpressionTyper {
         if (ModelGenerator.temporalOperators.contains(operator )) {
             return TemporalOperatorSpec.INSTANCE;
         }
+        if ("matches".equals(operator)) {
+            return RegexOperatorSpec.INSTANCE;
+        }
         if ( org.drools.model.functions.Operator.Register.hasOperator( 
operator ) ) {
             return NativeOperatorSpec.INSTANCE;
         }
@@ -801,11 +805,11 @@ public class ExpressionTyper {
     private TypedExpressionCursor binaryExpr(BinaryExpr binaryExpr) {
         TypedExpressionResult left = toTypedExpression(binaryExpr.getLeft());
         TypedExpression leftTypedExpression = left.getTypedExpression()
-                                                  .orElseThrow(() -> new 
NoSuchElementException("TypedExpressionResult doesn't contain 
TypedExpression!"));
+                .orElseThrow(() -> new 
NoSuchElementException("TypedExpressionResult doesn't contain 
TypedExpression!"));
         binaryExpr.setLeft(leftTypedExpression.getExpression());
         TypedExpressionResult right = toTypedExpression(binaryExpr.getRight());
         TypedExpression rightTypedExpression = right.getTypedExpression()
-                                                    .orElseThrow(() -> new 
NoSuchElementException("TypedExpressionResult doesn't contain 
TypedExpression!"));
+                .orElseThrow(() -> new 
NoSuchElementException("TypedExpressionResult doesn't contain 
TypedExpression!"));
         binaryExpr.setRight(rightTypedExpression.getExpression());
         if 
(shouldConvertArithmeticBinaryToMethodCall(binaryExpr.getOperator(), 
leftTypedExpression.getType(), rightTypedExpression.getType())) {
             Expression compiledExpression = 
convertArithmeticBinaryToMethodCall(binaryExpr, 
leftTypedExpression.getOriginalPatternType(), ruleContext);
diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/NativeOperatorSpec.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/NativeOperatorSpec.java
index 7d77bbb9bd..89663ece09 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/NativeOperatorSpec.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/NativeOperatorSpec.java
@@ -45,7 +45,7 @@ public class NativeOperatorSpec implements OperatorSpec {
         MethodCallExpr methodCallExpr = createDslTopLevelMethod( EVAL_CALL );
 
         String opName = pointFreeExpr.getOperator().asString();
-        Operator operator = addOperatorArgument( context, methodCallExpr, 
opName );
+        Operator<?, ?> operator = addOperatorArgument( context, 
methodCallExpr, opName );
         if (operator != null && !operator.isCompatibleWithType( 
left.getRawClass() )) {
             context.addCompilationError( new InvalidExpressionErrorResult( 
"Cannot use contains on class " + left.getRawClass() + " in expression '" + 
PrintUtil.printNode(pointFreeExpr) + "'" ) );
         }
@@ -72,8 +72,8 @@ public class NativeOperatorSpec implements OperatorSpec {
                 methodCallExpr;
     }
 
-    protected Operator addOperatorArgument( RuleContext context, 
MethodCallExpr methodCallExpr, String opName ) {
-        Operator operator = Operator.Register.getOperator( opName );
+    protected Operator<?, ?> addOperatorArgument( RuleContext context, 
MethodCallExpr methodCallExpr, String opName ) {
+        Operator<?, ?> operator = Operator.Register.getOperator( opName );
         try {
             // if the operator has an INSTANCE field avoid the operator lookup 
at runtime
             operator.getClass().getField( "INSTANCE" );
diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/RegexOperatorSpec.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/RegexOperatorSpec.java
new file mode 100644
index 0000000000..f7f6731122
--- /dev/null
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/operatorspec/RegexOperatorSpec.java
@@ -0,0 +1,108 @@
+/*
+ * 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.drools.model.codegen.execmodel.generator.operatorspec;
+
+import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.NodeList;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.body.VariableDeclarator;
+import com.github.javaparser.ast.expr.EnclosedExpr;
+import com.github.javaparser.ast.expr.Expression;
+import com.github.javaparser.ast.expr.MethodCallExpr;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.CastExpr;
+import com.github.javaparser.ast.expr.BinaryExpr;
+import com.github.javaparser.ast.expr.NullLiteralExpr;
+import com.github.javaparser.ast.expr.UnaryExpr;
+import com.github.javaparser.ast.expr.StringLiteralExpr;
+import org.drools.model.codegen.execmodel.generator.RuleContext;
+import org.drools.model.codegen.execmodel.generator.TypedExpression;
+import 
org.drools.model.codegen.execmodel.generator.expressiontyper.ExpressionTyper;
+import org.drools.mvel.parser.ast.expr.PointFreeExpr;
+import org.drools.mvel.parser.ast.expr.RegexExpr;
+
+import java.util.regex.Pattern;
+
+import static 
org.drools.model.codegen.execmodel.generator.DrlxParseUtil.toClassOrInterfaceType;
+import static org.drools.util.StringUtils.md5Hash;
+
+public class RegexOperatorSpec extends NativeOperatorSpec {
+    public static final RegexOperatorSpec INSTANCE = new RegexOperatorSpec();
+
+    public Expression getExpression(RuleContext context, PointFreeExpr 
pointFreeExpr, TypedExpression left, ExpressionTyper expressionTyper) {
+        if (canPrecompileRegex(pointFreeExpr.getRight())) {
+            Expression regexExpression = pointFreeExpr.getRight().getFirst()
+                    .orElseThrow(() -> new IllegalStateException("Failed to 
parse regex expression"));
+
+            NameExpr regexFieldName = new NameExpr("regexp_" + 
md5Hash(regexExpression.toString()));
+
+            return new RegexExpr(
+                    getClassMemberFieldDeclaration(regexFieldName, 
regexExpression),
+                    getClassMemberInvocationExpression(pointFreeExpr, left, 
regexFieldName)
+            );
+        } else {
+            return super.getExpression(context, pointFreeExpr, left, 
expressionTyper);
+        }
+    }
+
+    private EnclosedExpr getClassMemberInvocationExpression(PointFreeExpr 
pointFreeExpr, TypedExpression left, NameExpr regexFieldName) {
+        // we need to cast the left expression to CharSequence, otherwise it 
might fail in cases of missing type safety
+        // e.g. test method parameters (_this) is of a raw type Map
+        EnclosedExpr typeSafeStringToMatch = new EnclosedExpr(new 
CastExpr(toClassOrInterfaceType(CharSequence.class), left.getExpression()));
+
+        MethodCallExpr matchesCallExpr = new MethodCallExpr(
+                new MethodCallExpr(regexFieldName, "matcher", 
NodeList.nodeList(typeSafeStringToMatch)),
+                "matches"
+        );
+
+        // null string should not match
+        BinaryExpr compoundRegexCallExpr = new BinaryExpr(
+                new BinaryExpr(left.getExpression(), new NullLiteralExpr(), 
BinaryExpr.Operator.NOT_EQUALS),
+                pointFreeExpr.isNegated() ? new UnaryExpr(matchesCallExpr, 
UnaryExpr.Operator.LOGICAL_COMPLEMENT) : matchesCallExpr,
+                BinaryExpr.Operator.AND
+        );
+
+        return new EnclosedExpr(compoundRegexCallExpr);
+    }
+
+    private FieldDeclaration getClassMemberFieldDeclaration(NameExpr 
regexFieldName, Expression regexExpression) {
+
+        MethodCallExpr compiledRegexField = new MethodCallExpr(
+                new NameExpr(Pattern.class.getName()), "compile", 
NodeList.nodeList(regexExpression)
+        );
+
+        VariableDeclarator variableDeclarator = new VariableDeclarator(
+                toClassOrInterfaceType(Pattern.class),
+                regexFieldName.getName(),
+                compiledRegexField
+        );
+
+        return new FieldDeclaration(
+                NodeList.nodeList(Modifier.privateModifier(), 
Modifier.staticModifier(), Modifier.finalModifier()),
+                variableDeclarator
+        );
+    }
+
+    private boolean canPrecompileRegex(NodeList<Expression> 
regexPatternExpression) {
+        return regexPatternExpression.size() == 1 &&
+                regexPatternExpression.getFirst()
+                        .filter(StringLiteralExpr.class::isInstance)
+                        .isPresent();
+    }
+}
diff --git 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/util/lambdareplace/MaterializedLambdaPredicate.java
 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/util/lambdareplace/MaterializedLambdaPredicate.java
index 0b3aa5fee9..dfa6175e3e 100644
--- 
a/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/util/lambdareplace/MaterializedLambdaPredicate.java
+++ 
b/drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/util/lambdareplace/MaterializedLambdaPredicate.java
@@ -19,16 +19,11 @@
 package org.drools.model.codegen.execmodel.util.lambdareplace;
 
 import com.github.javaparser.ast.Modifier;
+import com.github.javaparser.ast.Node;
 import com.github.javaparser.ast.NodeList;
 import com.github.javaparser.ast.body.EnumDeclaration;
 import com.github.javaparser.ast.body.MethodDeclaration;
-import com.github.javaparser.ast.expr.AssignExpr;
-import com.github.javaparser.ast.expr.BooleanLiteralExpr;
-import com.github.javaparser.ast.expr.Expression;
-import com.github.javaparser.ast.expr.MethodCallExpr;
-import com.github.javaparser.ast.expr.NameExpr;
-import com.github.javaparser.ast.expr.ObjectCreationExpr;
-import com.github.javaparser.ast.expr.VariableDeclarationExpr;
+import com.github.javaparser.ast.expr.*;
 import com.github.javaparser.ast.stmt.BlockStmt;
 import com.github.javaparser.ast.stmt.ExpressionStmt;
 import com.github.javaparser.ast.stmt.ReturnStmt;
@@ -36,10 +31,12 @@ import com.github.javaparser.ast.type.ClassOrInterfaceType;
 import com.github.javaparser.ast.type.PrimitiveType;
 import com.github.javaparser.utils.StringEscapeUtils;
 import org.drools.model.functions.PredicateInformation;
+import org.drools.mvel.parser.ast.expr.RegexExpr;
 
-import static 
org.drools.model.codegen.execmodel.generator.DrlxParseUtil.createSimpleAnnotation;
-import static 
org.drools.model.codegen.execmodel.generator.DrlxParseUtil.toClassOrInterfaceType;
-import static 
org.drools.model.codegen.execmodel.generator.DrlxParseUtil.toStringLiteral;
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.drools.model.codegen.execmodel.generator.DrlxParseUtil.*;
 
 public class MaterializedLambdaPredicate extends MaterializedLambda {
 
@@ -65,6 +62,11 @@ public class MaterializedLambdaPredicate extends 
MaterializedLambda {
     }
 
     private void createTestMethod(EnumDeclaration classDeclaration) {
+        collectRegexExpressions(lambdaExpr).stream()
+                .map(RegexExpr::getCompiledRegexMember)
+                .distinct()
+                .forEach(classDeclaration::addMember);
+
         MethodDeclaration methodDeclaration = 
classDeclaration.addMethod("test", Modifier.Keyword.PUBLIC);
         
methodDeclaration.setThrownExceptions(NodeList.nodeList(toClassOrInterfaceType(java.lang.Exception.class)));
         methodDeclaration.addAnnotation(createSimpleAnnotation("Override"));
@@ -76,6 +78,22 @@ public class MaterializedLambdaPredicate extends 
MaterializedLambda {
         methodDeclaration.setBody(new BlockStmt(NodeList.nodeList(new 
ReturnStmt(clone.getExpression()))));
     }
 
+    /**
+     * recursively traverse the node tree and collect all RegexExpr
+     * @param node
+     * @return
+     */
+    private Collection<RegexExpr> collectRegexExpressions(Node node) {
+        if (node instanceof RegexExpr) {
+            return Collections.singletonList((RegexExpr) node);
+        } else {
+            return node.getChildNodes().stream()
+                    .map(this::collectRegexExpressions)
+                    .flatMap(Collection::stream)
+                    .toList();
+        }
+    }
+
     private void createPredicateInformationMethod(EnumDeclaration 
classDeclaration) {
         MethodDeclaration methodDeclaration = 
classDeclaration.addMethod("predicateInformation", Modifier.Keyword.PUBLIC);
         methodDeclaration.addAnnotation("Override");
diff --git 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/generator/ExpressionTyperTest.java
 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/generator/ExpressionTyperTest.java
index fea155e03b..f1595a6c1e 100644
--- 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/generator/ExpressionTyperTest.java
+++ 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/execmodel/generator/ExpressionTyperTest.java
@@ -60,16 +60,15 @@ import static 
org.drools.model.codegen.execmodel.generator.DrlxParseUtil.THIS_PL
 public class ExpressionTyperTest {
 
     private HashSet<String> imports;
-    private PackageModel packageModel;
     private TypeResolver typeResolver;
     private RuleContext ruleContext;
-    private KnowledgeBuilderImpl knowledgeBuilder = new KnowledgeBuilderImpl();
-    private RuleDescr ruleDescr = new RuleDescr("testRule");
+    private final KnowledgeBuilderImpl knowledgeBuilder = new 
KnowledgeBuilderImpl();
+    private final RuleDescr ruleDescr = new RuleDescr("testRule");
 
     @BeforeEach
     public void setUp() throws Exception {
         imports = new HashSet<>();
-        packageModel = new PackageModel("", "", null, null, new 
DRLIdGenerator());
+        PackageModel packageModel = new PackageModel("", "", null, null, new 
DRLIdGenerator());
         typeResolver = new ClassTypeResolver(imports, 
getClass().getClassLoader());
         ruleContext = new RuleContext(knowledgeBuilder, knowledgeBuilder, 
packageModel, typeResolver, ruleDescr);
         imports.add(Person.class.getCanonicalName());
@@ -107,11 +106,20 @@ public class ExpressionTyperTest {
     }
 
     @Test
-    public void pointFreeTest() {
+    public void pointFreeForDynamicRegexMatchesOperatorTest() {
+        final PointFreeExpr expression = new PointFreeExpr(null, new 
NameExpr("name"), NodeList.nodeList(new MethodCallExpr("getEmail")), new 
SimpleName("matches"), false, null, null, null, null);
+        TypedExpressionResult typedExpressionResult = new 
ExpressionTyper(ruleContext, Person.class, null, 
true).toTypedExpression(expression);
+        final TypedExpression actual = 
typedExpressionResult.getTypedExpression().get();
+        final TypedExpression expected = 
typedResult("D.eval(org.drools.model.operators.MatchesOperator.INSTANCE, 
_this.getName(), _this.getEmail())", String.class);
+        assertThat(actual).isEqualTo(expected);
+    }
+
+    @Test
+    public void pointFreeForStaticRegexMatchesOperatorTest() {
         final PointFreeExpr expression = new PointFreeExpr(null, new 
NameExpr("name"), NodeList.nodeList(new StringLiteralExpr("[A-Z]")), new 
SimpleName("matches"), false, null, null, null, null);
         TypedExpressionResult typedExpressionResult = new 
ExpressionTyper(ruleContext, Person.class, null, 
true).toTypedExpression(expression);
         final TypedExpression actual = 
typedExpressionResult.getTypedExpression().get();
-        final TypedExpression expected = 
typedResult("D.eval(org.drools.model.operators.MatchesOperator.INSTANCE, 
_this.getName(), \"[A-Z]\")", String.class);
+        final TypedExpression expected = typedResult("(_this.getName() != null 
&& regexp_49CE5AB50F4FBCBE25DB1AF1EC5CACE2.matcher(((java.lang.CharSequence) 
_this.getName())).matches())", String.class);
         assertThat(actual).isEqualTo(expected);
     }
 
diff --git 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/project/RuleCodegenTest.java
 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/project/RuleCodegenTest.java
index d7eb5e37b2..453b4e11de 100644
--- 
a/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/project/RuleCodegenTest.java
+++ 
b/drools-model/drools-model-codegen/src/test/java/org/drools/model/codegen/project/RuleCodegenTest.java
@@ -130,6 +130,22 @@ public class RuleCodegenTest {
         assertRules(2, 1, generatedFiles.size() - externalizedLambda - 
legacyApiFiles);
     }
 
+    @ParameterizedTest
+    
@MethodSource("org.drools.model.codegen.project.RuleCodegenTest#contextBuilders")
+    public void generateCepRegexRule(DroolsModelBuildContext.Builder 
contextBuilder) {
+        withLegacyApi(contextBuilder);
+
+        RuleCodegen ruleCodegen = getRuleCodegenFromFiles(
+                contextBuilder,
+                new File(RESOURCE_PATH + 
"/org/drools/simple/cep/cep-regex.drl"));
+
+        Collection<GeneratedFile> generatedFiles = 
ruleCodegen.withHotReloadMode().generate();
+        assertHasLegacyApiFiles(generatedFiles);
+        int externalizedLambda = 2;
+        int legacyApiFiles = 2;
+        assertRules(2, 1, generatedFiles.size() - externalizedLambda - 
legacyApiFiles);
+    }
+
     @ParameterizedTest
     
@MethodSource("org.drools.model.codegen.project.RuleCodegenTest#contextBuilders")
     public void generateCepRule(DroolsModelBuildContext.Builder 
contextBuilder) {
diff --git 
a/drools-model/drools-model-codegen/src/test/resources/org/drools/simple/cep/cep-regex.drl
 
b/drools-model/drools-model-codegen/src/test/resources/org/drools/simple/cep/cep-regex.drl
new file mode 100644
index 0000000000..4a7dfd62ad
--- /dev/null
+++ 
b/drools-model/drools-model-codegen/src/test/resources/org/drools/simple/cep/cep-regex.drl
@@ -0,0 +1,28 @@
+/**
+ * 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.drools.simple.cep
+
+import org.drools.model.codegen.project.data.Person
+
+declare Person @role(event) end
+
+rule IsTest when
+  Person( name matches "tst1", name matches "tst2" || matches "tst3" )
+then
+end
diff --git 
a/drools-model/drools-mvel-parser/src/main/java/org/drools/mvel/parser/ast/expr/RegexExpr.java
 
b/drools-model/drools-mvel-parser/src/main/java/org/drools/mvel/parser/ast/expr/RegexExpr.java
new file mode 100644
index 0000000000..9abc474479
--- /dev/null
+++ 
b/drools-model/drools-mvel-parser/src/main/java/org/drools/mvel/parser/ast/expr/RegexExpr.java
@@ -0,0 +1,68 @@
+/*
+ * 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.drools.mvel.parser.ast.expr;
+
+import com.github.javaparser.ast.AllFieldsConstructor;
+import com.github.javaparser.ast.Node;
+import com.github.javaparser.ast.body.FieldDeclaration;
+import com.github.javaparser.ast.expr.EnclosedExpr;
+import com.github.javaparser.ast.expr.LiteralExpr;
+import com.github.javaparser.ast.visitor.CloneVisitor;
+import com.github.javaparser.ast.visitor.GenericVisitor;
+import com.github.javaparser.ast.visitor.VoidVisitor;
+
+public final class RegexExpr extends LiteralExpr {
+
+    private final FieldDeclaration compiledRegexMember;
+    private final EnclosedExpr matchesEvaluationExpr;
+
+    @AllFieldsConstructor
+    public RegexExpr(FieldDeclaration compiledRegexMember, EnclosedExpr 
matchesEvaluationExpr) {
+        super();
+
+        this.compiledRegexMember = compiledRegexMember;
+        this.matchesEvaluationExpr = matchesEvaluationExpr;
+    }
+
+    @Override
+    public <R, A> R accept(GenericVisitor<R, A> v, A arg) {
+        if (v instanceof CloneVisitor) {
+            return (R) new RegexExpr(compiledRegexMember.clone(), 
matchesEvaluationExpr.clone());
+        } else {
+            return v.visit(matchesEvaluationExpr, arg);
+        }
+    }
+
+    @Override
+    public <A> void accept(VoidVisitor<A> v, A arg) {
+        v.visit(matchesEvaluationExpr, arg);
+    }
+
+    @Override
+    public boolean remove(Node node) {
+        if (node == null) {
+            return false;
+        }
+        return super.remove(node);
+    }
+
+    public FieldDeclaration getCompiledRegexMember() {
+        return compiledRegexMember;
+    }
+}


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

Reply via email to