All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxtion.ext.streaming.api.Wrapper Maven / Gradle / Ivy

There is a newer version: 2.10.50
Show newest version
/* 
 * 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.numeric.NumericFunctionStateless;
import com.fluxtion.ext.streaming.api.stream.Argument;
import static com.fluxtion.ext.streaming.api.stream.Argument.arg;
import com.fluxtion.ext.streaming.api.stream.StreamFunctions;
import com.fluxtion.ext.streaming.api.stream.StreamOperator;
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 { /** * The wrapped node * * @return the wrapped node */ T event(); /** * The type of the wrapped node * * @return wrapped node class */ Class eventClass(); default FilterWrapper filter(SerializableFunction filter) { return StreamOperator.service().filter(filter, this, true); } default FilterWrapper filter(SerializableFunction supplier, SerializableFunction filter) { return StreamOperator.service().filter(filter, this, supplier.method(), true); } default Wrapper get(SerializableFunction supplier) { if(supplier.method().getReturnType().isPrimitive()){ return (Wrapper) map((SerializableFunction)StreamFunctions.toDouble(), supplier); } else{ return (Wrapper) map((SerializableFunction)StreamFunctions.toReference(), supplier); } } default GroupBy group( SerializableFunction supplier, Class functionClass){ return StreamOperator.service().group(this, supplier, functionClass); } default GroupBy group( SerializableFunction key, SerializableFunction supplier, Class 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 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 mapper, SerializableFunction supplier) { return (Wrapper) StreamOperator.service().map((SerializableFunction) mapper, this, supplier.method(), true); } /** * maps a two arguments using a binary function. * @param * @param * @param * @param mapper * @param arg1 * @param arg2 * @return */ default Wrapper map(SerializableBiFunction mapper, Argument arg1, Argument arg2) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg1, arg2); } default Wrapper map(SerializableBiFunction mapper, SerializableFunction supplier1, SerializableFunction supplier2) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg(this, supplier1), arg(this, supplier2)); } default Wrapper map(SerializableBiFunction mapper, SerializableFunction supplier, Argument arg) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg(this, supplier), arg); } default Wrapper map(SerializableBiFunction mapper, Argument arg, SerializableFunction supplier) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg, arg(this, supplier)); } default Wrapper map(SerializableBiFunction mapper, SerializableFunction supplier, double arg) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg(this, supplier), arg(arg)); } default Wrapper map(SerializableBiFunction mapper, double arg, SerializableFunction supplier) { return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg(arg), 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, arg(this), arg1); } default Wrapper map(SerializableBiFunction mapper, double arg1){ return (Wrapper) StreamOperator.service().map((SerializableBiFunction) mapper, arg(this), arg(arg1)); } /** * 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 the com.fluxtion.ext.declarative.api.Wrapper */ 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 console, prefixed with the supplied message.{@link Object#toString()} will be invoked on the node instance. * * @param * @param prefix String prefix for the console message * @param supplier * @return The current node */ default Wrapper console(String prefix, SerializableFunction... supplier) { StreamOperator.ConsoleLog consoleLog = new StreamOperator.ConsoleLog(this, prefix); counter.increment(); if(supplier.length == 0 && Number.class.isAssignableFrom(eventClass())){ consoleLog.suppliers(Number::doubleValue); }else{ consoleLog.suppliers(supplier); } String consoleId = "consoleMsg_" + counter.intValue(); SepContext.service().add(consoleLog, consoleId); return this; } /** * Attaches a reset notifier instance to the current stream node. If the * node is {@link Stateful} it may be desirable to reset its state under * controlled conditions. When the resetNotifier is on an execution path it * will invoke the reset method of this node if it is {@link Stateful} * * @param resetNotifier external notifier * @return */ default Wrapper resetNotifier(Object resetNotifier) { return this; } /** * 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); } /** * resets the stateful node and publishes the current value. The reset is * after * the last child on the execution path is executed, equivalent to {@link #immediateReset(boolean) * } * with value of false. * * @param notifier * @return */ default Wrapper publishAndReset(Object notifier) { resetNotifier(notifier); immediateReset(false); return notifierOverride(notifier); } /** * 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; } /** * Controls reset timing policy for stateful nodes. Stateful nodes are * reset with {@link #resetNotifier(java.lang.Object) * } or {@link #alwaysReset(boolean) }. The timing policy has the following * behaviour: *

    *
  • true - the stateful node will be reset before any child nodes are * invoked on the execution path *
  • false: - the stateful node will be reset after the final node on the * execution path *
* * @param immediateReset reset timing policy * @return */ default Wrapper immediateReset(boolean immediateReset) { return this; } /** * Reset a stateful node after every execution cycle, without the need for a * an external {@link #resetNotifier(java.lang.Object) }. *
    *
  • true - the stateful node will be reset after every execution cycle *
  • false: - the stateful node will only be reset with {@link #resetNotifier(java.lang.Object) * } *
* * @param alwaysReset - reset policy for stateful nodes * @return */ default Wrapper alwaysReset(boolean alwaysReset) { return this; } /** * 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); } }