// 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: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/OrderId.java
// public class OrderId extends GenericId {
// 
//   public OrderId(@JsonProperty("id") String id) {
//     super(id);
//   }
// 
//   public static OrderId randomId() {
//     return new OrderId(UUID.randomUUID().toString());
//   }
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/OrderStatus.java
// public enum OrderStatus {
// 
//   ACTIVATED, PLACED
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/event/OrderActivatedEvent.java
// public class OrderActivatedEvent extends DomainEvent<OrderId> {
// 
//   public OrderActivatedEvent(@JsonProperty("aggregateId") OrderId aggregateId,
//                              @JsonProperty("version") int version,
//                              @JsonProperty("timestamp") long timestamp) {
//     super(aggregateId, version, timestamp);
//   }
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/event/OrderPlacedEvent.java
// public class OrderPlacedEvent extends DomainEvent<OrderId> {
// 
//   public final CustomerInformation customerInformation;
//   public final List<OrderLine> orderLines;
//   public final long orderAmount;
// 
//   public OrderPlacedEvent(@JsonProperty("aggregateId") OrderId id,
//                           @JsonProperty("version") int version,
//                           @JsonProperty("timestamp") long timestamp,
//                           @JsonProperty("customerInformation") CustomerInformation customerInformation,
//                           @JsonProperty("orderLines") List<OrderLine> orderLines,
//                           @JsonProperty("orderAmount") long orderAmount) {
//     super(id, version, timestamp);
//     this.customerInformation = customerInformation;
//     this.orderLines = Collections.unmodifiableList(orderLines);
//     this.orderAmount = orderAmount;
//   }
// 
// }


import se.citerus.cqrs.bookstore.domain.AggregateRoot;
import se.citerus.cqrs.bookstore.ordercontext.order.OrderId;
import se.citerus.cqrs.bookstore.ordercontext.order.OrderStatus;
import se.citerus.cqrs.bookstore.ordercontext.order.event.OrderActivatedEvent;
import se.citerus.cqrs.bookstore.ordercontext.order.event.OrderPlacedEvent;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
package se.citerus.cqrs.bookstore.ordercontext.order.domain;




public class Order extends AggregateRoot<OrderId> {

  private OrderStatus status;

  public void place(OrderId orderId, CustomerInformation customerInformation, List<OrderLine> orderLines, long totalAmount) {
    assertHasNotBeenPlaced();
    assertMoreThanZeroOrderLines(orderLines);
// 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: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/OrderId.java
// public class OrderId extends GenericId {
// 
//   public OrderId(@JsonProperty("id") String id) {
//     super(id);
//   }
// 
//   public static OrderId randomId() {
//     return new OrderId(UUID.randomUUID().toString());
//   }
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/OrderStatus.java
// public enum OrderStatus {
// 
//   ACTIVATED, PLACED
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/event/OrderActivatedEvent.java
// public class OrderActivatedEvent extends DomainEvent<OrderId> {
// 
//   public OrderActivatedEvent(@JsonProperty("aggregateId") OrderId aggregateId,
//                              @JsonProperty("version") int version,
//                              @JsonProperty("timestamp") long timestamp) {
//     super(aggregateId, version, timestamp);
//   }
// 
// }
// 
// Path: order-context-parent/eventbus-contract/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/event/OrderPlacedEvent.java
// public class OrderPlacedEvent extends DomainEvent<OrderId> {
// 
//   public final CustomerInformation customerInformation;
//   public final List<OrderLine> orderLines;
//   public final long orderAmount;
// 
//   public OrderPlacedEvent(@JsonProperty("aggregateId") OrderId id,
//                           @JsonProperty("version") int version,
//                           @JsonProperty("timestamp") long timestamp,
//                           @JsonProperty("customerInformation") CustomerInformation customerInformation,
//                           @JsonProperty("orderLines") List<OrderLine> orderLines,
//                           @JsonProperty("orderAmount") long orderAmount) {
//     super(id, version, timestamp);
//     this.customerInformation = customerInformation;
//     this.orderLines = Collections.unmodifiableList(orderLines);
//     this.orderAmount = orderAmount;
//   }
// 
// }


// Path: order-context-parent/order-command/src/main/java/se/citerus/cqrs/bookstore/ordercontext/order/domain/Order.java
import se.citerus.cqrs.bookstore.domain.AggregateRoot;
import se.citerus.cqrs.bookstore.ordercontext.order.OrderId;
import se.citerus.cqrs.bookstore.ordercontext.order.OrderStatus;
import se.citerus.cqrs.bookstore.ordercontext.order.event.OrderActivatedEvent;
import se.citerus.cqrs.bookstore.ordercontext.order.event.OrderPlacedEvent;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

package se.citerus.cqrs.bookstore.ordercontext.order.domain;




public class Order extends AggregateRoot<OrderId> {

  private OrderStatus status;

  public void place(OrderId orderId, CustomerInformation customerInformation, List<OrderLine> orderLines, long totalAmount) {
    assertHasNotBeenPlaced();
    assertMoreThanZeroOrderLines(orderLines);
    applyChange(new OrderPlacedEvent(orderId, nextVersion(), now(), toCustomerInformation(customerInformation),