Skip to content

Instantly share code, notes, and snippets.

@erichonorez
Created September 10, 2018 12:23
Show Gist options
  • Save erichonorez/a21c2347c2acb3f81156a549cdc0f49d to your computer and use it in GitHub Desktop.
Save erichonorez/a21c2347c2acb3f81156a549cdc0f49d to your computer and use it in GitHub Desktop.
package com.example.demo;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import lombok.Value;
import static io.vavr.API.$;
import static io.vavr.API.Case;
import static io.vavr.API.Match;
import static io.vavr.Predicates.instanceOf;
/**
* This solution uses Pattern Matching.
*
* The main advantages is that it is concise. Pattern matching can be used everywhere.
* The main disavantages is that the compiler does not help when new events are created (May be mitigated with unit tests).
*/
public class EventSourcingV4 {
interface Event {
String getLoanApplicationReference();
default String getVersion() {
return "V1";
}
}
interface EventV1 extends Event {
@Override
default String getVersion() {
return "V1";
}
}
@Value
static class CreatedV1 implements EventV1 {
private String loanApplicationReference;
}
@Value
static class GrantedV1 implements EventV1 {
private String loanApplicationReference;
}
interface EventV2 extends Event {
@Override
default String getVersion() {
return "V2";
}
}
@Value
static class CreatedV2 implements EventV2 {
private String loanApplicationReference;
}
@Value
static class GrantedV2 implements EventV2 {
private String loanApplicationReference;
}
interface State {
default boolean isEmpty() {
return false;
}
default boolean isCreated() {
return false;
}
default boolean isGranted() {
return false;
}
}
static class States {
public static State empty() {
return new Empty();
}
}
@Value
static class Empty implements State {
boolean isEmpty = true;
}
@Value
static class Created implements State {
String loanApplicationReference;
boolean isCreated = true;
}
@Value
static class Granted implements State {
String loanApplicationReference;
boolean isGranted = true;
}
static State apply(Event event, State state) {
return Match(event).of(
Case($(instanceOf(CreatedV1.class)), e -> applyEvent(e, state)),
Case($(instanceOf(GrantedV1.class)), e -> applyEvent(e, state)),
Case($(instanceOf(CreatedV2.class)), e -> applyEvent(e, state)),
Case($(instanceOf(GrantedV2.class)), e -> applyEvent(e, state))
);
}
static State apply(List<Event> events, State state) {
return events.stream()
.reduce(state, (s , e) -> apply(e, s), (state1, state2) -> state2);
}
static State applyEvent(CreatedV1 event, State state) {
return new Created(event.getLoanApplicationReference());
}
static State applyEvent(GrantedV1 event, State state) {
return new Granted(event.getLoanApplicationReference());
}
static State applyEvent(CreatedV2 event, State state) {
return new Created(event.getLoanApplicationReference());
}
static State applyEvent(GrantedV2 event, State state) {
return new Granted(event.getLoanApplicationReference());
}
public static void main(String[] args) {
String loanApplicationReference = UUID.randomUUID().toString();
State endState = apply(Arrays.asList(
new CreatedV1(loanApplicationReference),
new GrantedV1(loanApplicationReference)
), States.empty());
System.out.println(endState.isEmpty());
System.out.println(endState.isCreated());
System.out.println(endState.isGranted());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment