com.fluxtion.compiler.builder.dataflow.DataFlow Maven / Gradle / Ivy
package com.fluxtion.compiler.builder.dataflow;
import com.fluxtion.runtime.EventProcessorBuilderService;
import com.fluxtion.runtime.dataflow.FlowFunction;
import com.fluxtion.runtime.dataflow.aggregate.AggregateFlowFunction;
import com.fluxtion.runtime.dataflow.function.MergeMapFlowFunction;
import com.fluxtion.runtime.dataflow.function.NodePropertyToFlowFunction;
import com.fluxtion.runtime.dataflow.function.NodeToFlowFunction;
import com.fluxtion.runtime.dataflow.groupby.GroupByKey;
import com.fluxtion.runtime.event.Event;
import com.fluxtion.runtime.event.Signal;
import com.fluxtion.runtime.node.DefaultEventHandlerNode;
import com.fluxtion.runtime.partition.LambdaReflection;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableBiFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableSupplier;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Helper methods for subscribing and creating an {@link FlowBuilder} from external events or internal nodes
* in the graph.
*/
public interface DataFlow {
/**
* Subscribes to events of type {@literal }. Creates a handler method in the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* so that if {@link com.fluxtion.runtime.StaticEventProcessor#onEvent(Object)} is called an invocation is routed
* to this {@link FlowFunction}
*
* @param classSubscription A class literal describing the subscription
* @param The actual type dispatched to this {@link FlowFunction} by the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribe(Class classSubscription) {
return new FlowBuilder<>(
EventProcessorBuilderService.service().addOrReuse(new DefaultEventHandlerNode<>(classSubscription))
);
}
/**
* Subscribes to events of type {@literal } filtering by {@link Event#filterString()}. Creates a handler method in the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* so that if {@link com.fluxtion.runtime.StaticEventProcessor#onEvent(Object)} is called an invocation is routed
* to this {@link FlowFunction}
*
* @param classSubscription A class literal describing the subscription
* @param The actual type dispatched to this {@link FlowFunction} by the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* @param filter The filter string to apply
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribe(Class classSubscription, String filter) {
return new FlowBuilder<>(
EventProcessorBuilderService.service().addOrReuse(new DefaultEventHandlerNode<>(filter, classSubscription))
);
}
/**
* Subscribes to events of type {@literal } filtering by {@link Event#filterId()}. Creates a handler method in the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* so that if {@link com.fluxtion.runtime.StaticEventProcessor#onEvent(Object)} is called an invocation is routed
* to this {@link FlowFunction}
*
* @param classSubscription A class literal describing the subscription
* @param The actual type dispatched to this {@link FlowFunction} by the generated {@link com.fluxtion.runtime.StaticEventProcessor}
* @param filter The filter int to apply
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribe(Class classSubscription, int filter) {
return new FlowBuilder<>(
EventProcessorBuilderService.service().addOrReuse(new DefaultEventHandlerNode<>(filter, classSubscription))
);
}
/**
* Subscribes to an internal node within the processing graph and presents it as an {@link FlowBuilder}
* for constructing stream processing logic.
*
* @param source The node to be wrapped and made head of this stream
* @param The type of the node
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToNode(T source) {
return new FlowBuilder<>(new NodeToFlowFunction<>(source));
}
/**
* Subscribes to a property on an internal node within the processing graph and presents it as an {@link FlowBuilder}
* for constructing stream processing logic. The node will be created and added to the graph
*
* @param sourceProperty The property accessor
* @param The type of the node
* @param The type of the property that will be supplied in the stream
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToNodeProperty(SerializableFunction sourceProperty) {
T source;
if (sourceProperty.captured().length == 0) {
try {
source = (T) sourceProperty.getContainingClass().getDeclaredConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
NoSuchMethodException e) {
throw new RuntimeException("no default constructor found for class:"
+ sourceProperty.getContainingClass()
+ " either add default constructor or pass in a node instance");
}
} else {
source = (T) sourceProperty.captured()[0];
}
return subscribeToNode(source).map(sourceProperty);
}
/**
* Subscribes to a property on an internal node within the processing graph and presents it as an {@link FlowBuilder}
* for constructing stream processing logic.
*
* @param propertySupplier The property accessor
* @param The type of the property that will be supplied in the stream
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToNodeProperty(SerializableSupplier propertySupplier) {
EventProcessorBuilderService.service().addOrReuse(propertySupplier.captured()[0]);
return new FlowBuilder<>(new NodePropertyToFlowFunction<>(propertySupplier));
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToSignal(String filterId) {
return subscribe(Signal.class, filterId);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a stream that subscribes to a filtered
* {@link Signal} event, containing an event of the type specified. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @param signalType The type of value that is held by the {@link Signal} event
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToSignal(String filterId, Class signalType) {
return subscribe(Signal.class, filterId).map(Signal::getValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a stream that subscribes to a filtered
* {@link Signal} event, containing an event of the type specified. A default value is provided if the signal
* event contains a null value. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @param signalType The type of value that is held by the {@link Signal} event
* @param defaultValue the value to use if the signal event value is null
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder subscribeToSignal(String filterId, Class signalType, T defaultValue) {
return subscribe(Signal.class, filterId).map(Signal::getValue).defaultValue(defaultValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a int stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @return An {@link IntFlowBuilder} that can used to construct stream processing logic
*/
static IntFlowBuilder subscribeToIntSignal(String filterId) {
return subscribe(Signal.IntSignal.class, filterId).mapToInt(Signal.IntSignal::getValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a int stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows. A default value is provided if the signal
* event contains a 0 value
*
* @param filterId The filter string to apply
* @param defaultValue to use if the signal event value is 0
* @return An {@link IntFlowBuilder} that can used to construct stream processing logic
*/
static IntFlowBuilder subscribeToIntSignal(String filterId, int defaultValue) {
return subscribe(Signal.IntSignal.class, filterId).mapToInt(Signal.IntSignal::getValue)
.defaultValue(defaultValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a double stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @return An {@link DoubleFlowBuilder} that can used to construct stream processing logic
*/
static DoubleFlowBuilder subscribeToDoubleSignal(String filterId) {
return subscribe(Signal.DoubleSignal.class, filterId).mapToDouble(Signal.DoubleSignal::getValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a double stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows. A default value is provided if the signal
* event contains a 0 value
*
* @param filterId The filter string to apply
* @param defaultValue to use if the signal event value is 0
* @return An {@link DoubleFlowBuilder} that can used to construct stream processing logic
*/
static DoubleFlowBuilder subscribeToDoubleSignal(String filterId, double defaultValue) {
return subscribe(Signal.DoubleSignal.class, filterId).mapToDouble(Signal.DoubleSignal::getValue)
.defaultValue(defaultValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a long stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows.
*
* @param filterId The filter string to apply
* @return An {@link LongFlowBuilder} that can used to construct stream processing logic
*/
static LongFlowBuilder subscribeToLongSignal(String filterId) {
return subscribe(Signal.LongSignal.class, filterId).mapToLong(Signal.LongSignal::getValue);
}
/**
* See {@link DataFlow#subscribe(Class)} shortcut method to create a long stream that subscribes to a filtered
* {@link Signal} event. Useful for invoking triggers on flows. A default value is provided if the signal
* event contains a 0 value
*
* @param filterId The filter string to apply
* @param defaultValue to use if the signal event value is 0
* @return An {@link LongFlowBuilder} that can used to construct stream processing logic
*/
static LongFlowBuilder subscribeToLongSignal(String filterId, long defaultValue) {
return subscribe(Signal.LongSignal.class, filterId).mapToLong(Signal.LongSignal::getValue)
.defaultValue(defaultValue);
}
/**
* Merges and maps several {@link FlowFunction}'s into a single event stream of type T
*
* @param builder The builder defining the merge operations
* @param The output type of the merged stream
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder mergeMap(MergeAndMapFlowBuilder builder) {
MergeMapFlowFunction build = builder.build();
return new FlowBuilder<>(build);
}
/**
* Merges two {@link FlowBuilder}'s into a single event stream of type T
*
* @param streamAToMerge stream A to merge
* @param streamBToMerge stream B to merge
* @param type of stream A
* @param type of stream B
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder merge(FlowBuilder streamAToMerge, FlowBuilder streamBToMerge) {
return streamAToMerge.merge(streamBToMerge);
}
/**
* Merges multiple {@link FlowBuilder}'s into a single event stream of type T
*
* @param streamAToMerge stream A to merge
* @param streamBToMerge stream B to merge
* @param streamsToMerge streams to merge
* @param type of stream A
* @param type of stream B
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
@SuppressWarnings("unchecked")
static FlowBuilder merge(
FlowBuilder streamAToMerge,
FlowBuilder streamBToMerge,
FlowBuilder extends T>... streamsToMerge) {
return streamAToMerge.merge(streamBToMerge, streamsToMerge);
}
/**
* Applies a mapping bi function to a pair of streams, creating a stream that is the output of the function. The
* mapping function will be invoked whenever either stream triggers a notification
*
* @param biFunction The mapping {@link java.util.function.BiFunction}
* @param streamArg1 Stream providing the first argument to the mapping function
* @param streamArg2 Stream providing the second argument to the mapping function
* @param The type of argument 1 stream
* @param The type of argument 2 stream
* @param The return type of the mapping function
* @return An {@link FlowBuilder} that can used to construct stream processing logic
*/
static FlowBuilder mapBiFunction(SerializableBiFunction biFunction,
FlowBuilder streamArg1,
FlowBuilder streamArg2) {
return streamArg1.mapBiFunction(biFunction, streamArg2);
}
static GroupByFlowBuilder groupBy(SerializableFunction keyFunction) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupBy(keyFunction);
}
@SafeVarargs
static GroupByFlowBuilder, T> groupByFields(SerializableFunction... keyFunction) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction[0].method().getDeclaringClass();
return subscribe(classSubscription).groupByFields(keyFunction);
}
static > GroupByFlowBuilder groupBy(
SerializableFunction keyFunction, SerializableSupplier aggregateFunctionSupplier) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupBy(keyFunction, aggregateFunctionSupplier);
}
/**
* Aggregates a set of instances into a multimap style structure. The key is a compound key made up from an accessor
* of the input data
*
* @param keyFunction The accessor that makes up the key
* @param The item to aggregate
* @return The GroupByFlowBuilder that represents the multimap
*/
static GroupByFlowBuilder> groupByToList(SerializableFunction keyFunction) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupByToList(keyFunction);
}
static FlowBuilder> collectionFromSubscribe(Class classSubscription) {
return subscribe(classSubscription).mapToCollection();
}
static FlowBuilder> listFromSubscribe(Class classSubscription) {
return subscribe(classSubscription).mapToList();
}
static FlowBuilder> setFromSubscribe(Class classSubscription) {
return subscribe(classSubscription).mapToSet();
}
/**
* Aggregates a set of instances into a multimap style structure. The key is a compound key made up from the accessors
* of the input data
*
* @param keyFunctions The accessors that make up the compound key
* @param The item to aggregate
* @return The GroupByFlowBuilder that represents the multimap
*/
@SafeVarargs
static GroupByFlowBuilder, List> groupByToList(LambdaReflection.SerializableFunction... keyFunctions) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunctions[0].method().getDeclaringClass();
return subscribe(classSubscription).groupByToList(keyFunctions);
}
static GroupByFlowBuilder> groupByToSet(SerializableFunction keyFunction) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupByToSet(keyFunction);
}
/**
* Aggregates a set of instances into a multiset style structure. The key is a compound key made up from the accessors
* of the input data
*
* @param keyFunctions The accessors that make up the compound key
* @param The item to aggregate
* @return The GroupByFlowBuilder that represents the multimap
*/
@SafeVarargs
static GroupByFlowBuilder, Set> groupByToSet(LambdaReflection.SerializableFunction... keyFunctions) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunctions[0].method().getDeclaringClass();
return subscribe(classSubscription).groupByToSet(keyFunctions);
}
static GroupByFlowBuilder groupBy(
SerializableFunction keyFunction,
SerializableFunction valueFunction) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupBy(keyFunction, valueFunction);
}
static > GroupByFlowBuilder
groupBy(SerializableFunction keyFunction,
SerializableFunction valueFunction,
SerializableSupplier aggregateFunctionSupplier) {
@SuppressWarnings("unchecked")
Class classSubscription = (Class) keyFunction.method().getDeclaringClass();
return subscribe(classSubscription).groupBy(keyFunction, valueFunction, aggregateFunctionSupplier);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy