
com.opencredo.concursus.mapping.events.methods.proxying.ProxyingEventBus Maven / Gradle / Ivy
The newest version!
package com.opencredo.concursus.mapping.events.methods.proxying;
import com.opencredo.concursus.domain.events.channels.EventOutChannel;
import com.opencredo.concursus.domain.events.channels.RoutingEventOutChannel;
import com.opencredo.concursus.domain.events.dispatching.EventBus;
import com.opencredo.concursus.domain.events.state.StateBuilder;
import com.opencredo.concursus.domain.functional.Consumers;
import com.opencredo.concursus.mapping.events.methods.state.DispatchingStateBuilder;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
* An {@link EventBus} that generates proxies for event-emitter interfaces.
*/
public interface ProxyingEventBus extends EventBus {
/**
* Create a {@link ProxyingEventBus} that dispatches events via the supplied {@link EventBus}
* @param eventBus The {@link EventBus} to dispatch events to.
* @return The constructed {@link ProxyingEventBus}.
*/
static ProxyingEventBus proxying(EventBus eventBus) {
return eventBus::startBatch;
}
/**
* Create a proxy instance of the supplied interface, and pass it to the supplied {@link Consumer} to emit events.
* @param klass The interface to proxy.
* @param dispatcherConsumer The {@link Consumer} that will use the proxy object to emit events.
* @param The type of the proxy object.
*/
default void dispatch(Class klass, Consumer dispatcherConsumer) {
dispatch(Consumers.transform(
dispatcherConsumer,
eventConsumer -> EventEmittingProxy.proxying(eventConsumer, klass)));
}
/**
* Create proxy instances of the supplied interfaces, and pass them to the supplied {@link BiConsumer} to emit events.
* @param leftKlass The "left" interface to proxy.
* @param rightKlass The "right" interface to proxy.
* @param dispatchersConsumer The {@link BiConsumer} that will use the proxy objects to emit events.
* @param The type of the "left" proxy object.
* @param The type of the "right" proxy object.
*/
default void dispatch(Class leftKlass, Class rightKlass, BiConsumer dispatchersConsumer) {
dispatch(eventConsumer -> dispatchersConsumer.accept(
EventEmittingProxy.proxying(eventConsumer, leftKlass),
EventEmittingProxy.proxying(eventConsumer, rightKlass)
));
}
/**
* Get a proxy instance of the supplied interface that will create and complete a distinct batch containing a single
* event for each event-emitting method invocation.
* @param klass The interface to proxy.
* @param The type of the proxy object.
* @return The constructed proxy object.
*/
default T getDispatcherFor(Class klass) {
return EventEmittingProxy.proxying(this, klass);
}
/**
* Create a copy of this event bus that additionally sends events to the supplied state instance on batch completion.
* @param stateInstance The state instance to send events to.
* @param busConsumer A {@link Consumer} that will use the subscribed bus.
* @param The type of the state instance.
*/
default void updating(S stateInstance, Consumer busConsumer) {
updating(stateInstance.getClass(), stateInstance, busConsumer);
}
/**
* Create a copy of this event bus that additionally sends events to the supplied state instance on batch completion.
* @param stateClass The class of the state instance.
* @param stateInstance The state instance to send events to.
* @param busConsumer A {@link Consumer} that will use the subscribed bus.
* @param The type of the state instance.
*/
default void updating(Class extends S> stateClass, S stateInstance, Consumer busConsumer) {
StateBuilder stateBuilder = DispatchingStateBuilder.dispatchingTo(stateClass, stateInstance);
notifying(stateBuilder.toEventsOutChannel(), Consumers.transform(busConsumer, ProxyingEventBus::proxying));
}
/**
* Create a copy of this event bus that additionally sends events to the supplied state class on batch completion.
* @param stateClass The class of the state instance.
* @param busConsumer A {@link Consumer} that will use the subscribed bus.
* @param The type of the state instance.
* @return The constructed state, if present.
*/
default Optional creating(Class extends S> stateClass, Consumer busConsumer) {
StateBuilder stateBuilder = DispatchingStateBuilder.dispatchingTo(stateClass);
notifying(stateBuilder.toEventsOutChannel(), Consumers.transform(busConsumer, ProxyingEventBus::proxying));
return stateBuilder.get();
}
/**
* Create a copy of this event bus that additionally sends events to the supplied state objects (mapped by
* aggregate id) on batch completion.
* @param stateObjectsById The state objects to send events to on batch completion.
* @param busConsumer A {@link Consumer} that will use the subscribed bus.
*/
default void updating(Map stateObjectsById, Consumer busConsumer) {
EventOutChannel outChannel = RoutingEventOutChannel.routingWith(stateObjectsById.entrySet().stream()
.collect(Collectors.toMap(
Entry::getKey,
e -> DispatchingStateBuilder.dispatchingTo(e.getValue()))));
notifying(outChannel.toEventsOutChannel(), Consumers.transform(busConsumer, ProxyingEventBus::proxying));
}
/**
* Create a copy of this event bus that additionally sends events intended for the supplied state object to
* that object on batch completion. Use this when you will generate additional events that should not be routed
* to the state object.
* @param aggregateId The state object's aggregate id. Events not for this aggregate will not be routed to the object.
* @param stateInstance The state instance to route events to.
* @param busConsumer A {@link Consumer} that will use the subscribed bus.
* @param The type of the state instance.
*/
default void updating(String aggregateId, S stateInstance, Consumer busConsumer) {
StateBuilder stateBuilder = DispatchingStateBuilder.dispatchingTo(stateInstance);
notifying(events -> events.stream()
.filter(event -> event.getAggregateId().getId().equals(aggregateId))
.forEach(stateBuilder),
Consumers.transform(busConsumer, ProxyingEventBus::proxying));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy