com.opencredo.concourse.domain.events.sourcing.EventReplayer Maven / Gradle / Ivy
package com.opencredo.concourse.domain.events.sourcing;
import com.opencredo.concourse.domain.events.Event;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Organises a collection of {@link Event}s for replaying or collection in the desired order.
*/
public final class EventReplayer {
/**
* Create an {@link EventReplayer} replaying the supplied {@link Event}s.
* @param events The {@link Event}s to replay.
* @return The constructed {@link EventReplayer}.
*/
public static EventReplayer of(List events) {
return new EventReplayer(events, List::stream, Optional.empty());
}
private final List events;
private final Function, Stream> orderedStreamer;
private final Optional> filter;
private EventReplayer(List events, Function, Stream> orderedStreamer, Optional> filter) {
this.events = events;
this.orderedStreamer = orderedStreamer;
this.filter = filter;
}
/**
* Set the order to ascending.
* @return An {@link EventReplayer} replaying events in time-ascending order.
*/
public EventReplayer inAscendingOrder() {
return new EventReplayer(events, this::reverseStream, filter);
}
/**
* Set the order to ascending, sorted by the supplied {@link Comparator}.
* @param comparator The {@link Comparator} comparator to use to sort events.
* @return An {@link EventReplayer} replaying events in time-ascending order.
*/
public EventReplayer inAscendingOrder(Comparator comparator) {
return new EventReplayer(events, eventList -> reverseStream(eventList).sorted(comparator), filter);
}
/**
* Set the order to descending.
* @return An {@link EventReplayer} replaying events in time-descending order.
*/
public EventReplayer inDescendingOrder() {
return new EventReplayer(events, List::stream, filter);
}
/**
* Set the order to descending, sorted by the supplied {@link Comparator}.
* @param comparator The {@link Comparator} comparator to use to sort events.
* @return An {@link EventReplayer} replaying events in time-descending order.
*/
public EventReplayer inDescendingOrder(Comparator comparator) {
return new EventReplayer(events, eventList -> eventList.stream().sorted(comparator.reversed()), filter);
}
private Stream reverseStream(List eventList) {
return StreamSupport.stream(ReverseListSpliterator.over(eventList), false);
}
/**
* Apply a filter to the events
* @param predicate The {@link Predicate} to use to filter events.
* @return An {@link EventReplayer} replaying events which match the filter.
*/
public EventReplayer filter(Predicate predicate) {
return new EventReplayer(events, orderedStreamer, Optional.of(predicate));
}
/**
* Replay only the first {@link Event} in the sequence.
* @param consumer The event consumer to replay the event to.
*/
public void replayFirst(Consumer consumer) {
stream().findFirst().ifPresent(consumer);
}
private Stream stream() {
return filter.map(orderedStreamer.apply(events)::filter)
.orElseGet(() -> orderedStreamer.apply(events));
}
/**
* Replay all of the {@link Event}s in the sequence.
* @param consumer The event consumer to replay the events to.
*/
public void replayAll(Consumer consumer) {
stream().forEach(consumer);
}
/**
* Collect only the first {@link Event} in the sequence.
* @param collector The collector to collect the event with.
* @param The type of value returned by the collector.
* @return The collected value, or {@link Optional}::empty if the sequence is empty.
*/
public Optional collectFirst(Function, Consumer> collector) {
AtomicReference ref = new AtomicReference<>();
Consumer consumer = collector.apply(ref::set);
replayFirst(consumer);
return Optional.ofNullable(ref.get());
}
/**
* Collect all of the {@link Event}s in the sequence.
* @param collector The collector to collect the events with.
* @param The type of value returned by the collector.
* @return The collected values.
*/
public List collectAll(Function, Consumer> collector) {
List result = new ArrayList<>();
Consumer consumer = collector.apply(result::add);
replayAll(consumer);
return result;
}
/**
* Collect all of the {@link Event}s in the sequence into a {@link List}.
* @return The collected events.
*/
public List toList() {
return stream().collect(Collectors.toList());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy