dawidwys closed pull request #6781: [FLINK-10470] Add method to check if
pattern can produce empty matches
URL: https://github.com/apache/flink/pull/6781
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/flink-libraries/flink-cep/src/main/java/org/apache/flink/cep/nfa/compiler/NFACompiler.java
b/flink-libraries/flink-cep/src/main/java/org/apache/flink/cep/nfa/compiler/NFACompiler.java
index 8f49f68fe41..ed2ff2e7e59 100644
---
a/flink-libraries/flink-cep/src/main/java/org/apache/flink/cep/nfa/compiler/NFACompiler.java
+++
b/flink-libraries/flink-cep/src/main/java/org/apache/flink/cep/nfa/compiler/NFACompiler.java
@@ -40,8 +40,13 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import static org.apache.flink.util.Preconditions.checkNotNull;
/**
* Compiler class containing methods to compile a {@link Pattern} into a
{@link NFA} or a
@@ -74,6 +79,44 @@
}
}
+ /**
+ * Verifies if the provided pattern can possibly generate empty match.
Example of patterns that can possibly
+ * generate empty matches are: A*, A?, A* B? etc.
+ *
+ * @param pattern pattern to check
+ * @return true if empty match could potentially match the pattern,
false otherwise
+ */
+ public static boolean canProduceEmptyMatches(final Pattern<?, ?>
pattern) {
+ NFAFactoryCompiler<?> compiler = new
NFAFactoryCompiler<>(checkNotNull(pattern));
+ compiler.compileFactory();
+ State<?> startState =
compiler.getStates().stream().filter(State::isStart).findFirst().orElseThrow(
+ () -> new IllegalStateException("Compiler produced no
start state. It is a bug. File a jira."));
+
+ Set<State<?>> visitedStates = new HashSet<>();
+ final Stack<State<?>> statesToCheck = new Stack<>();
+ statesToCheck.push(startState);
+ while (!statesToCheck.isEmpty()) {
+ final State<?> currentState = statesToCheck.pop();
+ if (visitedStates.contains(currentState)) {
+ continue;
+ } else {
+ visitedStates.add(currentState);
+ }
+
+ for (StateTransition<?> transition :
currentState.getStateTransitions()) {
+ if (transition.getAction() ==
StateTransitionAction.PROCEED) {
+ if
(transition.getTargetState().isFinal()) {
+ return true;
+ } else {
+
statesToCheck.push(transition.getTargetState());
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
/**
* Converts a {@link Pattern} into graph of {@link State}. It enables
sharing of
* compilation state across methods.
diff --git
a/flink-libraries/flink-cep/src/test/java/org/apache/flink/cep/nfa/compiler/NFACompilerTest.java
b/flink-libraries/flink-cep/src/test/java/org/apache/flink/cep/nfa/compiler/NFACompilerTest.java
index f39b17483cd..821da031c6d 100644
---
a/flink-libraries/flink-cep/src/test/java/org/apache/flink/cep/nfa/compiler/NFACompilerTest.java
+++
b/flink-libraries/flink-cep/src/test/java/org/apache/flink/cep/nfa/compiler/NFACompilerTest.java
@@ -44,7 +44,9 @@
import java.util.Set;
import static org.apache.flink.cep.utils.NFAUtils.compile;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
@@ -226,4 +228,14 @@ public boolean filter(Event value) throws Exception {
return transitions;
}
+ @Test
+ public void testCheckingEmptyMatches() {
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a").optional()),
is(true));
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a").oneOrMore().optional()),
is(true));
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a").oneOrMore().optional().next("b").optional()),
is(true));
+
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a")), is(false));
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a").oneOrMore()),
is(false));
+
assertThat(NFACompiler.canProduceEmptyMatches(Pattern.begin("a").oneOrMore().next("b").optional()),
is(false));
+ }
}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services