All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.rahulsom.grooves.queries.internal.Utils Maven / Gradle / Ivy

package com.github.rahulsom.grooves.queries.internal;

import com.github.rahulsom.grooves.api.AggregateType;
import com.github.rahulsom.grooves.api.events.BaseEvent;
import com.github.rahulsom.grooves.api.events.DeprecatedBy;
import com.github.rahulsom.grooves.api.snapshots.internal.BaseSnapshot;
import io.reactivex.Flowable;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import static io.reactivex.Flowable.*;

/**
 * Utility objects and methods to help with Queries.
 *
 * @author Rahul Somasunderam
 */
public class Utils {

    private static final Collector JOIN_EVENT_IDS =
            Collectors.joining(", ");

    private static final Collector JOIN_EVENTS =
            Collectors.joining(",\n    ", "[\n    ", "\n]");

    private Utils() {
    }

    /**
     * Returns a snapshot or redirects to its deprecator.
     *
     * @param redirect           Whether a redirect is desirable
     * @param events             The sequence of events
     * @param it                 The snapshot
     * @param redirectedSnapshot A computation for the redirected snapshot
     * @param         The type of the snapshot
     * @param            The type of the event
     *
     * @return An observable of a snapshot.
     */
    @NotNull public static <
            AggregateIdT,
            AggregateT extends AggregateType,
            EventIdT,
            EventT extends BaseEvent,
            SnapshotIdT,
            SnapshotT extends BaseSnapshot
            > Flowable returnOrRedirect(
            boolean redirect,
            @NotNull List events,
            @NotNull SnapshotT it,
            @NotNull Supplier> redirectedSnapshot) {
        final EventT lastEvent =
                events.isEmpty() ? null : events.get(events.size() - 1);

        final boolean redirectToDeprecator =
                lastEvent != null
                        && lastEvent instanceof DeprecatedBy
                        && redirect;

        return fromPublisher(it.getDeprecatedByObservable())
                .flatMap(deprecatedBy -> redirectToDeprecator ? redirectedSnapshot.get() : just(it))
                .defaultIfEmpty(it);

    }

    /**
     * Computes forward only events. This could mean cancelling out events with their reverts
     * within a list, or sometimes, invoking the supplier of fallback events to get events.
     *
     * @param events                    The sequence of events
     * @param executor                  The executor to use for processing events
     * @param fallbackSnapshotAndEvents The fallback supplier
     * @param             The type of {@link AggregateT}'s id
     * @param               The type of Aggregate
     * @param                 The type of {@link EventT}'s id
     * @param                   The type of Event
     * @param              The type of {@link SnapshotT}'s id
     * @param                The type of Snapshot
     * @param                   The type of Query
     *
     * @return an observable of forward only events
     */
    @NotNull public static <
            AggregateIdT,
            AggregateT extends AggregateType,
            EventIdT,
            EventT extends BaseEvent,
            SnapshotIdT,
            SnapshotT extends BaseSnapshot,
            QueryT extends BaseQuery
            > Flowable getForwardOnlyEvents(
            @NotNull List events,
            @NotNull Executor executor,
            @NotNull Supplier>>>
                    fallbackSnapshotAndEvents) {
        return executor.applyReverts(fromIterable(events))
                .toList()
                .map(Flowable::just)
                .onErrorReturn(throwable -> executor
                        .applyReverts(
                                fallbackSnapshotAndEvents.get()
                                        .flatMap(it -> fromIterable(it.getSecond()))
                        )
                        .toList().toFlowable()
                )
                .toFlowable()
                .flatMap(it -> it)
                .flatMap(Flowable::fromIterable);
    }

    /**
     * Turns a list of events into a readable log style string.
     *
     * @param events   The list of events
     * @param  The type of events
     *
     * @return A String representation of events
     */
    @NotNull public static  String stringify(
            @NotNull List events) {
        return events.stream()
                .map(EventT::toString)
                .collect(JOIN_EVENTS);
    }

    /**
     * Turns a list of events into a readable list of ids.
     *
     * @param events   The list of events
     * @param  The type of events
     *
     * @return A String representation of events
     */
    @NotNull static  String ids(
            @NotNull List events) {
        return events.stream()
                .map(i -> String.valueOf(i.getId()))
                .collect(JOIN_EVENT_IDS);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy