// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/GenericId.java
// public class GenericId {
// 
//   public final String id;
// 
//   public static final String ID_PATTERN =
//       "^(([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12})$";
// 
//   public GenericId(String id) {
//     this.id = id;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     return EqualsBuilder.reflectionEquals(this, o);
//   }
// 
//   @Override
//   public int hashCode() {
//     return HashCodeBuilder.reflectionHashCode(this);
//   }
// 
//   @Override
//   public String toString() {
//     return id;
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/domain/AggregateRoot.java
// public class AggregateRoot<T extends GenericId> {
// 
//   private final List<DomainEvent> uncommittedEvents = new ArrayList<>();
// 
//   private T id;
//   private int version = 0;
//   private long timestamp = 0;
// 
//   public List<DomainEvent> getUncommittedEvents() {
//     return uncommittedEvents;
//   }
// 
//   public void loadFromHistory(List<DomainEvent> history) {
//     for (DomainEvent event : history) {
//       applyChange(event, false);
//     }
//   }
// 
//   protected int nextVersion() {
//     return version + 1;
//   }
// 
//   protected long now() {
//     return System.currentTimeMillis();
//   }
// 
//   public T id() {
//     return id;
//   }
// 
//   public int version() {
//     return version;
//   }
// 
//   public long timestamp() {
//     return timestamp;
//   }
// 
//   protected void applyChange(DomainEvent event) {
//     applyChange(event, true);
//   }
// 
//   private void applyChange(DomainEvent event, boolean isNew) {
//     updateMetadata(event);
//     invokeHandlerMethod(event);
//     if (isNew) uncommittedEvents.add(event);
//   }
// 
//   private void updateMetadata(DomainEvent event) {
//     this.id = (T) event.aggregateId;
//     this.version = event.version;
//     this.timestamp = event.timestamp;
//   }
// 
//   private void invokeHandlerMethod(DomainEvent event) {
//     Method handlerMethod = getHandlerMethod(event);
//     if (handlerMethod != null) {
//       handlerMethod.setAccessible(true);
//       try {
//         handlerMethod.invoke(this, event);
//       } catch (Exception e) {
//         throw new RuntimeException("Unable to call event handler method for " + event.getClass().getName(), e);
//       }
//     }
//   }
// 
//   private Method getHandlerMethod(DomainEvent event) {
//     try {
//       return getClass().getDeclaredMethod("handleEvent", event.getClass());
//     } catch (NoSuchMethodException e) {
//       return null;
//     }
//   }
// 
//   public boolean hasUncommittedEvents() {
//     return !uncommittedEvents.isEmpty();
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/event/DomainEvent.java
// public abstract class DomainEvent<T extends GenericId> implements Serializable {
// 
//   public final T aggregateId;
//   public final int version;
//   public final long timestamp;
// 
//   protected DomainEvent(T aggregateId, int version, long timestamp) {
//     this.aggregateId = aggregateId;
//     this.version = version;
//     this.timestamp = timestamp;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     return EqualsBuilder.reflectionEquals(this, o);
//   }
// 
//   @Override
//   public int hashCode() {
//     return HashCodeBuilder.reflectionHashCode(this);
//   }
// 
//   @Override
//   public String toString() {
//     return ToStringBuilder.reflectionToString(this, SHORT_PREFIX_STYLE);
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/event/DomainEventStore.java
// public interface DomainEventStore {
// 
//   List<DomainEvent> loadEvents(GenericId id);
// 
//   void save(GenericId id, Class<? extends AggregateRoot> type, List<DomainEvent> events);
// 
//   List<DomainEvent> getAllEvents();
// 
// }


import com.google.common.collect.Lists;
import se.citerus.cqrs.bookstore.GenericId;
import se.citerus.cqrs.bookstore.domain.AggregateRoot;
import se.citerus.cqrs.bookstore.event.DomainEvent;
import se.citerus.cqrs.bookstore.event.DomainEventStore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
package se.citerus.cqrs.bookstore.ordercontext.application.infrastructure;



public class InMemoryDomainEventStore implements DomainEventStore {

  private final List<DomainEvent> events = new ArrayList<>();

