Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.fluxtion.runtime.StaticEventProcessor 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.runtime;
import com.fluxtion.runtime.annotations.OnEventHandler;
import com.fluxtion.runtime.annotations.builder.FluxtionIgnore;
import com.fluxtion.runtime.annotations.builder.Inject;
import com.fluxtion.runtime.audit.*;
import com.fluxtion.runtime.audit.EventLogControlEvent.LogLevel;
import com.fluxtion.runtime.dataflow.FlowFunction;
import com.fluxtion.runtime.event.Signal;
import com.fluxtion.runtime.input.EventFeed;
import com.fluxtion.runtime.input.SubscriptionManager;
import com.fluxtion.runtime.lifecycle.Lifecycle;
import com.fluxtion.runtime.node.EventHandlerNode;
import com.fluxtion.runtime.node.InstanceSupplier;
import com.fluxtion.runtime.output.SinkDeregister;
import com.fluxtion.runtime.output.SinkRegistration;
import com.fluxtion.runtime.service.Service;
import com.fluxtion.runtime.service.ServiceRegistry;
import com.fluxtion.runtime.time.ClockStrategy;
import java.util.Map;
import java.util.function.*;
/**
* Processes events of any type and dispatches to registered {@link EventHandlerNode}
* and methods annotated with {@link OnEventHandler}. An subclass of a StaticEventProcessor is
* the product of running the event stream compiler on user input. On receipt of an event
* the processor selects an execution path that comprises a set of application nodes that
* have a reference to an incoming {@link OnEventHandler} for the specific event.
*
* The StaticEventProcessor
* has the following functionality:
*
*
* StaticEventProcessor process events of multiple type in a predictable order
* Application classes are nodes managed by StaticEventProcessor and are notified in a predictable manner when an event is processed
* An execution path is the set of connected nodes to a matching {@link OnEventHandler} for the incoming event
* Nodes on the execution path are invoked in topological order, where object reference determine precedence
* The root of the execution path is an {@link OnEventHandler}
* Dispatches events based on type to the correct handler
* Optional String or int filtering can be supplied to narrow the handler selection in conjunction with event type
* An execution path that is unique for the Event and filter is invoked when an event is received.
* All node instances are created and managed by StaticEventProcessor
*
* starting point of event dispatch
*
* @author Greg Higgins
*/
public interface StaticEventProcessor extends ServiceRegistry, NodeDiscovery {
@FluxtionIgnore
StaticEventProcessor NULL_EVENTHANDLER = e -> {
};
BooleanSupplier ALWAYS_FALSE = () -> false;
/**
* The user can pass in a map of values to this instance. The map will be available in the graph by injecting
* an {@link EventProcessorContext}.
*
*
* {@literal @}Inject
* public EventProcessorContext context;
*
*
*
* Calling this method before {@link Lifecycle#init()} will ensure all the nodes
* see the context when their {@link com.fluxtion.runtime.annotations.Initialise} annotated methods are invoked
*/
default void setContextParameterMap(Map newContextMapping) {
throw new UnsupportedOperationException("this StaticEventProcessor does not accept updated context map");
}
/**
* inject an instance into the running instance, is available via:
* {@link InstanceSupplier}
*
* Can also be accessed via {@link EventProcessorContext#getInjectedInstance(Class)}
* Can also be accessed via {@link EventProcessorContext#getInjectedInstanceAllowNull(Class)}
*
* @param instance the instance to inject
*/
@SuppressWarnings("unckecked")
default void injectInstance(T instance) {
injectInstance(instance, ((Class) instance.getClass()));
}
/**
* inject an instance into the running instance with a name qualifier, is available via:
* {@link InstanceSupplier}. Set the qualifier of the injected with {@link Inject#instanceName()}
*
* Can also be accessed via {@link EventProcessorContext#getInjectedInstance(Class)}
* Can also be accessed via {@link EventProcessorContext#getInjectedInstanceAllowNull(Class)}
*
* @param instance the instance to inject
* @param name the qualifying name of the instance to inject
*/
default void injectNamedInstance(Object instance, String name) {
addContextParameter(instance.getClass().getCanonicalName() + "_" + name, instance);
}
/**
* inject an instance into the running instance with a name qualifier, is available via:
* {@link InstanceSupplier}.
* Set the injected type supplied to the EventProcessor
*
* Can also be accessed via {@link EventProcessorContext#getInjectedInstance(Class)}
* Can also be accessed via {@link EventProcessorContext#getInjectedInstanceAllowNull(Class)}
*
* @param instance the instance to inject
* @param exposedType The type to make available at the injection site
*/
default void injectInstance(S instance, Class exposedType) {
addContextParameter(exposedType.getCanonicalName(), instance);
}
/**
* inject an instance into the running instance with a name qualifier, is available via:
* {@link InstanceSupplier}.
* Set the name with {@link Inject#instanceName()}
* Set the injected type supplied to the EventProcessor
*
* Can also be accessed via {@link EventProcessorContext#getInjectedInstance(Class, String)}
* Can also be accessed via {@link EventProcessorContext#getInjectedInstanceAllowNull(Class, String)}
*
* @param instance the instance to inject
* @param exposedType The type to make available at the injection sit
* @param name the qualifying name of the instance to inject
*/
default void injectNamedInstance(S instance, Class exposedType, String name) {
addContextParameter(exposedType.getCanonicalName() + "_" + name, instance);
}
default void addContextParameter(Object key, Object value) {
throw new UnsupportedOperationException("this StaticEventProcessor does not accept updates to context map");
}
/**
* Called when a new event e is ready to be processed. Calls a {@link #triggerCalculation()} first if any events
* have been buffered.
*
* @param e the {@link com.fluxtion.runtime.event.Event Event} to process.
*/
void onEvent(Object e);
default void onEvent(byte value) {
onEvent((Byte) value);
}
default void onEvent(char value) {
onEvent((Character) value);
}
default void onEvent(short value) {
onEvent((Short) value);
}
default void onEvent(int value) {
onEvent((Integer) value);
}
default void onEvent(float value) {
onEvent((Float) value);
}
default void onEvent(double value) {
onEvent((Double) value);
}
default void onEvent(long value) {
onEvent((Long) value);
}
/**
* Buffers an event as part of a transaction only EventHandler methods are invoked, no OnTrigger methods are
* processed. EventHandlers are marked as dirty ready for {@link #triggerCalculation()} to invoke a full event cycle
*
* @param event
*/
default void bufferEvent(Object event) {
throw new UnsupportedOperationException("buffering of events not supported");
}
default void bufferEvent(byte value) {
bufferEvent((Byte) value);
}
default void bufferEvent(char value) {
bufferEvent((Character) value);
}
default void bufferEvent(short value) {
bufferEvent((Short) value);
}
default void bufferEvent(int value) {
bufferEvent((Integer) value);
}
default void bufferEvent(float value) {
bufferEvent((Float) value);
}
default void bufferEvent(double value) {
bufferEvent((Double) value);
}
default void bufferEvent(long value) {
bufferEvent((Long) value);
}
/**
* Runs a graph calculation cycle invoking any {@link com.fluxtion.runtime.annotations.OnTrigger} methods whose
* parents are marked dirty. Used in conjunction with {@link #bufferEvent(Object)}, this method marks event handlers
* as dirty.
*/
default void triggerCalculation() {
throw new UnsupportedOperationException("buffering of events not supported");
}
default void addSink(String id, Consumer sink) {
onEvent(SinkRegistration.sink(id, sink));
}
default void addIntSink(String id, IntConsumer sink) {
onEvent(SinkRegistration.intSink(id, sink));
}
default void addDoubleSink(String id, DoubleConsumer sink) {
onEvent(SinkRegistration.doubleSink(id, sink));
}
default void addLongSink(String id, LongConsumer sink) {
onEvent(SinkRegistration.longSink(id, sink));
}
default void removeSink(String id) {
onEvent(SinkDeregister.sink(id));
}
/**
* Publishes an instance wrapped in a Signal and applies a class filter to the published signal
*
* receiving an event callback in a node
*
* {@literal @}OnEventHandler(filterStringFromClass = Date.class)
* public void handleEvent(Signal date) {
* count++;
* }
*
*
*
* publishing:
*
* eventProcessorInstance.publishObjectSignal(new Date());
*
*
* @param instance
* @param
*/
default void publishObjectSignal(T instance) {
onEvent(new Signal<>(instance));
}
default void publishObjectSignal(Class filterClass, T instance) {
onEvent(new Signal<>(filterClass, instance));
}
default void publishSignal(String filter) {
publishSignal(filter, new Object());
}
default void publishSignal(String filter, T value) {
onEvent(new Signal<>(filter, value));
}
default void publishSignal(String filter, int value) {
onEvent(Signal.intSignal(filter, value));
}
default void publishIntSignal(String filter, int value) {
publishSignal(filter, value);
}
default void publishSignal(String filter, double value) {
onEvent(Signal.doubleSignal(filter, value));
}
default void publishDoubleSignal(String filter, double value) {
publishSignal(filter, value);
}
default void publishSignal(String filter, long value) {
onEvent(Signal.longSignal(filter, value));
}
default void publishLongSignal(String filter, long value) {
publishSignal(filter, value);
}
default T getNodeById(String id) throws NoSuchFieldException {
throw new NoSuchFieldException(id);
}
default T getStreamed(String name) throws NoSuchFieldException {
FlowFunction stream = getNodeById(name);
return stream.get();
}
@SuppressWarnings("unchecked")
default A getAuditorById(String id) throws NoSuchFieldException, IllegalAccessException {
return getNodeById(id);
}
default void addEventFeed(EventFeed eventProcessorFeed) {
throw new UnsupportedOperationException("addEventProcessorFeed not implemented");
}
default void removeEventFeed(EventFeed eventProcessorFeed) {
throw new UnsupportedOperationException("removeEventProcessorFeed not implemented");
}
default void setAuditLogLevel(LogLevel logLevel) {
onEvent(new EventLogControlEvent(logLevel));
}
default void setAuditLogLevel(LogLevel logLevel, String nodeName) {
onEvent(new EventLogControlEvent(nodeName, null, logLevel));
}
default void setAuditLogProcessor(LogRecordListener logProcessor) {
onEvent(new EventLogControlEvent(logProcessor));
}
default void setAuditLogRecordEncoder(LogRecord logRecord) {
onEvent(new EventLogControlEvent(logRecord));
}
default void setAuditTimeFormatter(ObjLongConsumer timeFormatter) {
onEvent(new EventLogControlEvent(timeFormatter));
}
/**
* Attempts to get the last {@link com.fluxtion.runtime.audit.LogRecord} as a String if one is available. Useful
* for error handling if there is a filure in the graph;
*
* @return The last logRecord as a String if it is available
*/
default String getLastAuditLogRecord() {
try {
return this.getNodeById(EventLogManager.NODE_NAME).lastRecordAsString();
} catch (Throwable e) {
return "";
}
}
default void setClockStrategy(ClockStrategy clockStrategy) {
onEvent(ClockStrategy.registerClockEvent(clockStrategy));
}
/**
* Returns an instance of the event processor cast to an interface type. The implemented interfaces of an event processor
* are specified using the com.fluxtion.compiler.EventProcessorConfig#addInterfaceImplementation during the
* building phase of the processor or using the @ExportService annotation.
*
* @param the interface type to cast to
* @return The {@link StaticEventProcessor} cast to an interface
*/
@SuppressWarnings("unchecked")
default T getExportedService() {
return (T) this;
}
/**
* Determines if the event processor exports the service interface. The implemented interfaces of an event processor
* are specified using the com.fluxtion.compiler.EventProcessorConfig#addInterfaceImplementation during the
* building phase of the processor or using the @ExportService annotation.
*
* @param exportedServiceClass the type of service to search for
* @param the interface type to cast to
* @return flag indicating the event processor exports the interface
*/
default boolean exportsService(Class exportedServiceClass) {
T svcExport = getExportedService();
return exportedServiceClass.isInstance(svcExport);
}
/**
* Returns an instance of the event processor cast to an interface type. The implemented interfaces of an event processor
* are specified using the com.fluxtion.compiler.EventProcessorConfig#addInterfaceImplementation during the
* building phase of the processor or using the @ExportService annotation.
*
* @param exportedServiceClass the type of service to search for
* @param the interface type to cast to
* @return The {@link StaticEventProcessor} cast to an interface
*/
default T getExportedService(Class exportedServiceClass) {
return exportsService(exportedServiceClass) ? getExportedService() : null;
}
/**
* Returns an instance of the event processor cast to an interface type, returning a default value if one cannot
* be found
*
* @param exportedServiceClass the type of service to search for
* @param defaultValue default service instance to return if no service is exported
* @param the interface type to cast to
* @return The {@link StaticEventProcessor} cast to an interface
*/
default T getExportedService(Class exportedServiceClass, T defaultValue) {
return exportsService(exportedServiceClass) ? getExportedService() : defaultValue;
}
/**
* Passes the event processor cast to an interface for a consumer to process if the event processor exports service
*
* @param exportedServiceClass the type of service to search for
* @param serviceConsumer service consumer callback, invoked if the service is exported
* @param the interface type to cast to
*/
default void consumeServiceIfExported(Class exportedServiceClass, Consumer serviceConsumer) {
T exportedService = getExportedService(exportedServiceClass);
if (exportedService != null) {
serviceConsumer.accept(exportedService);
}
}
/**
* Register a Consumer that will be called whenever an event is posted to the processor but there are no registered
* event handlers for that type.
*
* @param consumer The Unknown event type handler
* @param The type of the event
*/
default void setUnKnownEventHandler(Consumer consumer) {
}
@Override
default void registerService(Service> service) {
}
@Override
default void deRegisterService(Service> service) {
}
default SubscriptionManager getSubscriptionManager() {
throw new UnsupportedOperationException();
}
}