com.fluxtion.ext.streaming.api.Wrapper Maven / Gradle / Ivy
/*
* Copyright (C) 2018 V12 Technology Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* .
*/
package com.fluxtion.ext.streaming.api;
import com.fluxtion.api.SepContext;
import com.fluxtion.api.partition.LambdaReflection.SerializableBiFunction;
import com.fluxtion.api.partition.LambdaReflection.SerializableConsumer;
import com.fluxtion.api.partition.LambdaReflection.SerializableFunction;
import com.fluxtion.ext.streaming.api.group.GroupBy;
import com.fluxtion.ext.streaming.api.stream.Argument;
import com.fluxtion.ext.streaming.api.stream.StreamOperator;
import com.fluxtion.ext.streaming.api.window.WindowBuildOperations;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
/**
* A wrapper class that holds a reference to a node in the SEP. Any node in SEP
* can be a source of a stream of values.
* Stream operations are provided to filter and map the underlying wrapped type.
*
* @author Greg Higgins
* @param
*/
public interface Wrapper extends Stateful{
/**
* The wrapped node
*
* @return the wrapped node
*/
T event();
/**
* The type of the wrapped node
*
* @return wrapped node class
*/
Class eventClass();
@Override
default void reset(){}
default Argument arg(SerializableFunction supplier){
return Argument.arg(this, supplier);
}
default Argument arg(){
return Argument.arg(this);
}
/**
* Set the default value for this instance. The default value will be set when any call to reset is made. Having a
* default value allows an instance to be used by its children before an event has been processed.
*
* @param defaultValue the default value to use
* @return
*/
default Wrapper defaultVal(T defaultValue){
return StreamOperator.service().defaultVal(this, defaultValue);
}
default FilterWrapper filter(SerializableFunction filter) {
return StreamOperator.service().filter(filter, this, true);
}
default FilterWrapper filter(SerializableFunction supplier, SerializableFunction extends S, Boolean> filter) {
return StreamOperator.service().filter(filter, this, supplier.method(), true);
}
default Wrapper get(SerializableFunction supplier) {
return StreamOperator.service().get(supplier, this);
}
default WrappedList collect(){
return SepContext.service().add(new ArrayListWrappedCollection<>(this));
}
default GroupBy group(
SerializableFunction key,
SerializableBiFunction super R, ? super R, ? extends R> functionClass) {
return StreamOperator.service().group(this, key, functionClass);
}
default GroupBy group(
SerializableFunction key,
SerializableFunction supplier,
SerializableBiFunction super R, ? super R, ? extends R> functionClass) {
return StreamOperator.service().group(this, key, supplier, functionClass);
}
/**
* Maps a value using the provided mapping function.The input is the
* wrapped instance inside this {@link Wrapper}.
*
* @param The return type of the mapping function
* @param
* @param mapper the mapping function
* @return A wrapped value containing the result of the mapping operation
*/
default Wrapper map(SerializableFunction mapper) {
return (Wrapper) StreamOperator.service().map((SerializableFunction) mapper, this, true);
}
/**
* Maps a value using the provided mapping function. The input is the return
* value of the supplier function invoked on the wrapped instance.
*
* @param The return type of the mapping function
* @param The input type required by the mapping function
* @param mapper the mapping function
* @param supplier
* @return A wrapped value containing the result of the mapping operation
*/
default Wrapper map(SerializableFunction extends S, R> mapper, SerializableFunction supplier) {
return StreamOperator.service().map((SerializableFunction) mapper, this, supplier.method(), true);
}
default Wrapper map(SerializableBiFunction mapper, Argument arg1, Argument arg2) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg1, arg2);
}
default Wrapper map(SerializableBiFunction extends U, ? extends S, R> mapper,
SerializableFunction supplier1, SerializableFunction supplier2) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(this, supplier1), Argument.arg(this, supplier2));
}
default Wrapper map(SerializableBiFunction extends U, ? extends S, R> mapper, SerializableFunction supplier, Argument arg) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(this, supplier), arg);
}
default Wrapper map(SerializableBiFunction extends U, ? extends S, R> mapper, Argument arg, SerializableFunction supplier) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg, Argument.arg(this, supplier));
}
default Wrapper map(SerializableBiFunction extends U, S, R> mapper, SerializableFunction supplier, double arg) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(this, supplier), Argument.arg(arg));
}
default Wrapper map(SerializableBiFunction extends U, ? extends S, R> mapper, double arg, SerializableFunction supplier) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(arg), Argument.arg(this, supplier));
}
/**
* Maps a binary function using the wrapped instance as the first argument
* to the binary function.
*
* @param The result type of the mapping function
* @param The type of the supplied argument
* @param The input type for first argument to mapping function
* @param The input type for second argument to mapping function
* @param mapper The mapping function
* @param arg1 The second argument of the binary mapping function
* @return
*/
default Wrapper map(SerializableBiFunction mapper, Argument arg1) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(this), arg1);
}
default Wrapper map(SerializableBiFunction mapper, double arg1) {
return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, Argument.arg(this), Argument.arg(arg1));
}
//windows reducing
/**
* Create a time based tumbling window aggregate result expiring after a duration has passed. The window combines the results of the supplied
* function for all events that occur within the timed window
* @param the result type of the function
* @param mapper The function to apply to each event in the window
* @param time The duration of the window
* @return A result that is updated at the window expiry
*/
default Wrapper tumbling(SerializableFunction mapper, Duration time) {
return WindowBuildOperations.service().tumbling(this, mapper, time);
}
/**
* Create a count based tumbling window aggregate result expiring after receiving a number of events. The window combines the results of the supplied
* function for all events that occur within the window
* @param the result type of the function
* @param mapper The function to apply to each event in the window
* @param itemCount the number of events in a window
* @return A result that is updated at the window expiry
*/
default Wrapper tumbling(SerializableFunction mapper, int itemCount) {
return WindowBuildOperations.service().tumbling(this, mapper, itemCount);
}
/**
* Create a time based sliding window aggregate result publishing after a duration has passed. The window combines the results of the supplied
* function for all events that occur within the number of buckets. The total window time = time per bucket X number of buckets
* @param the result type of the function
* @param mapper The function to apply to each event in the window
* @param time The duration of a bucket
* @param numberOfBuckets the number of buckets in the window
* @return A result that is updated at the window expiry
*/
default Wrapper sliding(SerializableFunction mapper, Duration time, int numberOfBuckets) {
return WindowBuildOperations.service().sliding(this, mapper, time, numberOfBuckets);
}
/**
* Create a count based sliding window aggregate result publishing after a count has passed. The window combines the results of the supplied
* function for all events that occur within the number of buckets. The total window count = the number of events per bucket X number of buckets
* @param the result type of the function
* @param mapper The function to apply to each event in the window
* @param itemCountPerBuket the number of events per bucket
* @param numberOfBuckets the number of buckets in the window
* @return A result that is updated at the window expiry
*/
default Wrapper sliding(SerializableFunction mapper, int itemCountPerBuket, int numberOfBuckets) {
return WindowBuildOperations.service().sliding(this, mapper, itemCountPerBuket, numberOfBuckets);
}
//window collecting
/**
* Collects the events into a WrappedList using a time based sliding window strategy.
* @param timePerBucket time per bucket
* @param numberOfBuckets number of buckets in sliding window
* @return The collection of events in sliding window
*/
default WrappedList sliding(Duration timePerBucket, int numberOfBuckets){
return WindowBuildOperations.service().sliding(collect(), timePerBucket, numberOfBuckets);
}
/**
* Collects the events into a WrappedList using a count based sliding window strategy.
* @param itemCount the count of events per bucket
* @param numberOfBuckets number of buckets in sliding window
* @return The collection of events in sliding window
*/
default WrappedList sliding(int itemCount, int numberOfBuckets){
return WindowBuildOperations.service().sliding(collect(), itemCount, numberOfBuckets);
}
/**
* Collects the events into a WrappedList using a time based tumbling window strategy.
* @param time duration of the tumbling window
* @return The collection of events in sliding window
*/
default WrappedList tumbling(Duration time){
return WindowBuildOperations.service().tumbling(collect(), time);
}
/**
* Collects the events into a WrappedList using a time based tumbling window strategy.
* @param itemCount number of items in the tumbling window
* @return The collection of events in sliding window
*/
default WrappedList tumbling(int itemCount){
return WindowBuildOperations.service().tumbling(collect(), itemCount);
}
/**
* pushes a data item from the current node in the stream to any node.The
* target node will become part of the same execution graph as the
* source.
* The returned node is the current node in the stream.
*
* @param
* @param
* @param supplier
* @param mapper
* @return this
*/
default Wrapper push(SerializableFunction supplier, SerializableConsumer mapper) {
StreamOperator.service().push(this, supplier.method(), mapper);
return (Wrapper) this;
}
default Wrapper push(SerializableConsumer mapper) {
StreamOperator.service().push(this, null, mapper);
return (Wrapper) this;
}
/**
* Registers a {@link Consumer} to operate on the current node when an event
* wave is passing through this node. The consumer can perform any operation
* on the node including mutations. This node, possibly mutated, is passed
* as a reference to child nodes. No new nodes are created in the stream as
* a side-effect of this processing.
*
* @param consumer {@link Consumer} of this node
* @return The current node
*/
default Wrapper forEach(SerializableConsumer consumer) {
return (Wrapper) StreamOperator.service().forEach(consumer, this, null);
}
default Wrapper forEach(SerializableConsumer consumer, String consumerId) {
return (Wrapper) StreamOperator.service().forEach(consumer, this, consumerId);
}
LongAdder counter = new LongAdder();
/**
* dump this node to log, prefixed with the supplied
message.{@link Object#toString()} will be invoked on the node instance.
*
* @param prefix String prefix for the log message
* @param supplier
* @return The current node
*/
default Wrapper log(String prefix, SerializableFunction... supplier) {
if (!prefix.contains("{}")) {
prefix += " {}";
}
return (Wrapper) StreamOperator.service().log(this, prefix, supplier);
}
default Wrapper log() {
return log("");
}
/**
* Attaches an event notification instance to the current stream node. When
* the notifier updates all the child nodes of this stream node will be on
* the execution path and invoked following normal SEP rules.
*
* The existing execution path will be unaltered if either the parent
* wrapped node or the eventNotifier updates then the execution path will
* progress.
*
* @param eventNotifier external event notifier
* @return
*/
default Wrapper notiferMerge(Object eventNotifier) {
return StreamOperator.service().notiferMerge(this, eventNotifier);
}
/**
* Attaches an event notification instance to the current stream node,
* overriding the execution path of the current stream. Only when the
* notifier updates will the child nodes of this stream node be on the
* execution path.
*
* @param eventNotifier external event notifier
* @return
*/
default Wrapper notifierOverride(Object eventNotifier) {
return StreamOperator.service().notifierOverride(this, eventNotifier);
}
/**
* Publishes the current value to all child dependencies and then resets. After all children have processed the trigger a reset is
* invoked on the wrapped instance. The publish and reset is triggered when the supplied notifier triggers in the
* execution graph.
*
* @param notifier trigger for publish and reset
* @return
*/
default Wrapper publishAndReset(Object notifier) {
return this;
}
/**
* Resets the current value without notifying children of a change. The reset is triggered when the supplied notifier triggers in the
* execution graph.
*
* @param notifier trigger for reset
* @return
*/
default Wrapper resetNoPublish(Object notifier){
return this;
}
/**
* Resets the stateful node and publishes the current value by notifying child nodes. The reset is
* before the notification is broadcast. The reset and publish is triggered when the supplied notifier triggers in the
* execution graph.
*
* @param notifier trigger for reset and publish
* @return
*/
default Wrapper resetAndPublish(Object notifier) {
return this;
}
/**
* Controls the notification policy of event notification to child nodes for
* this stream node. The default policy is to invoke child nodes when the
* return of the parent event method is true. NotifyOnChange notifies the
* child only when the parent node return of the previous cycle is false and
* this one is true.
*
*
* This can be useful if a single notification of a breach is required and
* subsequent continued breaches are swallowed, for example this can prevent
* logging spamming when combined with filters.
*
* @param notifyOnChange false = notify always. true = notify on change only
* @return The current node
*/
default Wrapper notifyOnChange(boolean notifyOnChange) {
return this;
}
/**
* Set this property to signal the wrapper has a valid value and child nodes do not have to wait for a trigger
* notification before using the data from this instance.
*
* @param validOnStart
* @return
*/
default Wrapper validOnStart(boolean validOnStart) {
return this;
}
default boolean isValidOnStart() {
return false;
}
/**
* Set the node id for this node within the generated SEP. This is the
* variable name of the node in a Java SEP. The id must be unique for the
* SEP.
*
* @param id the unique id of the node in the SEP
* @return The current node
*/
default Wrapper id(String id) {
return StreamOperator.service().nodeId(this, id);
}
}