public class EmailDeleteCommand {

    private String uuid;

    public EmailDeleteCommand(String id) {
        this.uuid = id;
    }

    public String getUuid() {
        return uuid;
    }

} public class EmailCreateCommand {

    private final String uuid;

    private final Email email;

    public EmailCreateCommand(String uuid, Email email) {
        this.uuid = uuid;
        this.email = email;
    }

    public Email getEmail() {
        return email;
    }

    public String getUuid() {
        return uuid;
    }

} public class EmailDeliveryCommand {

    private final String uuid;
    private final Instant instant;

    public EmailDeliveryCommand(String uuid, Instant instant) {
        this.uuid = uuid;
        this.instant = instant;
    }

    public String getUuid() {
        return uuid;
    }

    public Instant getInstant() {
        return instant;
    }

} public class EmailSendCommand {

    private final String uuid;
    private final Instant instant;

    public EmailSendCommand(String uuid, Instant instant) {
        this.uuid = uuid;
        this.instant = instant;
    }

    public String getUuid() {
        return uuid;
    }

    public Instant getInstant() {
        return instant;
    }

} @Entity
public class Email {

    @Id
    @GeneratedValue
    private long id;

    @NotNull
    private long authId;

    @NotNull
    @Size(min = 2, max = 256)
    private String name;

    @org.hibernate.validator.constraints.Email
    @NotNull
    @Column(unique = true)
    private String email;
    
    private EmailState state;

    @Version
    private long version;

    public Email() {
    }

    public Email(String name, String email, EmailState state) {
        this.name = name;
        this.email = email;
        this.state = state;
    }

    public Email(long id, String name, String email, EmailState state) {
        this(name, email,state);
        this.id = id;
    }

    public EmailState getState() {
        return state;
    }

    
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public long getAuthId() {
        return authId;
    }

    public void setAuthId(long authId) {
        this.authId = authId;
    }

    public long getVersion() {
        return version;
    }

    public void setVersion(long version) {
        this.version = version;
    }

    @Override
    public String toString() {
        return "Email{" + "id=" + id + ", authId=" + authId + ", name=" + name + ", email=" + email + ", version=" + version + '}';
    }

    public Email setState(EmailState emailState) {
        state = emailState;
        return this;
    }

} public class EmailCreatedEvent implements EmailEvent {

    private Email email;

    public EmailCreatedEvent(String uuid) {
    }

    protected String uuid;

    protected Instant when = Instant.now();

    @Override
    public String uuid() {
        return uuid;
    }

    @Override
    public Instant when() {
        return when;
    }

    public EmailCreatedEvent(String uuid, Email account) {
        this.email = account;
        this.uuid = uuid;
    }

    @Override
    public Email getEmail() {
        return email;
    }

} public class EmailDeliveredEvent extends AbstractDomainEvent implements EmailEvent {

    private final String uuid;
    private final Instant when = Instant.now();
    private final String type = "sent";
    
    private final Email email;

    public EmailDeliveredEvent(String uuid, Email email) {
        this.uuid = uuid;
        this.email = email;
    }

    @Override
    public String uuid() {
        return uuid;
    }

    public String type() {
        return type;
    }

    @Override
    public Instant when() {
        return when;
    }

    @Override
    public Email getEmail() {
        return email;
    }

} public class EmailDeletedEvent extends AbstractDomainEvent implements EmailEvent {

    private final String uuid;
    private final String type = "Deleted";
    private final Instant when = Instant.now();
    
    private Email email;

    /**
     *
     * @param uuid
     * @param email
     */
    public EmailDeletedEvent(String uuid, Email email) {
        this.uuid = uuid;
        this.email = email;
    }

    @Override
    public String uuid() {
        return uuid;
    }

    public String type() {
        return type;
    }

    @Override
    public Instant when() {
        return when;
    }

    public Email getEmail() {
        return email;
    }

} public interface EmailEvent extends AppEvent{
    
    Email getEmail();
    
} public class EmailSentEvent extends AbstractDomainEvent implements EmailEvent {

    private final String type = "sent";
    
    private Email email;

    public EmailSentEvent(String uuid, Email email) {
        this.uuid = uuid;
        this.email = email;
    }

    @Override
    public Email getEmail() {
        return email;
    }

} public interface AppEvent {

    String uuid();

    Instant when();

}
import com.apssouza.eventsourcing.commands.EmailDeleteCommand;
import com.apssouza.eventsourcing.commands.EmailCreateCommand;
import com.apssouza.eventsourcing.commands.EmailDeliveryCommand;
import com.apssouza.eventsourcing.commands.EmailSendCommand;
import com.apssouza.eventsourcing.entities.Email;
import com.apssouza.eventsourcing.events.EmailCreatedEvent;
import com.apssouza.eventsourcing.events.EmailDeliveredEvent;
import com.apssouza.eventsourcing.events.EmailDeletedEvent;
import com.apssouza.eventsourcing.events.EmailEvent;
import com.apssouza.eventsourcing.events.EmailSentEvent;
import com.apssouza.infra.AppEvent;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
package com.apssouza.eventsourcing.aggregates;


/**
 * Email aggregate, it aggregate all events related to Email and get the final
 * state
 *
 * @author apssouza
 */
public class EmailAggregate extends AbstractAggregate implements Aggregate {

    private final Email state;

    public EmailAggregate(String uuid, List<AppEvent> changes) {
        this(uuid, changes, new Email());
    }

    public EmailAggregate(String uuid, List<AppEvent> changes, Email state) {
        this.uuid = uuid;
        this.changes = changes;
        this.state = state;
    }

    public EmailAggregate create(EmailCreateCommand command) throws Exception {
        if (state.getState() != null) {
            throw new Exception("Is not possible to edit a deleted email");
        }
        return applyChange(new EmailCreatedEvent(uuid, command.getEmail()));