
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 extends TEvent> 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