
com.fluxtion.compiler.builder.dataflow.FlowBuilder Maven / Gradle / Ivy
/*
* Copyright (c) 2025 gregory higgins.
* All rights reserved.
*
* 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.compiler.builder.dataflow;
import com.fluxtion.runtime.EventProcessorBuilderService;
import com.fluxtion.runtime.dataflow.FlowFunction;
import com.fluxtion.runtime.dataflow.FlowSupplier;
import com.fluxtion.runtime.dataflow.TriggeredFlowFunction;
import com.fluxtion.runtime.dataflow.aggregate.AggregateFlowFunction;
import com.fluxtion.runtime.dataflow.aggregate.function.AggregateFlowFunctionWrapper;
import com.fluxtion.runtime.dataflow.aggregate.function.FixSizedSlidingWindow;
import com.fluxtion.runtime.dataflow.aggregate.function.TimedSlidingWindow;
import com.fluxtion.runtime.dataflow.aggregate.function.TumblingWindow;
import com.fluxtion.runtime.dataflow.function.BinaryMapFlowFunction.BinaryMapToRefFlowFunction;
import com.fluxtion.runtime.dataflow.function.*;
import com.fluxtion.runtime.dataflow.function.MapFlowFunction.MapRef2RefFlowFunction;
import com.fluxtion.runtime.dataflow.groupby.*;
import com.fluxtion.runtime.dataflow.helpers.Aggregates;
import com.fluxtion.runtime.dataflow.helpers.Collectors;
import com.fluxtion.runtime.dataflow.helpers.DefaultValue;
import com.fluxtion.runtime.dataflow.helpers.DefaultValue.DefaultValueFromSupplier;
import com.fluxtion.runtime.dataflow.helpers.Mappers;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableBiFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableFunction;
import com.fluxtion.runtime.partition.LambdaReflection.SerializableSupplier;
import java.util.*;
public class FlowBuilder extends AbstractFlowBuilder> implements FlowDataSupplier> {
FlowBuilder(TriggeredFlowFunction eventStream) {
super(eventStream);
EventProcessorBuilderService.service().add(eventStream);
}
@Override
protected FlowBuilder connect(TriggeredFlowFunction stream) {
return new FlowBuilder<>(stream);
}
@Override
protected FlowBuilder connectMap(TriggeredFlowFunction stream) {
return new FlowBuilder<>(stream);
}
@Override
protected FlowBuilder identity() {
return this;
}
public FlowSupplier flowSupplier() {
return eventStream;
}
public FlowBuilder defaultValue(T defaultValue) {
return map(new DefaultValue<>(defaultValue)::getOrDefault);
}
public FlowBuilder defaultValue(SerializableSupplier defaultValue) {
return map(new DefaultValueFromSupplier<>(defaultValue)::getOrDefault);
}
public FlowBuilder lookup(SerializableFunction lookupKeyFunction,
SerializableFunction lookupFunction,
SerializableBiFunction enrichFunction) {
return new FlowBuilder<>(new LookupFlowFunction<>(eventStream, lookupKeyFunction, lookupFunction, enrichFunction));
}
//PROCESSING - START
public FlowBuilder map(SerializableFunction mapFunction) {
return super.mapBase(mapFunction);
}
public FlowBuilder> mapToSet() {
return map(Collectors.toSet());
}
public FlowBuilder> mapToSet(SerializableFunction mapFunction) {
return map(mapFunction).map(Collectors.toSet());
}
public FlowBuilder> mapToList() {
return map(Collectors.toList());
}
public FlowBuilder> mapToCollection() {
return map(Collectors.toCollection());
}
public FlowBuilder> mapToList(SerializableFunction mapFunction) {
return map(mapFunction).map(Collectors.toList());
}
public FlowBuilder> mapToList(int maxElements) {
return map(Collectors.toList(maxElements));
}
public FlowBuilder> mapToList(SerializableFunction mapFunction, int maxElements) {
return map(mapFunction).map(Collectors.toList(maxElements));
}
public FlowBuilder mapBiFunction(SerializableBiFunction int2IntFunction,
FlowBuilder stream2Builder) {
return new FlowBuilder<>(
new BinaryMapToRefFlowFunction<>(
eventStream, stream2Builder.eventStream, int2IntFunction)
);
}
public FlowBuilder merge(FlowBuilder extends T> streamToMerge) {
return new FlowBuilder<>(new MergeFlowFunction<>(eventStream, streamToMerge.eventStream));
}
@SuppressWarnings("unchecked")
public FlowBuilder merge(FlowBuilder extends T> streamToMerge, FlowBuilder extends T>... streamsToMerge) {
List> mergeList = new ArrayList<>();
mergeList.add(eventStream);
mergeList.add(streamToMerge.eventStream);
for (FlowBuilder extends T> flowBuilder : streamsToMerge) {
mergeList.add(flowBuilder.eventStream);
}
return new FlowBuilder<>(new MergeFlowFunction<>(mergeList));
}
public FlowBuilder flatMap(SerializableFunction> iterableFunction) {
return new FlowBuilder<>(new FlatMapFlowFunction<>(eventStream, iterableFunction));
}
public FlowBuilder flatMap(SerializableFunction> iterableFunction, String flatMapCompleteSignal) {
FlatMapFlowFunction> flatMapIteratorFlowFunction = new FlatMapFlowFunction<>(eventStream, iterableFunction);
flatMapIteratorFlowFunction.setFlatMapCompleteSignal(flatMapCompleteSignal);
return new FlowBuilder<>(flatMapIteratorFlowFunction);
}
public FlowBuilder flatMapFromIterator(SerializableFunction> iterableFunction) {
return new FlowBuilder<>(new FlatMapIteratorFlowFunction<>(eventStream, iterableFunction));
}
public FlowBuilder flatMapFromIterator(SerializableFunction> iterableFunction, String flatMapCompleteSignal) {
FlatMapIteratorFlowFunction> flatMapIteratorFlowFunction = new FlatMapIteratorFlowFunction<>(eventStream, iterableFunction);
flatMapIteratorFlowFunction.setFlatMapCompleteSignal(flatMapCompleteSignal);
return new FlowBuilder<>(flatMapIteratorFlowFunction);
}
public FlowBuilder flatMapFromArray(SerializableFunction iterableFunction) {
return new FlowBuilder<>(new FlatMapArrayFlowFunction<>(eventStream, iterableFunction));
}
public FlowBuilder flatMapFromArray(SerializableFunction iterableFunction, String flatMapCompleteSignal) {
FlatMapArrayFlowFunction> flatMapIteratorFlowFunction = new FlatMapArrayFlowFunction<>(eventStream, iterableFunction);
flatMapIteratorFlowFunction.setFlatMapCompleteSignal(flatMapCompleteSignal);
return new FlowBuilder<>(flatMapIteratorFlowFunction);
}
public > FlowBuilder
aggregate(SerializableSupplier aggregateFunction) {
return new FlowBuilder<>(new AggregateFlowFunctionWrapper<>(eventStream, aggregateFunction));
}
public > FlowBuilder
tumblingAggregate(SerializableSupplier aggregateFunction, int bucketSizeMillis) {
return new FlowBuilder<>(
new TumblingWindow<>(eventStream, aggregateFunction, bucketSizeMillis));
}
public > FlowBuilder
slidingAggregate(SerializableSupplier aggregateFunction, int bucketSizeMillis, int bucketsPerWindow) {
return new FlowBuilder<>(
new TimedSlidingWindow<>(eventStream, aggregateFunction, bucketSizeMillis, bucketsPerWindow));
}
public > FlowBuilder
slidingAggregateByCount(SerializableSupplier aggregateFunction, int elementsInWindow) {
return new FlowBuilder<>(
new FixSizedSlidingWindow<>(eventStream, aggregateFunction, elementsInWindow));
}
/**
* Aggregates a flow using a key function to group by and an aggregating function to process new values for a keyed
* bucket.
*
* @param keyFunction The key function that groups and buckets incoming values
* @param valueFunction The value that is extracted from the incoming stream and applied to the aggregating function
* @param aggregateFunctionSupplier A factory that supplies aggregating functions, each function has its own function instance
* @param Value type extracted from the incoming data flow
* @param The type of the key used to group values
* @param The return type of the aggregating function
* @param The aggregating function type
* @return A GroupByFlowBuilder for the aggregated flow
*/
public > GroupByFlowBuilder
groupBy(SerializableFunction keyFunction,
SerializableFunction valueFunction,
SerializableSupplier aggregateFunctionSupplier) {
MapFlowFunction, TriggeredFlowFunction> x = new MapRef2RefFlowFunction<>(eventStream,
new GroupByFlowFunctionWrapper<>(keyFunction, valueFunction, aggregateFunctionSupplier)::aggregate)
.defaultValue(GroupBy.emptyCollection());
return new GroupByFlowBuilder<>(x);
}
/**
* Specialisation of groupBy where the value is the identity of the incoming data flow
*
* @param keyFunction The key function that groups and buckets incoming values
* @param aggregateFunctionSupplier A factory that supplies aggregating functions, each function has its own function instance
* @param The type of the key used to group values
* @param The return type of the aggregating function
* @param The aggregating function type
* @return A GroupByFlowBuilder for the aggregated flow
* @see FlowBuilder#groupBy(SerializableFunction, SerializableFunction, SerializableSupplier)
*/
public > GroupByFlowBuilder
groupBy(SerializableFunction keyFunction, SerializableSupplier aggregateFunctionSupplier) {
return groupBy(keyFunction, Mappers::identity, aggregateFunctionSupplier);
}
/**
* Specialisation of groupBy where the output of the groupBy is the last value received for a bucket. The value is
* extracted using the value function
*
* @param keyFunction The key function that groups and buckets incoming values
* @param valueFunction The value that is extracted from the incoming stream and applied to the aggregating function
* @param Value type extracted from the incoming data flow
* @param The type of the key used to group values
* @return A GroupByFlowBuilder for the aggregated flow
* @see FlowBuilder#groupBy(SerializableFunction, SerializableFunction, SerializableSupplier)
*/
public GroupByFlowBuilder groupBy(
SerializableFunction keyFunction,
SerializableFunction valueFunction) {
return groupBy(keyFunction, valueFunction, Aggregates.identityFactory());
}
/**
* Specialisation of groupBy where the output of the groupBy is the last value received for a bucket, where
* the value is the identity of the incoming data flow
*
* @param keyFunction The key function that groups and buckets incoming values
* @param The type of the key used to group values
* @return A GroupByFlowBuilder for the aggregated flow
*/
public GroupByFlowBuilder groupBy(SerializableFunction keyFunction) {
return groupBy(keyFunction, Mappers::identity);
}
/**
* Creates a GroupByFlowBuilder using a compound key created by a set of method reference accessors to for the value.
* The value is the last value supplied
*
* @param keyFunctions multi arg key accessors
* @return GroupByFlowBuilder keyed on properties
*/
@SafeVarargs
public final GroupByFlowBuilder, T> groupByFields(
SerializableFunction... keyFunctions) {
return groupBy(GroupByKey.build(keyFunctions));
}
/**
* Aggregates a flow using a key to group by and an aggregating function to process new values for a keyed
* bucket. The key is a compound key created by a set of method reference accessors to for the value.
*
* @param aggregateFunctionSupplier A factory that supplies aggregating functions, each function has its own function instance
* @param keyFunctions multi arg key accessors
* @param The return type of the aggregating function
* @param The aggregating function type
* @return A GroupByFlowBuilder for the aggregated flow
* @see FlowBuilder#groupBy(SerializableFunction, SerializableFunction, SerializableSupplier)
*/
@SafeVarargs
public final > GroupByFlowBuilder, A> groupByFieldsAggregate(
SerializableSupplier aggregateFunctionSupplier,
SerializableFunction... keyFunctions) {
return groupBy(GroupByKey.build(keyFunctions), aggregateFunctionSupplier);
}
/**
* Creates a GroupByFlowBuilder using a compound key created by a set of method reference accessors to for the key
* The value is extracted from the input using the value function
*
* @param valueFunction the value that will be stored in the groupBy
* @param keyFunctions multi arg key accessors
* @return GroupByFlowBuilder keyed on properties
*/
@SafeVarargs
public final GroupByFlowBuilder, V> groupByFieldsAndGet(
SerializableFunction valueFunction,
SerializableFunction... keyFunctions) {
return groupBy(GroupByKey.build(keyFunctions), valueFunction);
}
/**
* Creates a GroupByFlowBuilder using a compound key created by a set of method reference accessors to for the key
* The value is extracted from the input using the value function and is used as an input to the aggregating function
*
* @param valueFunction the value that will be stored in the groupBy
* @param aggregateFunctionSupplier A factory that supplies aggregating functions, each function has its own function instance
* @param keyFunctions multi arg key accessors
* @param Value type extracted from the incoming data flow
* @param The return type of the aggregating function
* @param The aggregating function type
* @return A GroupByFlowBuilder for the aggregated flow
* @see FlowBuilder#groupBy(SerializableFunction, SerializableFunction, SerializableSupplier)
*/
@SafeVarargs
public final > GroupByFlowBuilder, A> groupByFieldsGetAndAggregate(
SerializableFunction valueFunction,
SerializableSupplier aggregateFunctionSupplier,
SerializableFunction... keyFunctions) {
return groupBy(GroupByKey.build(keyFunctions), valueFunction, aggregateFunctionSupplier);
}
public GroupByFlowBuilder> groupByToList(SerializableFunction keyFunction) {
return groupBy(keyFunction, Mappers::identity, Collectors.listFactory());
}
/**
* 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
* @return The GroupByFlowBuilder that represents the multimap
*/
@SafeVarargs
public final GroupByFlowBuilder, List> groupByToList(SerializableFunction... keyFunctions) {
return groupByFieldsAggregate(Collectors.listFactory(), keyFunctions);
}
public GroupByFlowBuilder> groupByToList(
SerializableFunction keyFunction, SerializableFunction valueFunction) {
return groupBy(keyFunction, valueFunction, Collectors.listFactory());
}
public GroupByFlowBuilder> groupByToSet(SerializableFunction keyFunction) {
return groupBy(keyFunction, Mappers::identity, Collectors.setFactory());
}
/**
* 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
* @return The GroupByFlowBuilder that represents the multimap
*/
@SafeVarargs
public final GroupByFlowBuilder, Set> groupByToSet(SerializableFunction... keyFunctions) {
return groupByFieldsAggregate(Collectors.setFactory(), keyFunctions);
}
public GroupByFlowBuilder> groupByToSet(SerializableFunction keyFunction, SerializableFunction valueFunction) {
return groupBy(keyFunction, valueFunction, Collectors.setFactory());
}
public GroupByFlowBuilder> groupByToList(
SerializableFunction keyFunction,
int maxElementsInList) {
return groupBy(keyFunction, Mappers::identity, Collectors.listFactory(maxElementsInList));
}
public > GroupByFlowBuilder
groupByTumbling(SerializableFunction keyFunction,
SerializableFunction valueFunction,
SerializableSupplier aggregateFunctionSupplier,
int bucketSizeMillis) {
return new GroupByFlowBuilder<>(new GroupByTumblingWindow<>(
eventStream,
aggregateFunctionSupplier,
keyFunction,
valueFunction,
bucketSizeMillis
));
}
public GroupByFlowBuilder
groupByTumbling(SerializableFunction keyFunction,
SerializableFunction valueFunction,
int bucketSizeMillis) {
return groupByTumbling(keyFunction, valueFunction, Aggregates.identityFactory(), bucketSizeMillis);
}
public > GroupByFlowBuilder
groupBySliding(SerializableFunction keyFunction,
SerializableFunction valueFunction,
SerializableSupplier aggregateFunctionSupplier,
int bucketSizeMillis,
int numberOfBuckets) {
return new GroupByFlowBuilder<>(new GroupByTimedSlidingWindow<>(
eventStream,
aggregateFunctionSupplier,
keyFunction,
valueFunction,
bucketSizeMillis,
numberOfBuckets
));
}
public GroupByFlowBuilder
groupBySliding(SerializableFunction keyFunction,
SerializableFunction valueFunction,
int bucketSizeMillis,
int numberOfBuckets) {
return groupBySliding(keyFunction, valueFunction, Aggregates.identityFactory(), bucketSizeMillis, numberOfBuckets);
}
public > GroupByFlowBuilder
groupBySliding(SerializableFunction keyFunction,
SerializableSupplier aggregateFunctionSupplier,
int bucketSizeMillis,
int numberOfBuckets) {
return new GroupByFlowBuilder<>(new GroupByTimedSlidingWindow<>(
eventStream,
aggregateFunctionSupplier,
keyFunction,
Mappers::identity,
bucketSizeMillis,
numberOfBuckets
));
}
public > Z mapOnNotify(I target) {
return super.mapOnNotifyBase(target);
}
/*
Done:
================
add peek to primitive streams
Use transient reference in any stream that has an instance function reference. Remove anchor
add standard predicates for primitives
De-dupe filter
mapOnNotify
optional:
================
add peek functions to support log and audit helpers
zip - really just a stateful function
*/
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy