You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@flink.apache.org by kl0u <gi...@git.apache.org> on 2017/06/01 11:56:09 UTC

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

GitHub user kl0u opened a pull request:

    https://github.com/apache/flink/pull/4041

    [FLINK-6198] [cep] Update CEP documentation.

    R @tzulitai @dawidwys 

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/kl0u/flink cep-doc

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/flink/pull/4041.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #4041
    
----
commit 2ce49dc722b72a31a178ee6a0763919597646ea6
Author: kkloudas <kk...@gmail.com>
Date:   2017-05-23T17:07:42Z

    [FLINK-6198] [cep] Update CEP documentation.

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119603232
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -23,22 +23,24 @@ specific language governing permissions and limitations
     under the License.
     -->
     
    -FlinkCEP is the complex event processing library for Flink.
    -It allows you to easily detect complex event patterns in a stream of endless data.
    -Complex events can then be constructed from matching sequences.
    -This gives you the opportunity to quickly get hold of what's really important in your data.
    +FlinkCEP is the Complex Event Processing (CEP) library implemented on top of Flink.
    +It allows you to easily detect event patterns in an endless stream of events, thus
    +giving you the opportunity to quickly get hold of what's really important in your 
    +data.
     
    -<span class="label label-danger">Attention</span> The events in the `DataStream` to which
    -you want to apply pattern matching have to implement proper `equals()` and `hashCode()` methods
    -because these are used for comparing and matching events.
    +This page described the API calls available in Flink CEP. We start by presenting the [Pattern API](#the-pattern-api), 
    --- End diff --
    
    This page described -> This page describes


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119602446
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -65,21 +67,49 @@ Next, you have to add the FlinkCEP dependency to the `pom.xml` of your project.
     Note that FlinkCEP is currently not part of the binary distribution.
     See linking with it for cluster execution [here]({{site.baseurl}}/dev/linking.html).
     
    -Now you can start writing your first CEP program using the pattern API.
    +Now you can start writing your first CEP program using the Pattern API.
    +
    +<span class="label label-danger">Attention</span> The events in the `DataStream` to which
    +you want to apply pattern matching have to implement proper `equals()` and `hashCode()` methods
    +because these are used for comparing and matching events.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
     DataStream<Event> input = ...
     
    -Pattern<Event, ?> pattern = Pattern.begin("start").where(evt -> evt.getId() == 42)
    -    .next("middle").subtype(SubEvent.class).where(subEvt -> subEvt.getVolume() >= 10.0)
    -    .followedBy("end").where(evt -> evt.getName().equals("end"));
    +Pattern<Event, ?> pattern = Pattern.begin("start").where(
    +        new SimpleCondition<Event>() {
    +            @Override
    +            public boolean filter(Event event) {
    +                return evt.getId() == 42;
    --- End diff --
    
    `evt` --> `event`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119609218
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -215,12 +303,11 @@ start.subtype(classOf[SubEvent]).where(subEvent => ... /* some condition */)
     </div>
     </div>
     
    -As it can be seen here, the subtype condition can also be combined with an additional filter condition on the subtype.
    -In fact, you can always provide multiple conditions by calling `where` and `subtype` multiple times.
    -These conditions will then be combined using the logical AND operator.
    +**Combining Conditions:** As shown, the `subtype` condition can be combined with additional conditions. 
    +In fact, this holds for every condition. You can arbitrarily combine multiple conditions by sequentially calling 
    +`where()`. The final result will be the logical **AND** of the results of the individual conditions.
     
    -In order to construct or conditions, one has to call the `or` method with a respective filter function.
    -Any existing filter function is then ORed with the given one.
    +In order to combine conditions using *OR*, you can call the `or` method, as shown below.
    --- End diff --
    
    bold the OR (*OR* -> **OR**)
    `or` -> `or()`



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119596846
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -874,3 +1141,19 @@ val alerts = patternStream.select(createAlert(_)))
     {% endhighlight %}
     </div>
     </div>
    +
    +## Migrating from an older Flink version
    +
    +The CEP library in Flink-1.3 ships with a number of new features which have led to some changes in the API. Here we 
    +describe the changes that you need to make to your old CEP jobs, in order to be able to run them with Flink-1.3. After 
    +making these changes and recompiling your job, you will be able to resume its execution from a savepoint taken with the 
    +old version of your job, *i.e.* without having to re-process your past data.
    +
    +The changes required are:
    +
    +1. Change your conditions (the ones in the `where(...)` clause) to extend the `SimpleCondition` class instead of 
    +implementing the `FilterFunction` interface.
    +
    +2. Change your functions provided as arguments to the `select(...)` and `flatSelect(...)` methods to expect a list of
    +events associated with each state (`List` in `Java`, `Iterable` in `Scala`). This is because with the addition of
    +the looping states, multiple input events can much a single (looping) state.
    --- End diff --
    
    hehe good "cats" (catch) :P


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    Thanks a lot @dawidwys for having a detailed look at it! I will integrate your comments and then merge.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119879015
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -168,33 +256,34 @@ start.where(
     </div>
     </div>
     
    -<span class="label label-danger">Attention</span> The call to `Context.getEventsForPattern(...)` has to find the 
    -elements that belong to the pattern. The cost of this operation can vary, so when implementing your condition, try 
    -to minimize the times the method is called.
    +<span class="label label-danger">Attention</span> The call to `context.getEventsForPattern(...)` finds all the 
    +previously accepted events for a given potential match. The cost of this operation can vary, so when implementing 
    +your condition, try to minimize the times the method is called.
     
    -**Simple Conditions:** This type of conditions extend the aforementioned `IterativeCondition` class. They are simple 
    -filtering conditions that decide to accept an element or not, based only on properties of the element itself.
    +**Simple Conditions:** This type of conditions extend the aforementioned `IterativeCondition` class and decides 
    --- End diff --
    
    ... This type of condition extends the aforementioned `IterativeCondition` class and decides whether ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by rmetzger <gi...@git.apache.org>.
Github user rmetzger commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    Cool, thx



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119610954
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
    --- End diff --
    
    I would make it a higher level section and changed Conditions on Contiguity -> Contiguity.
    
    Also I think this is the place where inner contiguity for looping states should be described.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119607288
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +Contiguity conditions should be specified both within individual (looping) states but also 
    +across states. For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
    +
    +### Combining States
    +
    +Now that we have seen how an individual state can look, it is time to see how to combine them into a full pattern sequence.
    +
    +A pattern sequence has to start with an initial state, as shown below:
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedBy("middle");
    +Pattern<Event, ?> start = Pattern.<Event>begin("start");
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedBy("middle")
    +val start : Pattern[Event, _] = Pattern.begin("start")
     {% endhighlight %}
     </div>
     </div>
     
    -For non-strict contiguity one can specify if only the first succeeding matching event will be matched, or
    -all. In the latter case multiple matches will be emitted for the same beginning.
    +Next, you can append more states to your pattern by specifying the desired *contiguity conditions* between them. 
    +This can be done using: 
    +
    +1. `next()`, for *strict*, 
    +2. `followedBy()`, for *relaxed*, and 
    +3. `followedByAny()`, for *non-deterministic relaxed* contiguity.
    +
    +or 
    +
    +1. `notNext()`, if you do not want an event type to directly follow another
    +2. `notFollowedBy()`, if you do not want an event type to be anywhere between two other event types
    +
    +
    +<span class="label label-danger">Attention</span> A pattern sequence cannot end in `notFollowedBy()`.
    +
    +<span class="label label-danger">Attention</span> A `NOT` state cannot be preceded by an optional one.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedByAny("middle");
    +
    +// strict contiguity
    +Pattern<Event, ?> strict = start.next("middle").where(...);
    +
    +// relaxed contiguity
    +Pattern<Event, ?> relaxed = start.followedBy("middle").where(...);
    +
    +// non-deterministic relaxed contiguity
    +Pattern<Event, ?> nonDetermin = start.followedByAny("middle").where(...);
    +
    +// NOT pattern with strict contiguity
    +Pattern<Event, ?> strictNot = start.notNext("not").where(...);
    +
    +// NOT pattern with relaxed contiguity
    +Pattern<Event, ?> relaxedNot = start.notFollowedBy("not").where(...);
    +
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedByAny("middle")
    +
    +// strict contiguity
    +val strict: Pattern[Event, _] = start.next("middle").where(...)
    +
    +// relaxed contiguity
    +val relaxed: Pattern[Event, _] = start.followedBy("middle").where(...)
    +
    +// non-deterministic relaxed contiguity
    +val nonDetermin: Pattern[Event, _] = start.followedByAny("middle").where(...)
    +
    +// NOT pattern with strict contiguity
    +val strictNot: Pattern[Event, _] = start.notNext("not").where(...)
    +
    +// NOT pattern with relaxed contiguity
    +val relaxedNot: Pattern[Event, _] = start.notFollowedBy("not").where(...)
    +
     {% endhighlight %}
     </div>
    -
     </div>
    -It is also possible to define a temporal constraint for the pattern to be valid.
    -For example, one can define that a pattern should occur within 10 seconds via the `within` method. 
    +
    +Bear in mind that relaxed contiguity means that only the first succeeding matching event will be matched, while
    +non-deterministic relaxed contiguity, multiple matches will be emitted for the same beginning.
    +
    +Finally, it is also possible to define a temporal constraint for the pattern to be valid.
    +For example, you can define that a pattern should occur within 10 seconds via the `pattern.within()` method. 
     Temporal patterns are supported for both [processing and event time]({{site.baseurl}}/dev/event_time.html).
     
     <div class="codetabs" markdown="1">
    --- End diff --
    
    I wonder if it makes sense to break up this table into 2 parts, one placed under the "Individual States" section, and "Combining States" section, to make it clearer which API calls are for describing the construction of an individual state and which ones are for combining different states.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119604721
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    + non-matching events between any matching ones.
    + 
    +The latter refers to "looping" states, i.e. states that can accept more than one event, e.g. the `b+` in `a b+ c`, 
    +which searches for one or more `b`'s.
    +
    +##### Conditions on Properties
    --- End diff --
    
    I found this title to be very "hidden" in the content, in that its subsection titles "Iterative Conditions" and "Simple Conditions" where actually more prominent.
    
    Not really sure if this can be addressed though, just pointing out an observation on the built docs.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119852417
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    + non-matching events between any matching ones.
    + 
    +The latter refers to "looping" states, i.e. states that can accept more than one event, e.g. the `b+` in `a b+ c`, 
    +which searches for one or more `b`'s.
    +
    +##### Conditions on Properties
    +
    +Conditions on the event properties can be specified via the `pattern.where()` method. These can be either 
    +`IterativeCondition`s or `SimpleCondition`s.
    +
    +**Iterative Conditions:** This is the most general type of conditions. This allows to specify a condition that accepts 
    +any subsequent event based on some statistic over a subset of the previously accepted events. 
    --- End diff --
    
    This is the most general type of condition. This is how you can specify a condition that accepts subsequent events based on some statistic over a subset of the previously accepted events.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r120362519
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    --- End diff --
    
    I changed it, so now we have `Pattern` and `Pattern Sequence`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119878726
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -168,33 +256,34 @@ start.where(
     </div>
     </div>
     
    -<span class="label label-danger">Attention</span> The call to `Context.getEventsForPattern(...)` has to find the 
    -elements that belong to the pattern. The cost of this operation can vary, so when implementing your condition, try 
    -to minimize the times the method is called.
    +<span class="label label-danger">Attention</span> The call to `context.getEventsForPattern(...)` finds all the 
    +previously accepted events for a given potential match. The cost of this operation can vary, so when implementing 
    +your condition, try to minimize the times the method is called.
    --- End diff --
    
    ... try to minimize its use.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119602408
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -65,21 +67,49 @@ Next, you have to add the FlinkCEP dependency to the `pom.xml` of your project.
     Note that FlinkCEP is currently not part of the binary distribution.
     See linking with it for cluster execution [here]({{site.baseurl}}/dev/linking.html).
     
    -Now you can start writing your first CEP program using the pattern API.
    +Now you can start writing your first CEP program using the Pattern API.
    +
    +<span class="label label-danger">Attention</span> The events in the `DataStream` to which
    +you want to apply pattern matching have to implement proper `equals()` and `hashCode()` methods
    +because these are used for comparing and matching events.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
     DataStream<Event> input = ...
     
    -Pattern<Event, ?> pattern = Pattern.begin("start").where(evt -> evt.getId() == 42)
    -    .next("middle").subtype(SubEvent.class).where(subEvt -> subEvt.getVolume() >= 10.0)
    -    .followedBy("end").where(evt -> evt.getName().equals("end"));
    +Pattern<Event, ?> pattern = Pattern.begin("start").where(
    --- End diff --
    
    I think Pattern."<Event>" is required?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119883183
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,106 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    -
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> start = Pattern.<Event>begin("start");
    -{% endhighlight %}
    -</div>
    -
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val start : Pattern[Event, _] = Pattern.begin("start")
    -{% endhighlight %}
    -</div>
    -</div>
    -
    -Each state must have a unique name to identify the matched events later on.
    -Additionally, we can specify a filter condition for the event to be accepted as the start event via the `where` method.
    -These filtering conditions can be either an `IterativeCondition` or a `SimpleCondition`. 
    -
    -**Iterative Conditions:** This type of conditions can iterate over the previously accepted elements in the pattern and 
    -decide to accept a new element or not, based on some statistic over those elements. 
    -
    -Below is the code for an iterative condition that accepts elements whose name start with "foo" and for which, the sum 
    -of the prices of the previously accepted elements for a state named "middle", plus the price of the current event, do 
    -not exceed the value of 5.0. Iterative condition can be very powerful, especially in combination with quantifiers, e.g.
    -`oneToMany` or `zeroToMany`.
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    --- End diff --
    
    ... where transitions from one state to the next occur ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by asfgit <gi...@git.apache.org>.
Github user asfgit closed the pull request at:

    https://github.com/apache/flink/pull/4041


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119890353
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +}).or(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // alternative condition
    +    }
    +});
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
     {% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    +patternState.subtype(SubEvent.class);
     {% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +              <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +      {% highlight java %}
    +      patternState.oneOrMore();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>times(#ofTimes)</strong></td>
    +          <td>
    +              <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +{% highlight java %}
    +patternState.times(2);
    +{% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +              <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +              aforementioned quantifiers.</p>
    +      {% highlight java %}
    +      patternState.oneOrMore().optional();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_java"></a></td>
    +          <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +              events, i.e. any non-matching element breaks the match (as in next()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().consecutive()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +              <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +            
    +              <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +              <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +       <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +       <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +              between the matching events (as in followedByAny()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                   
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().allowCombinations()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +               <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +               
    +               <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +               <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +       </td>
    +       </tr>
    +  </tbody>
    +</table>
     </div>
     
     <div data-lang="scala" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +      
    +        <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +              <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +              it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    --- End diff --
    
    ... can it match the state.
    
    Or turn the sentence around to be more direct:
    
    An event matches the state only if it satisfies the condition.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119888143
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -341,153 +765,67 @@ Pattern<Event, ?> start = Pattern.<Event>begin("start");
                 </td>
             </tr>
             <tr>
    -            <td><strong>Next</strong></td>
    +            <td><strong>next()</strong></td>
                 <td>
    -                <p>Appends a new pattern state. A matching event has to directly succeed the previous matching event:</p>
    +                <p>Appends a new pattern state. A matching event has to directly succeed the previous matching event 
    +                (strict contiguity):</p>
     {% highlight java %}
    -Pattern<Event, ?> next = start.next("next");
    +Pattern<Event, ?> next = start.next("middle");
     {% endhighlight %}
                 </td>
             </tr>
             <tr>
    -            <td><strong>FollowedBy</strong></td>
    +            <td><strong>followedBy()</strong></td>
                 <td>
    -                <p>Appends a new pattern state. Other events can occur between a matching event and the previous matching event:</p>
    +                <p>Appends a new pattern state. Other events can occur between a matching event and the previous 
    +                matching event (relaxed contiguity):</p>
     {% highlight java %}
    -Pattern<Event, ?> followedBy = start.followedBy("next");
    +Pattern<Event, ?> followedBy = start.followedBy("middle");
     {% endhighlight %}
                 </td>
             </tr>
             <tr>
    -            <td><strong>Where</strong></td>
    +            <td><strong>followedByAny()</strong></td>
                 <td>
    -                <p>Defines a condition for the current pattern state. Only if an event satisifes the condition, it can match the state:</p>
    +                <p>Appends a new pattern state. Other events can occur between a matching event and the previous 
    +                matching event and alternative matches will be presented for every alternative matching event 
    --- End diff --
    
    add a comma:
    
    ... matching event, and alternative matches ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119613118
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    --- End diff --
    
    First I would start with example without looping state, as we silently introduce the internal continuity.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119605089
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    --- End diff --
    
    visit -> visits


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119889674
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +}).or(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // alternative condition
    +    }
    +});
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
     {% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    +patternState.subtype(SubEvent.class);
     {% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +              <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +      {% highlight java %}
    +      patternState.oneOrMore();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>times(#ofTimes)</strong></td>
    +          <td>
    +              <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +{% highlight java %}
    +patternState.times(2);
    +{% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +              <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +              aforementioned quantifiers.</p>
    +      {% highlight java %}
    +      patternState.oneOrMore().optional();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_java"></a></td>
    +          <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +              events, i.e. any non-matching element breaks the match (as in next()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().consecutive()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +              <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +            
    +              <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +              <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +       <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +       <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +              between the matching events (as in followedByAny()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                   
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().allowCombinations()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +               <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +               
    +               <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +               <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +       </td>
    +       </tr>
    +  </tbody>
    +</table>
     </div>
     
     <div data-lang="scala" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +      
    +        <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +              <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +              it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +              ANDed:</p>
     {% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    +patternState.where(event => ... /* some condition */)
     {% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight scala %}
    +patternState.where(event => ... /* some condition */)
    +    .or(event => ... /* alternative condition */)
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
    --- End diff --
    
    You meant to say "Only if an event is of this subtype, can it match the state:", but I recommend
    
    ... An event can only match the state if it is of this subtype:


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119607252
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    --- End diff --
    
    I would move this to the combining patterns section. It is easier to reason about after understanding the contiguity between single patterns/states.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119889986
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +}).or(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // alternative condition
    +    }
    +});
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
     {% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    +patternState.subtype(SubEvent.class);
     {% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +              <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +      {% highlight java %}
    +      patternState.oneOrMore();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>times(#ofTimes)</strong></td>
    +          <td>
    +              <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +{% highlight java %}
    +patternState.times(2);
    +{% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +              <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +              aforementioned quantifiers.</p>
    +      {% highlight java %}
    +      patternState.oneOrMore().optional();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_java"></a></td>
    +          <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +              events, i.e. any non-matching element breaks the match (as in next()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().consecutive()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +              <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +            
    +              <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +              <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +       <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +       <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +              between the matching events (as in followedByAny()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                   
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().allowCombinations()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +               <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +               
    +               <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +               <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +       </td>
    +       </tr>
    +  </tbody>
    +</table>
     </div>
     
     <div data-lang="scala" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +      
    +        <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +              <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +              it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +              ANDed:</p>
     {% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    +patternState.where(event => ... /* some condition */)
     {% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    --- End diff --
    
    An event can only match the state if it passes one of the conditions:



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    In fact I managed to finish the review. Generally the docs look great! Congrats on the hard work @kl0u! 
    
    @rmetzger Most of the comments I had were to the formatting/reordering, the only bigger concern is the naming of the State. All in all I think it can be merged today. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by rmetzger <gi...@git.apache.org>.
Github user rmetzger commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    I'll update the release announcement blog post, once the CEP doc has been updated


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119853002
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,106 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    -
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> start = Pattern.<Event>begin("start");
    -{% endhighlight %}
    -</div>
    -
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val start : Pattern[Event, _] = Pattern.begin("start")
    -{% endhighlight %}
    -</div>
    -</div>
    -
    -Each state must have a unique name to identify the matched events later on.
    -Additionally, we can specify a filter condition for the event to be accepted as the start event via the `where` method.
    -These filtering conditions can be either an `IterativeCondition` or a `SimpleCondition`. 
    -
    -**Iterative Conditions:** This type of conditions can iterate over the previously accepted elements in the pattern and 
    -decide to accept a new element or not, based on some statistic over those elements. 
    -
    -Below is the code for an iterative condition that accepts elements whose name start with "foo" and for which, the sum 
    -of the prices of the previously accepted elements for a state named "middle", plus the price of the current event, do 
    -not exceed the value of 5.0. Iterative condition can be very powerful, especially in combination with quantifiers, e.g.
    -`oneToMany` or `zeroToMany`.
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single 
    +event, while looping ones can accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one. By default, a state is a singleton state and you can transform 
    +it to a looping one using [Quantifiers](#quantifiers). In addition, each state can have one or more 
    +[Conditions](#conditions) based on which it accepts events.
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    + non-matching events between any matching ones.
    + 
    +The latter refers to "looping" states, i.e. states that can accept more than one event, e.g. the `b+` in `a b+ c`, 
    +which searches for one or more `b`'s.
    +
    +##### Conditions on Properties
    +
    +Conditions on the event properties can be specified via the `pattern.where()` method. These can be either 
    +`IterativeCondition`s or `SimpleCondition`s.
    +
    +**Iterative Conditions:** This is the most general type of conditions. This allows to specify a condition that accepts 
    +any subsequent event based on some statistic over a subset of the previously accepted events. 
    +
    +Below is the code for an iterative condition that accepts the next event for a state named "middle" if its name starts 
    +with "foo" and the sum of the prices of the previously accepted events for that state plus the price of the current 
    +event, do not exceed the value of 5.0. Iterative conditions can be very powerful, especially in combination with looping 
    --- End diff --
    
    The comma doesn't work where it is. I suggest
    
    Below is the code for an iterative condition that accepts the next event for a state named "middle" if its name starts with "foo", and if the sum of the prices of the previously accepted events for that state plus the price of the current event do not exceed the value of 5.0.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119890712
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    --- End diff --
    
    An event can match the state only if it passes at least one of the conditions.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119602073
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -23,22 +23,24 @@ specific language governing permissions and limitations
     under the License.
     -->
     
    -FlinkCEP is the complex event processing library for Flink.
    -It allows you to easily detect complex event patterns in a stream of endless data.
    -Complex events can then be constructed from matching sequences.
    -This gives you the opportunity to quickly get hold of what's really important in your data.
    +FlinkCEP is the Complex Event Processing (CEP) library implemented on top of Flink.
    +It allows you to easily detect event patterns in an endless stream of events, thus
    +giving you the opportunity to quickly get hold of what's really important in your 
    +data.
     
    -<span class="label label-danger">Attention</span> The events in the `DataStream` to which
    -you want to apply pattern matching have to implement proper `equals()` and `hashCode()` methods
    -because these are used for comparing and matching events.
    +This page described the API calls available in Flink CEP. We start by presenting the [Pattern API](#the-pattern-api), 
    --- End diff --
    
    "described" --> "describes"


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r120303532
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    --- End diff --
    
    I agree. The problem is that then we have many back-and-forths. I will try to somehow integrate this comments (probably with a forward reference like "more on contiguity ...").


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119595945
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -874,3 +1141,19 @@ val alerts = patternStream.select(createAlert(_)))
     {% endhighlight %}
     </div>
     </div>
    +
    +## Migrating from an older Flink version
    +
    +The CEP library in Flink-1.3 ships with a number of new features which have led to some changes in the API. Here we 
    +describe the changes that you need to make to your old CEP jobs, in order to be able to run them with Flink-1.3. After 
    +making these changes and recompiling your job, you will be able to resume its execution from a savepoint taken with the 
    +old version of your job, *i.e.* without having to re-process your past data.
    +
    +The changes required are:
    +
    +1. Change your conditions (the ones in the `where(...)` clause) to extend the `SimpleCondition` class instead of 
    +implementing the `FilterFunction` interface.
    +
    +2. Change your functions provided as arguments to the `select(...)` and `flatSelect(...)` methods to expect a list of
    +events associated with each state (`List` in `Java`, `Iterable` in `Scala`). This is because with the addition of
    +the looping states, multiple input events can much a single (looping) state.
    --- End diff --
    
    much -> match


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119607780
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    + non-matching events between any matching ones.
    + 
    +The latter refers to "looping" states, i.e. states that can accept more than one event, e.g. the `b+` in `a b+ c`, 
    +which searches for one or more `b`'s.
    +
    +##### Conditions on Properties
    +
    +Conditions on the event properties can be specified via the `pattern.where()` method. These can be either 
    --- End diff --
    
    Conditions on the event properties can be specified via the `pattern.where()` **and `pattern.or()`** method


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    Thanks a lot for the thorough review @tzulitai ! I will address your comments and then merge.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119888807
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +}).or(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // alternative condition
    +    }
    +});
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
     {% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    +patternState.subtype(SubEvent.class);
     {% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +              <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +      {% highlight java %}
    +      patternState.oneOrMore();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>times(#ofTimes)</strong></td>
    +          <td>
    +              <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +{% highlight java %}
    +patternState.times(2);
    +{% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +              <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +              aforementioned quantifiers.</p>
    +      {% highlight java %}
    +      patternState.oneOrMore().optional();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_java"></a></td>
    +          <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +              events, i.e. any non-matching element breaks the match (as in next()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().consecutive()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +              <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +            
    +              <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +              <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +       <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +       <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +              between the matching events (as in followedByAny()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                   
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().allowCombinations()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +               <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +               
    +               <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +               <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +       </td>
    +       </tr>
    +  </tbody>
    +</table>
     </div>
     
     <div data-lang="scala" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +      
    +        <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +              <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +              it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +              ANDed:</p>
     {% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    +patternState.where(event => ... /* some condition */)
     {% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight scala %}
    +patternState.where(event => ... /* some condition */)
    +    .or(event => ... /* alternative condition */)
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
    +{% highlight scala %}
    +patternState.subtype(classOf[SubEvent])
    +{% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +               <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +                            <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +                            internal contiguity see <a href="#consecutive_scala">consecutive</a></p>
    +      {% highlight scala %}
    +      patternState.oneOrMore()
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +                 <td><strong>times(#ofTimes)</strong></td>
    +                 <td>
    +                     <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +                                   <p>By default a relaxed internal contiguity (between subsequent events) is used. 
    +                                   For more info on the internal contiguity see <a href="#consecutive_scala">consecutive</a></p>
    +             {% highlight scala %}
    +             patternState.times(2)
    +             {% endhighlight %}
    +                 </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +             <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +                           aforementioned quantifiers.</p>
    +      {% highlight scala %}
    +      patternState.oneOrMore().optional()
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_scala"></a></td>
    +          <td>
    +            <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +                          events, i.e. any non-matching element breaks the match (as in next()).</p>
    +                          <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +      <p>E.g. a pattern like:</p> 
    +      {% highlight scala %}
    +      Pattern.begin("start").where(_.getName().equals("c"))
    +       .followedBy("middle").where(_.getName().equals("a"))
    +                            .oneOrMore().consecutive()
    +       .followedBy("end1").where(_.getName().equals("b"));
    +      {% endhighlight %}
    +
    +            <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +                        
    +                          <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +                          <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +              <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +              <td>
    +                <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +                     between the matching events (as in followedByAny()).</p>
    +                     <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                          
    +      <p>E.g. a pattern like:</p>
    +      {% highlight scala %}
    +      Pattern.begin("start").where(_.getName().equals("c"))
    +       .followedBy("middle").where(_.getName().equals("a"))
    +                            .oneOrMore().allowCombinations()
    +       .followedBy("end1").where(_.getName().equals("b"));
    +      {% endhighlight %}
    +                     
    +                      <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +                          
    +                      <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +                      <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +              </td>
    +              </tr>
    +  </tbody>
    +</table>
     </div>
    +
     </div>
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +### Combining States
    +
    +Now that we have seen how an individual state can look, it is time to see how to combine them into a full pattern sequence.
    --- End diff --
    
    Now that we have seen what an individual state can look like, ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119604886
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    --- End diff --
    
    I am aware of the difficulty of naming a single pattern but I am not sure if naming it state is good idea, as internally we use State for something different.
    
    Do you think the distinction: pattern <-> pattern sequence is not enough?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119888607
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +                ANDed:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +});
    +{% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight java %}
    +patternState.where(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // some condition
    +    }
    +}).or(new IterativeCondition<Event>() {
    +    @Override
    +    public boolean filter(Event value, Context ctx) throws Exception {
    +        return ... // alternative condition
    +    }
    +});
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
     {% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    +patternState.subtype(SubEvent.class);
     {% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +              <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +      {% highlight java %}
    +      patternState.oneOrMore();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>times(#ofTimes)</strong></td>
    +          <td>
    +              <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +              <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +              internal contiguity see <a href="#consecutive_java">consecutive</a></p>
    +{% highlight java %}
    +patternState.times(2);
    +{% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +              <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +              aforementioned quantifiers.</p>
    +      {% highlight java %}
    +      patternState.oneOrMore().optional();
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_java"></a></td>
    +          <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +              events, i.e. any non-matching element breaks the match (as in next()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().consecutive()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +              <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +            
    +              <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +              <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +       <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +       <td>
    +              <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +              between the matching events (as in followedByAny()).</p>
    +              <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                   
    +              <p>E.g. a pattern like:</p>
    +              {% highlight java %}
    +              Pattern.<Event>begin("start").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("c");
    +                }
    +              })
    +              .followedBy("middle").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("a");
    +                }
    +              }).oneOrMore().allowCombinations()
    +              .followedBy("end1").where(new SimpleCondition<Event>() {
    +                @Override
    +                public boolean filter(Event value) throws Exception {
    +                  return value.getName().equals("b");
    +                }
    +              });
    +              {% endhighlight %}
    +               <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +               
    +               <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +               <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +       </td>
    +       </tr>
    +  </tbody>
    +</table>
     </div>
     
     <div data-lang="scala" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +      
    +        <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +              <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +              it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    +              ANDed:</p>
     {% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    +patternState.where(event => ... /* some condition */)
     {% endhighlight %}
    +            </td>
    +        </tr>
    +        <tr>
    +            <td><strong>or(condition)</strong></td>
    +            <td>
    +                <p>Adds a new condition which is ORed with an existing one. Only if an event passes one of the 
    +                conditions, it can match the state:</p>
    +{% highlight scala %}
    +patternState.where(event => ... /* some condition */)
    +    .or(event => ... /* alternative condition */)
    +{% endhighlight %}
    +                    </td>
    +                </tr>
    +       <tr>
    +           <td><strong>subtype(subClass)</strong></td>
    +           <td>
    +               <p>Defines a subtype condition for the current pattern state. Only if an event is of this subtype, 
    +               it can match the state:</p>
    +{% highlight scala %}
    +patternState.subtype(classOf[SubEvent])
    +{% endhighlight %}
    +           </td>
    +       </tr>
    +       <tr>
    +          <td><strong>oneOrMore()</strong></td>
    +          <td>
    +               <p>Specifies that this state expects at least one occurrence of a matching event.</p>
    +                            <p>By default a relaxed internal contiguity (between subsequent events) is used. For more info on the 
    +                            internal contiguity see <a href="#consecutive_scala">consecutive</a></p>
    +      {% highlight scala %}
    +      patternState.oneOrMore()
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +                 <td><strong>times(#ofTimes)</strong></td>
    +                 <td>
    +                     <p>Specifies that this state expects an exact number of occurrences of a matching event.</p>
    +                                   <p>By default a relaxed internal contiguity (between subsequent events) is used. 
    +                                   For more info on the internal contiguity see <a href="#consecutive_scala">consecutive</a></p>
    +             {% highlight scala %}
    +             patternState.times(2)
    +             {% endhighlight %}
    +                 </td>
    +       </tr>
    +       <tr>
    +          <td><strong>optional()</strong></td>
    +          <td>
    +             <p>Specifies that this pattern is optional, i.e. it may not occur at all. This is applicable to all 
    +                           aforementioned quantifiers.</p>
    +      {% highlight scala %}
    +      patternState.oneOrMore().optional()
    +      {% endhighlight %}
    +          </td>
    +       </tr>
    +       <tr>
    +          <td><strong>consecutive()</strong><a name="consecutive_scala"></a></td>
    +          <td>
    +            <p>Works in conjunction with oneOrMore() and times() and imposes strict contiguity between the matching 
    +                          events, i.e. any non-matching element breaks the match (as in next()).</p>
    +                          <p>If not applied a relaxed contiguity (as in followedBy()) is used.</p>
    +            
    +      <p>E.g. a pattern like:</p> 
    +      {% highlight scala %}
    +      Pattern.begin("start").where(_.getName().equals("c"))
    +       .followedBy("middle").where(_.getName().equals("a"))
    +                            .oneOrMore().consecutive()
    +       .followedBy("end1").where(_.getName().equals("b"));
    +      {% endhighlight %}
    +
    +            <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +                        
    +                          <p>with consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}</p>
    +                          <p>without consecutive applied: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +          </td>
    +       </tr>
    +       <tr>
    +              <td><strong>allowCombinations()</strong><a name="allow_comb_java"></a></td>
    +              <td>
    +                <p>Works in conjunction with oneOrMore() and times() and imposes non-deterministic relaxed contiguity 
    +                     between the matching events (as in followedByAny()).</p>
    +                     <p>If not applied a relaxed contiguity (as in followedBy) is used.</p>
    +                          
    +      <p>E.g. a pattern like:</p>
    +      {% highlight scala %}
    +      Pattern.begin("start").where(_.getName().equals("c"))
    +       .followedBy("middle").where(_.getName().equals("a"))
    +                            .oneOrMore().allowCombinations()
    +       .followedBy("end1").where(_.getName().equals("b"));
    +      {% endhighlight %}
    +                     
    +                      <p>Will generate the following matches for an input sequence: C D A1 A2 A3 D A4 B</p>
    +                          
    +                      <p>with combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A3 B}, {C A1 A4 B}, {C A1 A2 A3 B}, {C A1 A2 A4 B}, {C A1 A3 A4 B}, {C A1 A2 A3 A4 B}</p>
    +                      <p>without combinations enabled: {C A1 B}, {C A1 A2 B}, {C A1 A2 A3 B}, {C A1 A2 A3 A4 B}</p>
    +              </td>
    +              </tr>
    +  </tbody>
    +</table>
     </div>
    +
     </div>
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +### Combining States
    +
    +Now that we have seen how an individual state can look, it is time to see how to combine them into a full pattern sequence.
    +
    +A pattern sequence has to start with an initial state, as shown below:
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedBy("middle");
    +Pattern<Event, ?> start = Pattern.<Event>begin("start");
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedBy("middle")
    +val start : Pattern[Event, _] = Pattern.begin("start")
     {% endhighlight %}
     </div>
     </div>
     
    -For non-strict contiguity one can specify if only the first succeeding matching event will be matched, or
    -all. In the latter case multiple matches will be emitted for the same beginning.
    +Next, you can append more states to your pattern by specifying the desired *contiguity conditions* between them. 
    +This can be done using: 
    +
    +1. `next()`, for *strict*, 
    +2. `followedBy()`, for *relaxed*, and 
    +3. `followedByAny()`, for *non-deterministic relaxed* contiguity.
    +
    +or 
    +
    +1. `notNext()`, if you do not want an event type to directly follow another
    +2. `notFollowedBy()`, if you do not want an event type to be anywhere between two other event types
    +
    +
    +<span class="label label-danger">Attention</span> A pattern sequence cannot end in `notFollowedBy()`.
    +
    +<span class="label label-danger">Attention</span> A `NOT` state cannot be preceded by an optional one.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedByAny("middle");
    +
    +// strict contiguity
    +Pattern<Event, ?> strict = start.next("middle").where(...);
    +
    +// relaxed contiguity
    +Pattern<Event, ?> relaxed = start.followedBy("middle").where(...);
    +
    +// non-deterministic relaxed contiguity
    +Pattern<Event, ?> nonDetermin = start.followedByAny("middle").where(...);
    +
    +// NOT pattern with strict contiguity
    +Pattern<Event, ?> strictNot = start.notNext("not").where(...);
    +
    +// NOT pattern with relaxed contiguity
    +Pattern<Event, ?> relaxedNot = start.notFollowedBy("not").where(...);
    +
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedByAny("middle")
    +
    +// strict contiguity
    +val strict: Pattern[Event, _] = start.next("middle").where(...)
    +
    +// relaxed contiguity
    +val relaxed: Pattern[Event, _] = start.followedBy("middle").where(...)
    +
    +// non-deterministic relaxed contiguity
    +val nonDetermin: Pattern[Event, _] = start.followedByAny("middle").where(...)
    +
    +// NOT pattern with strict contiguity
    +val strictNot: Pattern[Event, _] = start.notNext("not").where(...)
    +
    +// NOT pattern with relaxed contiguity
    +val relaxedNot: Pattern[Event, _] = start.notFollowedBy("not").where(...)
    +
     {% endhighlight %}
     </div>
    -
     </div>
    -It is also possible to define a temporal constraint for the pattern to be valid.
    -For example, one can define that a pattern should occur within 10 seconds via the `within` method. 
    +
    +Bear in mind that relaxed contiguity means that only the first succeeding matching event will be matched, while
    +non-deterministic relaxed contiguity, multiple matches will be emitted for the same beginning.
    --- End diff --
    
    ... will be matched, while with non-deterministic ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119618715
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    --- End diff --
    
    The sentence starting with "In pattern matchin" was hard to understand for me.
    
    How about?:
    In regex style symbols, in the pattern:
     > `a b+ c? d`
       
    or in more FLinkCEP style:
     > ( `a`, followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`),
      
    `a`, `c?`, and `d` are singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)).


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r120403427
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -1155,5 +1199,9 @@ The changes required are:
     implementing the `FilterFunction` interface.
     
     2. Change your functions provided as arguments to the `select(...)` and `flatSelect(...)` methods to expect a list of
    -events associated with each state (`List` in `Java`, `Iterable` in `Scala`). This is because with the addition of
    -the looping states, multiple input events can much a single (looping) state.
    \ No newline at end of file
    +events associated with each pattern (`List` in `Java`, `Iterable` in `Scala`). This is because with the addition of
    +the looping patterns, multiple input events can match a single (looping) pattern.
    +
    +3. The `followedBy()` in Flink 1.1 and 1.2 implied `non-deterministic relaxed contiguity` (see 
    --- End diff --
    
    Looks good! 😄 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119886927
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -700,26 +995,29 @@ class MyPatternFlatSelectFunction<IN, OUT> implements PatternFlatSelectFunction<
     </div>
     
     <div data-lang="scala" markdown="1">
    -The `select` method takes a selection function as argument, which is called for each matching event sequence.
    -It receives a map of string/event pairs of the matched events.
    -The string is defined by the name of the state to which the event has been matched.
    -The selection function returns exactly one result per call.
    +The `select()` method takes a selection function as argument, which is called for each matching event sequence.
    +It receives a match in the form of `Map[String, Iterable[IN]]` where the key is the name of each state in your pattern 
    +sequence and the value is an Iterable over all accepted events for that state (`IN` is the type of your input elements). 
    +The events for a given state are ordered by timestamp. The reason for returning an iterable of accepted events for each 
    +state is that when using looping states (e.g. `oneToMany()` and `times()`), more than one events may be accepted for a 
    +given state. The selection function returns exactly one result per call.
     
     {% highlight scala %}
    -def selectFn(pattern : mutable.Map[String, IN]): OUT = {
    -    val startEvent = pattern.get("start").get
    -    val endEvent = pattern.get("end").get
    +def selectFn(pattern : Map[String, Iterable[IN]]): OUT = {
    +    val startEvent = pattern.get("start").get.next
    +    val endEvent = pattern.get("end").get.next
         OUT(startEvent, endEvent)
     }
     {% endhighlight %}
     
    -The `flatSelect` method is similar to the `select` method. Their only difference is that the function passed to the `flatSelect` method can return an arbitrary number of results per call.
    -In order to do this, the function for `flatSelect` has an additional `Collector` parameter which is used for the element output.
    +The `flatSelect` method is similar to the `select` method. Their only difference is that the function passed to the 
    +`flatSelect` method can return an arbitrary number of results per call. In order to do this, the function for 
    +`flatSelect` has an additional `Collector` parameter which is used for forwarding your output elements downstream.
    --- End diff --
    
    ... which is used to forward ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119891095
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    +
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
    +<table class="table table-bordered">
    +    <thead>
    +        <tr>
    +            <th class="text-left" style="width: 25%">Pattern Operation</th>
    +            <th class="text-center">Description</th>
    +        </tr>
    +    </thead>
    +    <tbody>
    +       <tr>
    +            <td><strong>where(condition)</strong></td>
    +            <td>
    +                <p>Defines a condition for the current state. Only if an event satisifes the condition, 
    +                it can match the state. Multiple consecutive where() clauses lead to their condtions being 
    --- End diff --
    
    To match the state, an event must satisfy the condition.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119883989
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    --- End diff --
    
    +1 for the added formatting. I find the explanations hard to parse. How about this:
    
    1. Strict Contiguity: `{a2 b}` -- the `"c"` after `"a1"` causes `"a1"` to be discarded.
    
    2. Relaxed Contiguity: `{a1 b}` and `{a1 a2 b}` -- `"c"` is simply ignored.
    
    3. Non-Deterministic Relaxed Contiguity: `{a1 b}`, `{a2 b}`, and `{a1 a2 b}`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119612871
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    --- End diff --
    
    For the examples I would use some additional signs, cause just with the formatting it is hard to read.
    
    How about:
    
    To illustrate the above with an example, a pattern sequence `"a+ b"` (one or more `"a"`s followed by a `"b"`) with 
    
    input `"a1", "c", "a2", "b"` will have the following results:
    
     1. Strict Contiguity: `{a2 b}` because there is `"c"` `"a1"` and `"a2"` so `"a1"` is discarded.
    
     2. Relaxed Contiguity: `{a1 b}` and `{a1 a2 b}`, as `"c"` will get simply ignored.
     
     3. Non-Deterministic Relaxed Contiguity: `{a1 b}`, `{a2 b}` and `{a1 a2 b}`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119886720
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -700,26 +995,29 @@ class MyPatternFlatSelectFunction<IN, OUT> implements PatternFlatSelectFunction<
     </div>
     
     <div data-lang="scala" markdown="1">
    -The `select` method takes a selection function as argument, which is called for each matching event sequence.
    -It receives a map of string/event pairs of the matched events.
    -The string is defined by the name of the state to which the event has been matched.
    -The selection function returns exactly one result per call.
    +The `select()` method takes a selection function as argument, which is called for each matching event sequence.
    +It receives a match in the form of `Map[String, Iterable[IN]]` where the key is the name of each state in your pattern 
    +sequence and the value is an Iterable over all accepted events for that state (`IN` is the type of your input elements). 
    +The events for a given state are ordered by timestamp. The reason for returning an iterable of accepted events for each 
    +state is that when using looping states (e.g. `oneToMany()` and `times()`), more than one events may be accepted for a 
    --- End diff --
    
    ... more than one event may be accepted ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119606025
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +Contiguity conditions should be specified both within individual (looping) states but also 
    +across states. For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    --- End diff --
    
    Regarding "Contiguity conditions should be specified both within individual (looping) states but also across states".
    
    I'm not sure if it makes sense to present the detail that across states require contiguity conditions at this part of the doc. The main reason is that this section is about "Individual States", so the information was a bit "disruptive" when I first stumbled across it.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119608577
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    +
    +#### Quantifiers
    +
    +In FlinkCEP, looping patterns can be specified using the methods: `pattern.oneOrMore()`, for states that expect one or
    +more occurrences of a given event (e.g. the `b+` mentioned previously), and `pattern.times(#ofTimes)` for states that 
    +expect a specific number of occurrences of a given type of event, e.g. 4 `a`'s. All states, looping or not, can be made 
    +optional using the `pattern.optional()` method. For a state named `start`, the following are valid quantifiers:
    + 
    + <div class="codetabs" markdown="1">
    + <div data-lang="java" markdown="1">
    + {% highlight java %}
    + // expecting 4 occurrences
    + start.times(4);
    +  
    + // expecting 0 or 4 occurrences
    + start.times(4).optional();
    + 
    + // expecting 1 or more occurrences
    + start.oneOrMore();
    +   
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional();
    + {% endhighlight %}
    + </div>
    + 
    + <div data-lang="scala" markdown="1">
    + {% highlight scala %}
    + // expecting 4 occurrences
    + start.times(4)
    +   
    + // expecting 0 or 4 occurrences
    + start.times(4).optional()
    +  
    + // expecting 1 or more occurrences
    + start.oneOrMore()
    +    
    + // expecting 0 or more occurrences
    + start.oneOrMore().optional()
    + {% endhighlight %}
    + </div>
    + </div>
    +
    +#### Conditions
    +
    +At every state, and in order to go from one state to the next, you can specify additional **conditions**. 
    +These conditions can be related to:
    + 
    + 1. a [property of the incoming event](#conditions-on-properties), e.g. its value should be larger than 5, 
    + or larger than the average value of the previously accepted events.
    +
    + 2. the [contiguity of the matching events](#conditions-on-contiguity), e.g. detect pattern `a,b,c` without 
    + non-matching events between any matching ones.
    + 
    +The latter refers to "looping" states, i.e. states that can accept more than one event, e.g. the `b+` in `a b+ c`, 
    +which searches for one or more `b`'s.
    +
    +##### Conditions on Properties
    +
    +Conditions on the event properties can be specified via the `pattern.where()` method. These can be either 
    +`IterativeCondition`s or `SimpleCondition`s.
    +
    +**Iterative Conditions:** This is the most general type of conditions. This allows to specify a condition that accepts 
    +any subsequent event based on some statistic over a subset of the previously accepted events. 
    --- End diff --
    
    based on properties of the previously accepted events or even some statistic over a subset of them.
    
    This way we emphasize that we can take into account for example just the previous event.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119885420
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +334,399 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between events:
    +
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
    +
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
    --- End diff --
    
    Non-Deterministic Relaxed Contiguity is hard to understand. Maybe this is clearer:
    
    ... which further relaxes contiguity, allowing additional matches that ignore some matching events.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119606506
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -98,48 +128,105 @@ val result: DataStream[Alert] = patternStream.select(createAlert(_))
     </div>
     </div>
     
    -Note that we use Java 8 lambdas in our Java code examples to make them more succinct.
    -
     ## The Pattern API
     
    -The pattern API allows you to quickly define complex event patterns.
    -
    -Each pattern consists of multiple stages or what we call states.
    -In order to go from one state to the next, the user can specify conditions.
    -These conditions can be the contiguity of events or a filter condition on an event.
    -
    -Each pattern has to start with an initial state:
    +The pattern API allows you to quickly define complex pattern sequences that you want to extract 
    +from your input stream.
    +
    +Each such complex pattern sequence consists of multiple simple patterns, i.e. patterns looking for 
    +individual events with the same properties. These simple patterns are called **states**. A complex pattern 
    +can be seen as a graph of such states, where transition from one state to the next happens based on user-specified
    +*conditions*, e.g. `event.getName().equals("start")`. A *match* is a sequence of input events which visit all 
    +states of the complex pattern graph, through a sequence of valid state transitions.
    +
    +<span class="label label-danger">Attention</span> Each state must have a unique name to identify the matched 
    +events later on. 
    +
    +<span class="label label-danger">Attention</span> State names **CANNOT** contain the character `:`.
    +
    +In the remainder, we start by describing how to define [States](#states), before describing how you can 
    +combine individual states into [Complex Patterns](#combining-states).
    +
    +### Individual States
    +
    +A **State** can be either a *singleton* state, or a *looping* one. Singleton states accept a single event, 
    +while looping ones accept more than one. In pattern matching symbols, in the pattern `a b+ c? d` (or `a`, 
    +followed by *one or more* `b`'s, optionally followed by a `c`, followed by a `d`), `a`, `c?`, and `d` are 
    +singleton patterns, while `b+` is a looping one (see [Quantifiers](#quantifiers)). In addition, each state 
    +can have one or more *conditions* based on which it accepts events (see [Conditions](#conditions)).
    --- End diff --
    
    Perhaps somewhere in this paragraph, describe that by default, states are singleton? and to make it a looping one, use quantifiers.
    
    There is a sentence mentioning for looping state see quantifiers, but we can make the information a bit more explicit.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by tzulitai <gi...@git.apache.org>.
Github user tzulitai commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119607645
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -659,37 +913,45 @@ val patternStream: PatternStream[Event] = CEP.pattern(input, pattern)
     </div>
     </div>
     
    +The input stream can be *keyed* or *non-keyed* depending on your use-case.
    +
    +<span class="label label-danger">Attention</span> Applying your pattern on a non-keyed stream will result is a job with 
    +parallelism equal to 1.
    +
     ### Selecting from Patterns
    +
     Once you have obtained a `PatternStream` you can select from detected event sequences via the `select` or `flatSelect` methods.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     The `select` method requires a `PatternSelectFunction` implementation.
     A `PatternSelectFunction` has a `select` method which is called for each matching event sequence.
    -It receives a map of string/event pairs of the matched events.
    -The string is defined by the name of the state to which the event has been matched.
    -The `select` method can return exactly one result.
    +It receives a match in the form of `Map<String, List<IN>>` where the key is the name of each state in your pattern 
    +sequence and the value is a list of all accepted events for that state (`IN` is the type of your input elements). 
    --- End diff --
    
    Perhaps add information about the ordering of the list of matched events?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by rmetzger <gi...@git.apache.org>.
Github user rmetzger commented on the issue:

    https://github.com/apache/flink/pull/4041
  
    @dawidwys Do you think we can merge the updated documentation today already?
    I would like to put out the 1.3 release ann with a link to the CEP docs.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by alpinegizmo <gi...@git.apache.org>.
Github user alpinegizmo commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119887736
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -511,133 +849,81 @@ val start = Pattern.begin[Event]("start")
                 </td>
             </tr>
             <tr>
    -            <td><strong>Next</strong></td>
    +            <td><strong>next()</strong></td>
                 <td>
    -                <p>Appends a new pattern state. A matching event has to directly succeed the previous matching event:</p>
    +                <p>Appends a new pattern state. A matching event has to directly succeed the previous matching event 
    +                (strict contiguity):</p>
     {% highlight scala %}
     val next = start.next("middle")
     {% endhighlight %}
                 </td>
             </tr>
             <tr>
    -            <td><strong>FollowedBy</strong></td>
    +            <td><strong>followedBy()</strong></td>
                 <td>
    -                <p>Appends a new pattern state. Other events can occur between a matching event and the previous matching event:</p>
    +                <p>Appends a new pattern state. Other events can occur between a matching event and the previous 
    +                matching event (relaxed contiguity) :</p>
     {% highlight scala %}
     val followedBy = start.followedBy("middle")
     {% endhighlight %}
                 </td>
             </tr>
             <tr>
    -            <td><strong>Where</strong></td>
    -            <td>
    -                <p>Defines a filter condition for the current pattern state. Only if an event passes the filter, it can match the state:</p>
    -{% highlight scala %}
    -patternState.where(event => ... /* some condition */)
    -{% endhighlight %}
    -            </td>
    -        </tr>
    -        <tr>
    -            <td><strong>Or</strong></td>
    -            <td>
    -                <p>Adds a new filter condition which is ORed with an existing filter condition. Only if an event passes the filter condition, it can match the state:</p>
    -{% highlight scala %}
    -patternState.where(event => ... /* some condition */)
    -    .or(event => ... /* alternative condition */)
    -{% endhighlight %}
    -                    </td>
    +                    <td><strong>followedByAny()</strong></td>
    +                    <td>
    +                        <p>Appends a new pattern state. Other events can occur between a matching event and the previous 
    +                        matching event and alternative matches will be presented for every alternative matching event 
    --- End diff --
    
    add a comma:
    
    ... matching event, and alternative matches will be ...


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119616280
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    +
    + 2. Relaxed Contiguity: `a1 b` and `a1 a2 b`, as `c` will get simply ignored.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: `a1 b`, `a2 b` and `a1 a2 b`.
    + 
    +Contiguity conditions should be specified both within individual (looping) states but also 
    +across states. For looping states (e.g. `oneOrMore()` and `times()`) the default is *relaxed contiguity*. If you want 
    +strict contiguity, you have to explicitly specify it by using the `consecutive()` call, and if you want 
    +*non-deterministic relaxed contiguity* you can use the `allowCombinations()` call.
    +
    +### Combining States
    +
    +Now that we have seen how an individual state can look, it is time to see how to combine them into a full pattern sequence.
    +
    +A pattern sequence has to start with an initial state, as shown below:
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedBy("middle");
    +Pattern<Event, ?> start = Pattern.<Event>begin("start");
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedBy("middle")
    +val start : Pattern[Event, _] = Pattern.begin("start")
     {% endhighlight %}
     </div>
     </div>
     
    -For non-strict contiguity one can specify if only the first succeeding matching event will be matched, or
    -all. In the latter case multiple matches will be emitted for the same beginning.
    +Next, you can append more states to your pattern by specifying the desired *contiguity conditions* between them. 
    +This can be done using: 
    +
    +1. `next()`, for *strict*, 
    +2. `followedBy()`, for *relaxed*, and 
    +3. `followedByAny()`, for *non-deterministic relaxed* contiguity.
    +
    +or 
    +
    +1. `notNext()`, if you do not want an event type to directly follow another
    +2. `notFollowedBy()`, if you do not want an event type to be anywhere between two other event types
    +
    +
    +<span class="label label-danger">Attention</span> A pattern sequence cannot end in `notFollowedBy()`.
    +
    +<span class="label label-danger">Attention</span> A `NOT` state cannot be preceded by an optional one.
     
     <div class="codetabs" markdown="1">
     <div data-lang="java" markdown="1">
     {% highlight java %}
    -Pattern<Event, ?> nonStrictNext = start.followedByAny("middle");
    +
    +// strict contiguity
    +Pattern<Event, ?> strict = start.next("middle").where(...);
    +
    +// relaxed contiguity
    +Pattern<Event, ?> relaxed = start.followedBy("middle").where(...);
    +
    +// non-deterministic relaxed contiguity
    +Pattern<Event, ?> nonDetermin = start.followedByAny("middle").where(...);
    +
    +// NOT pattern with strict contiguity
    +Pattern<Event, ?> strictNot = start.notNext("not").where(...);
    +
    +// NOT pattern with relaxed contiguity
    +Pattern<Event, ?> relaxedNot = start.notFollowedBy("not").where(...);
    +
     {% endhighlight %}
     </div>
     
     <div data-lang="scala" markdown="1">
     {% highlight scala %}
    -val nonStrictNext : Pattern[Event, _] = start.followedByAny("middle")
    +
    +// strict contiguity
    +val strict: Pattern[Event, _] = start.next("middle").where(...)
    +
    +// relaxed contiguity
    +val relaxed: Pattern[Event, _] = start.followedBy("middle").where(...)
    +
    +// non-deterministic relaxed contiguity
    +val nonDetermin: Pattern[Event, _] = start.followedByAny("middle").where(...)
    +
    +// NOT pattern with strict contiguity
    +val strictNot: Pattern[Event, _] = start.notNext("not").where(...)
    +
    +// NOT pattern with relaxed contiguity
    +val relaxedNot: Pattern[Event, _] = start.notFollowedBy("not").where(...)
    +
     {% endhighlight %}
     </div>
    -
     </div>
    -It is also possible to define a temporal constraint for the pattern to be valid.
    -For example, one can define that a pattern should occur within 10 seconds via the `within` method. 
    +
    +Bear in mind that relaxed contiguity means that only the first succeeding matching event will be matched, while
    +non-deterministic relaxed contiguity, multiple matches will be emitted for the same beginning.
    +
    +Finally, it is also possible to define a temporal constraint for the pattern to be valid.
    --- End diff --
    
    I would emphasize it applies whole pattern sequence. And if multiple within are applied (even for different states/parts) the shortes one is picked up.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #4041: [FLINK-6198] [cep] Update CEP documentation.

Posted by dawidwys <gi...@git.apache.org>.
Github user dawidwys commented on a diff in the pull request:

    https://github.com/apache/flink/pull/4041#discussion_r119611549
  
    --- Diff: docs/dev/libs/cep.md ---
    @@ -246,63 +333,118 @@ pattern.where(event => ... /* some condition */).or(event => ... /* or condition
     </div>
     </div>
     
    -Next, we can append further states to detect complex patterns.
    -We can control the contiguity of two succeeding events to be accepted by the pattern.
    +##### Conditions on Contiguity
     
    -Strict contiguity means that two matching events have to be directly the one after the other.
    -This means that no other events can occur in between. 
    -A strict contiguity pattern state can be created via the `next` method.
    +FlinkCEP supports the following forms of contiguity between consecutive events:
     
    -<div class="codetabs" markdown="1">
    -<div data-lang="java" markdown="1">
    -{% highlight java %}
    -Pattern<Event, ?> strictNext = start.next("middle");
    -{% endhighlight %}
    -</div>
    + 1. Strict Contiguity: which expects all matching events to appear strictly the one after the other,
    + without any non-matching events in-between.
     
    -<div data-lang="scala" markdown="1">
    -{% highlight scala %}
    -val strictNext: Pattern[Event, _] = start.next("middle")
    -{% endhighlight %}
    -</div>
    -</div>
    + 2. Relaxed Contiguity: which simply ignores non-matching events appearing in-between the matching ones.
    + 
    + 3. Non-Deterministic Relaxed Contiguity: which further relaxes contiguity by also creating alternative
    + matches which ignore also matching events.
     
    -Non-strict contiguity means that other events are allowed to occur in-between two matching events.
    -A non-strict contiguity pattern state can be created via the `followedBy` or `followedByAny` method.
    +To illustrate the above with an example, a pattern sequence `a+ b` (one or more `a`s followed by a `b`) with 
    +input `a1, c, a2, b` will have the following results:
    +
    + 1. Strict Contiguity: `a2 b` because there is `c` `a1` and `a2` so `a1` is discarded.
    --- End diff --
    
    there is `c` between `a1` and `a2`


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---