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]