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

tzimanyi 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 edc77d536e [incubator-kie-issues#1409]-Fixed matches function behavior 
(#6055)
edc77d536e is described below

commit edc77d536e07a9c3cf879f51351bea28e7889897
Author: bncriju <[email protected]>
AuthorDate: Fri Aug 23 12:39:55 2024 +0530

    [incubator-kie-issues#1409]-Fixed matches function behavior (#6055)
---
 .../feel/runtime/functions/MatchesFunction.java    | 79 +++++++++++-------
 .../runtime/functions/MatchesFunctionTest.java     | 94 ++++++++++++++++++----
 2 files changed, 129 insertions(+), 44 deletions(-)

diff --git 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/MatchesFunction.java
 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/MatchesFunction.java
index f6b1806ca2..79ff2a0136 100644
--- 
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/MatchesFunction.java
+++ 
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/runtime/functions/MatchesFunction.java
@@ -18,16 +18,21 @@
  */
 package org.kie.dmn.feel.runtime.functions;
 
+import java.security.InvalidParameterException;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.Collectors;
 
 import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
 import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class MatchesFunction
         extends BaseFEELFunction {
-
+    private static final Logger log = 
LoggerFactory.getLogger(MatchesFunction.class);
     public static final MatchesFunction INSTANCE = new MatchesFunction();
 
     private MatchesFunction() {
@@ -39,40 +44,58 @@ public class MatchesFunction
     }
 
     public FEELFnResult<Boolean> invoke(@ParameterName("input") String input, 
@ParameterName("pattern") String pattern, @ParameterName("flags") String flags) 
{
-        if ( input == null ) {
-            return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "input", "cannot be null" ) );
-        }
-        if ( pattern == null ) {
-            return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "pattern", "cannot be null" ) );
-        }
         try {
-            int f = processFlags( flags );
-            Pattern p = Pattern.compile( pattern, f );
-            Matcher m = p.matcher( input );
-            return FEELFnResult.ofResult( m.find() );
-        } catch ( PatternSyntaxException e ) {
-            return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "pattern", "is invalid and can not be compiled", e ) );
-        } catch ( IllegalArgumentException t ) {
+            return matchFunctionWithFlags(input,pattern,flags);
+        } catch ( PatternSyntaxException t ) {
+            return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "pattern", "is invalid and can not be compiled", t ) );
+        } catch (InvalidParameterException t ) {
+            return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, t.getMessage(), "cannot be null", t ) );
+        } catch (IllegalArgumentException t ) {
             return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "flags", "contains unknown flags", t ) );
-        } catch ( Throwable t) {
+        } catch (Throwable t) {
             return FEELFnResult.ofError( new InvalidParametersEvent( 
Severity.ERROR, "pattern", "is invalid and can not be compiled", t ) );
         }
     }
 
