Open
Description
/**
* The incorporate method uses a simple state machine for an order's status to generate
* the current state of an order using event sourcing and aggregation.
* <p>
* The event diagram below represents how events are incorporated into generating the
* order status. The event log for the order status can be used to rollback the state
* of the order in the case of a failed distributed transaction.
* <p>
* Events: +<--PURCHASED+ +<--CREATED+ +<---ORDERED+ +<----SHIPPED+
* * | | | | | | | |
* Status +PURCHASED---+PENDING------+CONFIRMED-----+SHIPPED--------+DELIVERED
* * | | | | | | | |
* Events: +CREATED---->+ +ORDERED-->+ +SHIPPED--->+ +DELIVERED-->+
*
* @param orderEvent is the event to incorporate into the state machine
* @return the aggregate {@link Order} with the aggregated order status
*/
public Order incorporate(OrderEvent orderEvent) {
if (orderStatus == null)
orderStatus = OrderStatus.PURCHASED;
switch (orderStatus) {
case PURCHASED:
if (orderEvent.getType() == OrderEventType.CREATED)
orderStatus = OrderStatus.PENDING;
break;
case PENDING:
if (orderEvent.getType() == OrderEventType.ORDERED) {
orderStatus = OrderStatus.CONFIRMED;
} else if (orderEvent.getType() == OrderEventType.PURCHASED) {
orderStatus = OrderStatus.PURCHASED;
}
break;
case CONFIRMED:
if (orderEvent.getType() == OrderEventType.SHIPPED) {
orderStatus = OrderStatus.SHIPPED;
} else if (orderEvent.getType() == OrderEventType.CREATED) {
orderStatus = OrderStatus.PENDING;
}
break;
case SHIPPED:
if (orderEvent.getType() == OrderEventType.DELIVERED) {
orderStatus = OrderStatus.DELIVERED;
} else if (orderEvent.getType() == OrderEventType.ORDERED) {
orderStatus = OrderStatus.CONFIRMED;
}
break;
case DELIVERED:
if (orderEvent.getType() == OrderEventType.SHIPPED)
orderStatus = OrderStatus.SHIPPED;
break;
default:
// Invalid event type with regards to the order status
break;
}
return this;
}