  @Override
  public synchronized List<DomainEvent> loadEvents(GenericId id) {
    List<DomainEvent> loadedEvents = new ArrayList<>();

    for (DomainEvent event : events) {
      if (event.aggregateId.equals(id)) {
        loadedEvents.add(event);
      }
    }
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/GenericId.java
// public class GenericId {
// 
//   public final String id;
// 
//   public static final String ID_PATTERN =
//       "^(([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12})$";
// 
//   public GenericId(String id) {
//     this.id = id;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     return EqualsBuilder.reflectionEquals(this, o);
//   }
// 
//   @Override
//   public int hashCode() {
//     return HashCodeBuilder.reflectionHashCode(this);
//   }
// 
//   @Override
//   public String toString() {
//     return id;
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/domain/AggregateRoot.java
// public class AggregateRoot<T extends GenericId> {
// 
//   private final List<DomainEvent> uncommittedEvents = new ArrayList<>();
// 
//   private T id;
//   private int version = 0;
//   private long timestamp = 0;
// 
//   public List<DomainEvent> getUncommittedEvents() {
//     return uncommittedEvents;
//   }
// 
//   public void loadFromHistory(List<DomainEvent> history) {
//     for (DomainEvent event : history) {
//       applyChange(event, false);
//     }
//   }
// 
//   protected int nextVersion() {
//     return version + 1;
//   }
// 
//   protected long now() {
//     return System.currentTimeMillis();
//   }
// 
//   public T id() {
//     return id;
//   }
// 
//   public int version() {
//     return version;
//   }
// 
//   public long timestamp() {
//     return timestamp;
//   }
// 
//   protected void applyChange(DomainEvent event) {
//     applyChange(event, true);
//   }
// 
//   private void applyChange(DomainEvent event, boolean isNew) {
//     updateMetadata(event);
//     invokeHandlerMethod(event);
//     if (isNew) uncommittedEvents.add(event);
//   }
// 
//   private void updateMetadata(DomainEvent event) {
//     this.id = (T) event.aggregateId;
//     this.version = event.version;
//     this.timestamp = event.timestamp;
//   }
// 
//   private void invokeHandlerMethod(DomainEvent event) {
//     Method handlerMethod = getHandlerMethod(event);
//     if (handlerMethod != null) {
//       handlerMethod.setAccessible(true);
//       try {
//         handlerMethod.invoke(this, event);
//       } catch (Exception e) {
//         throw new RuntimeException("Unable to call event handler method for " + event.getClass().getName(), e);
//       }
//     }
//   }
// 
//   private Method getHandlerMethod(DomainEvent event) {
//     try {
//       return getClass().getDeclaredMethod("handleEvent", event.getClass());
//     } catch (NoSuchMethodException e) {
//       return null;
//     }
//   }
// 
//   public boolean hasUncommittedEvents() {
//     return !uncommittedEvents.isEmpty();
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/event/DomainEvent.java
// public abstract class DomainEvent<T extends GenericId> implements Serializable {
// 
//   public final T aggregateId;
//   public final int version;
//   public final long timestamp;
// 
//   protected DomainEvent(T aggregateId, int version, long timestamp) {
//     this.aggregateId = aggregateId;
//     this.version = version;
//     this.timestamp = timestamp;
//   }
// 
//   @Override
//   public boolean equals(Object o) {
//     return EqualsBuilder.reflectionEquals(this, o);
//   }
// 
//   @Override
//   public int hashCode() {
//     return HashCodeBuilder.reflectionHashCode(this);
//   }
// 
//   @Override
//   public String toString() {
//     return ToStringBuilder.reflectionToString(this, SHORT_PREFIX_STYLE);
//   }
// 
// }
// 
// Path: cqrs-lib/src/main/java/se/citerus/cqrs/bookstore/event/DomainEventStore.java
// public interface DomainEventStore {
// 
//   List<DomainEvent> loadEvents(GenericId id);
// 
//   void save(GenericId id, Class<? extends AggregateRoot> type, List<DomainEvent> events);
// 
//   List<DomainEvent> getAllEvents();
// 
// }


// Path: order-context-parent/order-application/src/main/java/se/citerus/cqrs/bookstore/ordercontext/application/infrastructure/InMemoryDomainEventStore.java
import com.google.common.collect.Lists;
import se.citerus.cqrs.bookstore.GenericId;
import se.citerus.cqrs.bookstore.domain.AggregateRoot;
import se.citerus.cqrs.bookstore.event.DomainEvent;
import se.citerus.cqrs.bookstore.event.DomainEventStore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

package se.citerus.cqrs.bookstore.ordercontext.application.infrastructure;



public class InMemoryDomainEventStore implements DomainEventStore {

  private final List<DomainEvent> events = new ArrayList<>();

  @Override
  public synchronized List<DomainEvent> loadEvents(GenericId id) {
    List<DomainEvent> loadedEvents = new ArrayList<>();

    for (DomainEvent event : events) {
      if (event.aggregateId.equals(id)) {
        loadedEvents.add(event);
      }
    }
    if (loadedEvents.isEmpty()) throw new IllegalArgumentException("Aggregate does not exist: " + id);