-    private int processFlags(String flags) {
-        int f = 0;
-        if( flags != null ) {
-            if( flags.contains( "s" ) ) {
-                f |= Pattern.DOTALL;
-            }
-            if( flags.contains( "m" ) ) {
-                f |= Pattern.MULTILINE;
-            }
-            if( flags.contains( "i" ) ) {
-                f |= Pattern.CASE_INSENSITIVE;
-            }
+    static FEELFnResult<Boolean> matchFunctionWithFlags(String input, String 
pattern, String flags) {
+        log.debug("Input:  {} , Pattern: {}, Flags: {}", input, pattern, 
flags);
+        if ( input == null ) {
+            throw new InvalidParameterException("input");
+        }
+        if ( pattern == null ) {
+            throw new InvalidParameterException("pattern");
         }
-        return f;
+            final String flagsString;
+            if (flags != null && !flags.isEmpty()) {
+                checkFlags(flags);
+                if(!flags.contains("U")){
+                    flags += "U";
+                }
+                flagsString = String.format("(?%s)", flags);
+            } else {
+                flagsString = "";
+            }
+            log.debug("flagsString: {}", flagsString);
+            String stringToBeMatched = flagsString + pattern;
+            log.debug("stringToBeMatched: {}", stringToBeMatched);
+            Pattern p=Pattern.compile(stringToBeMatched);
+            Matcher m = p.matcher( input );
+            boolean matchFound=m.find();
+            log.debug("matchFound: {}", matchFound);
+            return FEELFnResult.ofResult(matchFound);
     }
 
+   static void checkFlags(String flags) {
+        Set<Character> allowedChars = Set.of('s','i','x','m');
+         boolean isValidFlag= flags.chars()
+                .mapToObj(c -> (char) c)
+                .allMatch(allowedChars::contains)
+                && flags.chars()
+                .mapToObj(c -> (char) c)
+                .collect(Collectors.toSet())
+                .size() == flags.length();
+         if(!isValidFlag){
+             throw new IllegalArgumentException("Not a valid flag parameter " 
+flags);
+         }
+    }
 }
diff --git 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/MatchesFunctionTest.java
 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/MatchesFunctionTest.java
index eeb86f511a..eea47b17de 100644
--- 
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/MatchesFunctionTest.java
+++ 
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/runtime/functions/MatchesFunctionTest.java
@@ -19,54 +19,116 @@
 package org.kie.dmn.feel.runtime.functions;
 
 import org.junit.jupiter.api.Test;
-import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;
+import org.mockito.MockedStatic;
 
-class MatchesFunctionTest {
+import java.security.InvalidParameterException;
+import java.util.regex.PatternSyntaxException;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.*;
 
-    private final static MatchesFunction matchesFunction = 
MatchesFunction.INSTANCE;
+class MatchesFunctionTest {
 
     @Test
     void invokeNull() {
-        FunctionTestUtil.assertResultError(matchesFunction.invoke((String) 
null, null), InvalidParametersEvent.class);
-        FunctionTestUtil.assertResultError(matchesFunction.invoke(null, 
"test"), InvalidParametersEvent.class);
-        FunctionTestUtil.assertResultError(matchesFunction.invoke("test", 
null), InvalidParametersEvent.class);
+        assertThrows(InvalidParameterException.class, () -> 
MatchesFunction.matchFunctionWithFlags(null, null, null));
+        assertThrows(InvalidParameterException.class, () -> 
MatchesFunction.matchFunctionWithFlags(null, "test",null));
+        assertThrows(InvalidParameterException.class, () -> 
MatchesFunction.matchFunctionWithFlags("test", null,null));
     }
 
     @Test
     void invokeUnsupportedFlags() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("foobar", 
"fo.bar", "g"), true);
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.matchFunctionWithFlags("foobar", "fo.bar", "g"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.matchFunctionWithFlags("abracadabra", "bra", "p"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.matchFunctionWithFlags("abracadabra", "bra", "X"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.matchFunctionWithFlags("abracadabra", "bra", " "));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.matchFunctionWithFlags("abracadabra", "bra", "iU"));
     }
 
     @Test
     void invokeWithoutFlagsMatch() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("test", "test"), 
true);
-        FunctionTestUtil.assertResult(matchesFunction.invoke("foobar", 
"^fo*b"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("test", 
"test",null), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("foobar", 
"^fo*b",null), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("abracadabra",
 "bra", ""), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("abracadabra",
 "bra",null), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("(?xi)[hello
 world()]", "hello",null), true);
     }
 
     @Test
     void invokeWithoutFlagsNotMatch() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("test", "testt"), 
false);
-        FunctionTestUtil.assertResult(matchesFunction.invoke("foobar", 
"^fo*bb"), false);
-        FunctionTestUtil.assertResult(matchesFunction.invoke("fo\nbar", 
"fo.bar"), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("test", 
"testt",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("foobar", 
"^fo*bb",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"fo.bar",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("h", 
"(.)\3",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("h", 
"(.)\2",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("input", 
"\3",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"(?iU)(?iU)(ab)[|cd]",null), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"(?x)(?i)hello world","i"), false);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"(?xi)hello world",null), false);
     }
 
     @Test
     void invokeWithFlagDotAll() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("fo\nbar", 
"fo.bar", "s"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"fo.bar", "s"), true);
     }
 
     @Test
     void invokeWithFlagMultiline() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("fo\nbar", 
"^bar", "m"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"^bar", "m"), true);
     }
 
     @Test
     void invokeWithFlagCaseInsensitive() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("foobar", 
"^Fo*bar", "i"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("foobar", 
"^Fo*bar", "i"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("foobar", 
"^Fo*bar", "i"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("\u212A", 
"k","i"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("\u212A", 
"K","i"), true);
+    }
+
+    @Test
+    void invokeWithFlagComments() {
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("hello 
world", "hello"+"\"+ sworld", "x"), false);
     }
 
     @Test
     void invokeWithAllFlags() {
-        FunctionTestUtil.assertResult(matchesFunction.invoke("fo\nbar", 
"Fo.^bar", "smi"), true);
+        
FunctionTestUtil.assertResult(MatchesFunction.matchFunctionWithFlags("fo\nbar", 
"Fo.^bar", "smi"), true);
+    }
+
+    @Test
+    void checkForPatternTest() {
+        assertThrows(PatternSyntaxException.class, () -> 
MatchesFunction.matchFunctionWithFlags("foobar",  "(abc|def(ghi", "i"));
+    }
+
+    @Test
+    void checkFlagsTest() {
+        assertDoesNotThrow(() -> MatchesFunction.checkFlags("s"));
+        assertDoesNotThrow(() -> MatchesFunction.checkFlags("i"));
+        assertDoesNotThrow(() -> MatchesFunction.checkFlags("sx"));
+        assertDoesNotThrow(() -> MatchesFunction.checkFlags("six"));
+        assertDoesNotThrow(() -> MatchesFunction.checkFlags("sixm"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("a"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("sa"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("siU@"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("siUxU"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("ss"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("siiU"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("si U"));
+        assertThrows(IllegalArgumentException.class, () -> 
MatchesFunction.checkFlags("U"));
     }
+
+    @Test
+    void checkMatchFunctionWithFlagsInvocation() {
+        MatchesFunction matchesFunctionSpied = spy(MatchesFunction.INSTANCE);
+        matchesFunctionSpied.invoke("input", "pattern");
+        verify(matchesFunctionSpied, times(1)).invoke("input", "pattern", 
null);
+        try (MockedStatic<MatchesFunction> matchesFunctionMocked = 
mockStatic(MatchesFunction.class)) {
+            matchesFunctionSpied.invoke("input", "pattern");
+            matchesFunctionMocked.verify(() -> 
MatchesFunction.matchFunctionWithFlags("input", "pattern", null));
+            matchesFunctionSpied.invoke("input", "pattern", "flags");
+            matchesFunctionMocked.verify(() -> 
MatchesFunction.matchFunctionWithFlags("input", "pattern", "flags"));
+        }
+    }
+
 }
\ No newline at end of file


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

Reply via email to