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

org.elder.sourcerer.DefaultImmutableAggregate Maven / Gradle / Ivy

package org.elder.sourcerer;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import org.elder.sourcerer.functions.AppendHandler;
import org.elder.sourcerer.functions.AppendHandlerSingle;
import org.elder.sourcerer.functions.ParameterizedAppendHandler;
import org.elder.sourcerer.functions.ParameterizedAppendHandlerSingle;
import org.elder.sourcerer.functions.ParameterizedPojoUpdateHandler;
import org.elder.sourcerer.functions.ParameterizedPojoUpdateHandlerSingle;
import org.elder.sourcerer.functions.ParameterizedUpdateHandler;
import org.elder.sourcerer.functions.ParameterizedUpdateHandlerAggregate;
import org.elder.sourcerer.functions.ParameterizedUpdateHandlerSingle;
import org.elder.sourcerer.functions.PojoUpdateHandler;
import org.elder.sourcerer.functions.PojoUpdateHandlerSingle;
import org.elder.sourcerer.functions.UpdateHandler;
import org.elder.sourcerer.functions.UpdateHandlerAggregate;
import org.elder.sourcerer.functions.UpdateHandlerSingle;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Stream;

/**
 * Default sourcerer implementation of ImmutableAggregate.
 */
public class DefaultImmutableAggregate
        implements ImmutableAggregate {
    private final AggregateProjection projection;
    private final String id;
    private final int sourceVersion;
    private final TState state;
    private final ImmutableList appliedEvents;

    DefaultImmutableAggregate(
            @NotNull final AggregateProjection projection,
            @NotNull final String id,
            final int sourceVersion,
            @NotNull final TState state,
            @NotNull final List events) {
        Preconditions.checkNotNull(projection);
        Preconditions.checkNotNull(id);
        Preconditions.checkNotNull(events);
        this.projection = projection;
        this.id = id;
        this.sourceVersion = sourceVersion;
        this.state = state;
        this.appliedEvents = ImmutableList.copyOf(events);
    }

    /**
     * Creates a new immutable aggregate from the given projection, initialized with the empty
     * value as defined by the projection, no events, and a "not created" version.
     *
     * @param projection The projection used to apply events to the state of the aggregate.
     * @param id         The id of the aggregate.
     * @return A new immutable aggregate with empty state and "not created" version.
     */
    public static  DefaultImmutableAggregate createNew(
            final AggregateProjection projection,
            final String id) {
        return new DefaultImmutableAggregate<>(
                projection,
                id,
                Aggregate.VERSION_NOT_CREATED,
                projection.empty(),
                ImmutableList.of());
    }

    /**
     * Creates a new immutable aggregate state from the given projection, current state and version.
     *
     * @param projection    The projection used to apply events to the state of the aggregate.
     * @param id            The id of the aggregate.
     * @param sourceVersion The current version of the aggregate, in the state provided.
     * @param state         The current state of the aggregate.
     * @return A new immutable aggregate with the provided current state.
     */
    public static  DefaultImmutableAggregate fromExisting(
            final AggregateProjection projection,
            final String id,
            final int sourceVersion,
            final TState state) {
        return new DefaultImmutableAggregate<>(
                projection,
                id,
                sourceVersion,
                state,
                ImmutableList.of());
    }

    @Override
    @NotNull
    @Contract(pure = true)
    public String id() {
        return id;
    }

    @Override
    public int sourceVersion() {
        return sourceVersion;
    }

    @Override
    @NotNull
    @Contract(pure = true)
    public TState state() {
        return state;
    }

    @Override
    @NotNull
    @Contract(pure = true)
    public List events() {
        return appliedEvents;
    }

    @Override
    public ImmutableAggregate toImmutable() {
        return this;
    }

    @Override
    public MutableAggregate toMutable() {
        return new DefaultMutableAggregate<>(
                projection,
                id,
                sourceVersion,
                state,
                appliedEvents);
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(@NotNull final TEvent event) {
        Preconditions.checkNotNull(event);
        @NotNull TState newState = projection.apply(id, state, event);
        return new DefaultImmutableAggregate<>(
                projection,
                id,
                sourceVersion,
                newState,
                ImmutableList.builder().addAll(appliedEvents).add(event).build());
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final Iterable events) {
        Preconditions.checkNotNull(events);
        @NotNull TState newState = projection.apply(id, state, events);
        return new DefaultImmutableAggregate<>(
                projection,
                id,
                sourceVersion,
                newState,
                ImmutableList.builder().addAll(appliedEvents).addAll(events).build());
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final AppendHandler handler) {
        return this.apply(handler.execute());
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final AppendHandlerSingle handler) {
        return this.apply(handler.executeSingle());
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedAppendHandler handler,
            final TParam params) {
        return this.apply(handler.execute(params));
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedAppendHandlerSingle handler,
            final TParam params) {
        return this.apply(handler.executeSingle(params));
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final UpdateHandler handler) {
        return this.apply(handler.execute(this));
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final UpdateHandlerSingle handler) {
        return this.apply(handler.executeSingle(this));
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final UpdateHandlerAggregate handler) {
        return handler.executeWithAggregate(this).toImmutable();
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final PojoUpdateHandler handler) {
        return this.apply(handler.execute(this.state));
    }

    @NotNull
    @Override
    public ImmutableAggregate apply(
            @NotNull final PojoUpdateHandlerSingle handler) {
        return this.apply(handler.executeSingle(this.state));
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedUpdateHandler handler,
            final TParam params) {
        return this.apply(handler.execute(this, params));
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedUpdateHandlerSingle handler,
            final TParam params) {
        return this.apply(handler.executeSingle(this, params));
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedUpdateHandlerAggregate handler,
            final TParam params) {
        return handler.executeWithAggregate(this, params).toImmutable();
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedPojoUpdateHandler handler,
            final TParam params) {
        return this.apply(handler.execute(this.state, params));
    }

    @NotNull
    @Override
    public  ImmutableAggregate apply(
            @NotNull final ParameterizedPojoUpdateHandlerSingle handler,
            final TParam params) {
        return this.apply(handler.executeSingle(this.state, params));
    }

    @NotNull
    @Override
    public  ImmutableAggregate fold(
            @NotNull final ParameterizedUpdateHandler handler,
            @NotNull final Stream params) {
        return foldLeft(
                params,
                (ImmutableAggregate) this,
                (state, param) -> state.apply(handler, param));
    }

    @NotNull
    @Override
    public  ImmutableAggregate fold(
            @NotNull final ParameterizedUpdateHandlerSingle handler,
            @NotNull final Stream params) {
        return foldLeft(
                params,
                (ImmutableAggregate) this,
                (state, param) -> state.apply(handler, param));
    }

    @NotNull
    @Override
    public  ImmutableAggregate fold(
            @NotNull final ParameterizedUpdateHandlerAggregate handler,
            @NotNull final Stream params) {
        return foldLeft(
                params,
                (ImmutableAggregate) this,
                (state, param) -> state.apply(handler, param));
    }

    @NotNull
    @Override
    public  ImmutableAggregate fold(
            @NotNull final ParameterizedPojoUpdateHandler handler,
            @NotNull final Stream params) {
        return foldLeft(
                params,
                (ImmutableAggregate) this,
                (state, param) -> state.apply(handler, param));
    }

    @NotNull
    @Override
    public  ImmutableAggregate fold(
            @NotNull final ParameterizedPojoUpdateHandlerSingle handler,
            @NotNull final Stream params) {
        return foldLeft(
                params,
                (ImmutableAggregate) this,
                (state, param) -> state.apply(handler, param));
    }

    @NotNull
    @Override
    public ImmutableAggregate rebase(final int version) {
        return new DefaultImmutableAggregate<>(
                projection,
                id,
                version,
                state,
                ImmutableList.of());
    }

    private static  U foldLeft(
            final Stream inputStream,
            final U state,
            final BiFunction folder) {
        U currentState = state;
        Iterator iterator = inputStream.iterator();
        while (iterator.hasNext()) {
            currentState = folder.apply(currentState, iterator.next());
        }
        return currentState;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy