1 package ordertracker;
2
3 import java.util.concurrent.TimeUnit;
4
5 import com.google.common.base.Optional;
6
7 import ordertracker.Order.Events.ArrivedDepot;
8 import ordertracker.Order.Events.ArrivedFinalDepot;
9 import ordertracker.Order.Events.Assign;
10 import ordertracker.Order.Events.CouldNotDeliver;
11 import ordertracker.Order.Events.Create;
12 import ordertracker.Order.Events.DeliverAgain;
13 import ordertracker.Order.Events.Delivered;
14 import ordertracker.Order.Events.DeliveredByPickup;
15 import ordertracker.Order.Events.Delivering;
16 import ordertracker.Order.Events.DeliveryFailed;
17 import ordertracker.Order.Events.NoMoreAttempts;
18 import ordertracker.Order.Events.PickedUp;
19 import ordertracker.Order.Events.ReturnToSender;
20 import ordertracker.Order.Events.Send;
21 import ordertracker.Order.State;
22 import scala.concurrent.duration.Duration;
23
24 public class OrderBehaviour implements Order.Behaviour {
25
26 private final Order self;
27
28 public OrderBehaviour(Order self) {
29 this.self = self;
30 }
31
32 @Override
33 public void onEntryPreparing(Create event) {
34 self.setAttempts(0);
35 self.setComment(event.getComment());
36 self.setDescription(event.getDescription());
37 self.setDestinationEmail(event.getDestinationEmail());
38 self.setFromAddress(event.getFromAddress());
39 self.setId(event.getOrderID());
40 self.setMaxAttempts(event.getMaxAttempts());
41 self.setSenderEmail(event.getSenderEmail());
42 self.setToAddress(event.getToAddress());
43 event(Order.State.PREPARING);
44 }
45
46 @Override
47 public void onEntryReadyForDispatch(Send event) {
48 event(Order.State.READY_FOR_DISPATCH);
49 }
50
51 @Override
52 public void onEntryCourierAssigned(Assign event) {
53 event(Order.State.COURIER_ASSIGNED);
54 }
55
56 @Override
57 public void onEntryInTransit(PickedUp event) {
58 event(Order.State.IN_TRANSIT);
59 }
60
61 @Override
62 public void onEntryInTransit(ArrivedDepot event) {
63 Optional<Depot> depot = Depot.find(event.getDepotID());
64 if (!depot.isPresent())
65 throw new RuntimeException("depot does not exist: " + event.getDepotID());
66 else {
67 self.setDepot_R1(depot.get());
68 event(Order.State.IN_TRANSIT);
69 }
70 }
71
72 @Override
73 public void onEntryReadyForDelivery(ArrivedFinalDepot event) {
74 Optional<Depot> depot = Depot.find(event.getDepotID());
75 if (!depot.isPresent())
76 throw new RuntimeException("depot does not exist: " + event.getDepotID());
77 else {
78 self.setDepot_R1(depot.get());
79 event(Order.State.READY_FOR_DELIVERY);
80 }
81 }
82
83 @Override
84 public void onEntryDelivering(Delivering event) {
85 self.setAttempts(self.getAttempts() + 1);
86 event(Order.State.DELIVERING);
87 }
88
89 @Override
90 public void onEntryDelivered(Delivered event) {
91
92
93 event(Order.State.DELIVERED);
94 }
95
96 @Override
97 public void onEntryDeliveryFailed(DeliveryFailed event) {
98 event(Order.State.DELIVERY_FAILED);
99 if (self.getAttempts() >= self.getMaxAttempts())
100 self.signal(new Order.Events.NoMoreAttempts());
101 else
102 self.signal(new Order.Events.DeliverAgain());
103 }
104
105 @Override
106 public void onEntryAwaitingNextDeliveryAttempt(DeliverAgain event) {
107 self.signal(new Order.Events.DeliverAgain(), Duration.create(12, TimeUnit.MILLISECONDS));
108 event(Order.State.AWAITING_NEXT_DELIVERY_ATTEMPT);
109 }
110
111 @Override
112 public void onEntryHeldForPickup(NoMoreAttempts event) {
113 returnToSenderIfNotPickedUp();
114 }
115
116 @Override
117 public void onEntryHeldForPickup(CouldNotDeliver event) {
118 returnToSenderIfNotPickedUp();
119 }
120
121 private void returnToSenderIfNotPickedUp() {
122 self.signal(new Order.Events.ReturnToSender(), Duration.create(14, TimeUnit.MILLISECONDS));
123 event(Order.State.HELD_FOR_PICKUP);
124 }
125
126 @Override
127 public void onEntryReturnToSender(ReturnToSender event) {
128
129 event(Order.State.RETURN_TO_SENDER);
130 }
131
132 @Override
133 public void onEntryDelivered(DeliveredByPickup event) {
134 event(Order.State.DELIVERED);
135 }
136
137 private void event(State state) {
138
139 SystemEvent.find("1").get().signal(new SystemEvent.Events.NewEvent(state.toString()));
140 }
141
142 @Override
143 public void onEntryReadyForDelivery(DeliverAgain event) {
144 event(Order.State.READY_FOR_DELIVERY);
145 }
146
147 }