// 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/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);
//   }
// 
// }


import se.citerus.cqrs.bookstore.GenericId;
import se.citerus.cqrs.bookstore.event.DomainEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
  }

  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;
  }

// 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/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/domain/AggregateRoot.java
import se.citerus.cqrs.bookstore.GenericId;
import se.citerus.cqrs.bookstore.event.DomainEvent;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

  }

  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) {