]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
Some UI Fixes in PizzeriaGUI inter-table communication.
[pub/jan/sbc.git] / src / main / java / at / ac / tuwien / sbc / valesriegler / xvsm / WaiterXVSM.java
1 package at.ac.tuwien.sbc.valesriegler.xvsm;
2
3 import at.ac.tuwien.sbc.valesriegler.common.OrderId;
4 import at.ac.tuwien.sbc.valesriegler.common.Util;
5 import at.ac.tuwien.sbc.valesriegler.types.*;
6 import org.mozartspaces.core.MzsConstants;
7 import org.mozartspaces.core.MzsConstants.RequestTimeout;
8 import org.mozartspaces.core.MzsCoreException;
9 import org.mozartspaces.core.TransactionReference;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import java.io.Serializable;
14 import java.util.Arrays;
15 import java.util.List;
16
17 public class WaiterXVSM extends AbstractXVSMConnector {
18     private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
19     private final int waiterId;
20
21     public WaiterXVSM(int waiterId, int port) {
22         super(port);
23
24         this.waiterId = waiterId;
25
26         freeTablesContainer = useContainer(Util.FREE_TABLES);
27         assignTableContainer = useContainer(Util.ASSIGN_TABLE);
28         takeOrderContainer = useContainer(Util.TAKE_ORDER);
29         orderTakenContainer = useContainer(Util.ORDER_TAKEN);
30         deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
31         groupAgentOrderTakenContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_TAKEN, Util.GROUP_AGENT_PORT);
32         preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
33         orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
34         groupAgentOrderCompleteContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_COMPLETE, Util.GROUP_AGENT_PORT);
35         deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
36         paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
37         groupAgentPaymentRequestContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_REQUEST, Util.GROUP_AGENT_PORT);
38         paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
39         groupAgentPaymentDoneContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_DONE, Util.GROUP_AGENT_PORT);
40         tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
41         groupAgentTableAssignedContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_TABLE_ASSIGNED, Util.GROUP_AGENT_PORT);
42         pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
43         phoneCallsContainer = useContainer(Util.PHONE_CALLS);
44         groupAgentDeliveryOrderTakenContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_DELIVERY_ORDER_TAKEN, Util.GROUP_AGENT_PORT);
45     }
46
47     public void listenForPhoneOrders() {
48         SpaceListener phoneListener = new SpaceListenerImpl(capi, phoneCallsContainer, true) {
49             @Override
50             void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
51                 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
52
53                 for (DeliveryGroupData phoneOrder : phoneOrders) {
54                     final int id = phoneOrder.getId();
55                     final DeliveryGroupData template = new DeliveryGroupData(id);
56                     final String errorMsg = String.format("There was phone call with id %d", id);
57
58                     final TransactionReference tx = getDefaultTransaction();
59                     try {
60                         final DeliveryGroupData groupFromSpace = takeMatchingEntity(template, phoneCallsContainer, tx, RequestTimeout.DEFAULT, errorMsg);
61                         groupFromSpace.setWaiterIdOfOrder(WaiterXVSM.this.waiterId);
62                         final Order order = groupFromSpace.getOrder();
63                         groupFromSpace.setDeliveryStatus(DeliveryStatus.ORDERED);
64
65                         updatePizzeriaOrderNumber(order, tx);
66
67
68                         // send the order as a whole to the space
69                         final List<DeliveryGroupData> groupsWhoHaveOrdered = Arrays.asList(groupFromSpace);
70                         sendItemsToContainer(groupsWhoHaveOrdered,
71                                 deliveryOrderTakenContainer, RequestTimeout.ZERO, tx);
72                         sendItemsToContainer(order.getOrderedPizzas(),
73                                 preparePizzasContainer, RequestTimeout.ZERO, tx);
74                         sendItemsToContainer(groupsWhoHaveOrdered,
75                                 groupAgentDeliveryOrderTakenContainer, RequestTimeout.ZERO, null);
76                         capi.commitTransaction(tx);
77
78                         log.info("Waite has taken a phone delivery call!");
79                     } catch (Exception e) {
80                     }
81
82
83                 }
84
85             }
86         };
87         createNotification(phoneListener, phoneCallsContainer);
88     }
89
90     private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
91     /*  get the id of the last order of the pizzeria and set the order accordingly and
92         update the space */
93         final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
94         final int id = orderId.getId();
95         final int nextId = id + 1;
96         order.setId(nextId);
97         final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
98         for (PizzaOrder orderedPizza : orderedPizzas) {
99             orderedPizza.setOrderId(nextId);
100         }
101         sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
102     }
103
104
105     public void listenForFreeTable() {
106         SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
107
108             @Override
109             void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
110
111                 List<Table> tables = castEntries(entries);
112
113                 for (Table table : tables) {
114
115                     TransactionReference tx = getDefaultTransaction();
116
117                     // Acquire a lock for the free table in the
118                     // FreeTableContainer
119                     int id = table.getId();
120
121                     Table tableTemplate = new Table(id);
122                     try {
123                         Table lockedFreeTable = takeMatchingEntity(tableTemplate,
124                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
125                                 String.format("There was no free table found with id %d", id));
126
127
128                         GroupData groupTemplate = new GroupData();
129                         GroupData lockedGroup = takeMatchingEntity(groupTemplate,
130                                 assignTableContainer, tx, RequestTimeout.DEFAULT,
131                                 "There is no group waiting for a table at the moment");
132
133                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
134                     } catch (Exception e) {
135 //                                              log.info(e.getMessage());
136                     }
137                 }
138             }
139         };
140
141         createNotification(listener, freeTablesContainer);
142     }
143
144     public void listenForNewGuests() {
145         SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
146
147             @Override
148             void onEntriesWritten(List<? extends Serializable> entries)
149                     throws Exception {
150                 log.info("New guest groups have arrived");
151
152                 List<GroupData> groups = castEntries(entries);
153
154                 for (GroupData group : groups) {
155
156                     TransactionReference tx = getDefaultTransaction();
157
158                     // Acquire a lock for the group in the
159                     // AssignTableContainer
160                     String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
161
162                     try {
163                         GroupData lockedGroup = takeMatchingEntity(
164                                 new GroupData(group.getId()),
165                                 assignTableContainer, tx,
166                                 RequestTimeout.DEFAULT, groupNotFound);
167                         // Acquire a lock for one free table in the
168                         // TablesContainer
169                         String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
170                         Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
171                                 noFreeTable);
172
173                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
174                     } catch (Exception e) {
175 //                                              log.info(e.getMessage());
176                     }
177                 }
178             }
179         };
180
181         createNotification(listener, assignTableContainer);
182     }
183
184     public void listenForPaymentRequest() {
185         SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
186
187             @Override
188             void onEntriesWritten(List<? extends Serializable> entries)
189                     throws Exception {
190
191                 List<GroupData> groups = castEntries(entries);
192
193                 for (GroupData groupData : groups) {
194                     TransactionReference tx = getDefaultTransaction();
195                     GroupData entity = new GroupData(groupData.getId());
196
197                     // Acquire the lock so that another waiter can't do the same
198                     // thing!
199                     String paymentRequestTakenByOtherWaiter = String.format(
200                             "The payment request for group %d was already taken by an other waiter!",
201                             groupData.getId());
202                     try {
203                         takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
204
205                         groupData.setPayingWaiter(waiterId);
206
207                         final List<GroupData> groupsPayed = Arrays.asList(groupData);
208                         sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
209                         sendItemsToContainer(groupsPayed, groupAgentPaymentDoneContainer, RequestTimeout.ZERO, null);
210
211                         capi.commitTransaction(tx);
212                     } catch (Exception e) {
213 //                                              log.info(e.getMessage());
214                     }
215                 }
216             }
217         };
218
219         createNotification(paymentListener, paymentRequestContainer);
220     }
221
222     public void listenForOrderRequests() {
223         SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
224
225             @Override
226             void onEntriesWritten(List<? extends Serializable> entries)
227                     throws Exception {
228
229                 List<GroupData> groups = castEntries(entries);
230
231                 for (GroupData groupData : groups) {
232
233                     TransactionReference tx = getDefaultTransaction();
234                     GroupData entity = new GroupData(groupData.getId());
235                     entity.setState(GroupState.SITTING);
236
237                     try {
238                         // Acquire the lock so that another waiter can't do the same thing!
239                         String orderTakenByOtherWaiter = String.format(
240                                 "The order for group %d was already taken by an other waiter!",
241                                 groupData.getId());
242                         takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
243
244                         groupData.setOrderWaiter(waiterId);
245                         groupData.setState(GroupState.ORDERED);
246                         Order order = groupData.getOrder();
247                         order.setStatus(OrderStatus.ORDERED);
248
249                         /*  get the id of the last order of the pizzeria and set the order accordingly and
250                             update the space */
251                         updatePizzeriaOrderNumber(order, tx);
252
253                         // send the order as a whole to the space
254                         final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(groupData);
255                         sendItemsToContainer(groupsWhoHaveOrdered,
256                                 orderTakenContainer, RequestTimeout.ZERO, tx);
257                         sendItemsToContainer(order.getOrderedPizzas(),
258                                 preparePizzasContainer, RequestTimeout.ZERO, tx);
259                         sendItemsToContainer(groupsWhoHaveOrdered,
260                                 groupAgentOrderTakenContainer, RequestTimeout.ZERO, null);
261                         capi.commitTransaction(tx);
262
263                         log.info("Waiter has taken order from group {}",
264                                 groupData.getId());
265                     } catch (Exception e) {
266 //                                              log.info(e.getMessage());
267                     }
268                 }
269             }
270         };
271
272         createNotification(ordersListener, takeOrderContainer);
273     }
274
275     public void listenForPreparedPizzas() {
276         /**
277          * A waiter gets informed when a new pizza is complete. He takes the
278          * orderId of the pizza and looks up the corresponding order from which
279          * he gets the number of necessary pizzas of the order. He then tries to
280          * fetch all pizzas with the corresponding orderId and compares the
281          * number of those pizzas with the number of necessary pizzas. If all
282          * pizzas of an order are complete he then delivers them!
283          */
284         SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
285
286             @Override
287             void onEntriesWritten(List<? extends Serializable> entries)
288                     throws Exception {
289
290                 List<Pizza> pizzas = castEntries(entries);
291
292                 for (Pizza pizza : pizzas) {
293                     int orderId = pizza.getOrderId();
294                     Order order = new Order();
295                     order.setId(orderId);
296
297                     TransactionReference tx = getDefaultTransaction();
298                     final boolean isDeliveryPizza = pizza.isDeliveryPizza();
299
300                     try {
301                         GroupData entity = new GroupData();
302                         entity.setState(null);
303                         entity.setOrder(order);
304
305                         GroupData groupData = takeMatchingEntity(entity,
306                                 orderTakenContainer, tx, RequestTimeout.DEFAULT,
307                                 "Another waiter just checks if the order is complete");
308                         int groupId = groupData.getId();
309                         int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
310
311                         Pizza pizzaTemplate = new Pizza();
312                         pizzaTemplate.setOrderId(orderId);
313
314                         List<Pizza> pizzasOfOrder = takeMatchingEntities(
315                                 pizzaTemplate, deliverPizzasContainer, tx,
316                                 RequestTimeout.DEFAULT,
317                                 "Cannot take the pizzas from the deliverPizzasContainer");
318
319                         if (pizzasOfOrder.size() == numberOfPizzas) {
320                             GroupData group = new GroupData();
321                             group.setServingWaiter(waiterId);
322                             Order completeOrder = new Order();
323                             completeOrder.setId(orderId);
324                             completeOrder.setGroupId(groupId);
325                             group.setOrder(completeOrder);
326                             final List<GroupData> groupsWithCompleteOrder = Arrays.asList(group);
327                             sendItemsToContainer(groupsWithCompleteOrder,
328                                     orderCompleteContainer, RequestTimeout.DEFAULT,
329                                     tx);
330                             sendItemsToContainer(groupsWithCompleteOrder,
331                                     groupAgentOrderCompleteContainer, RequestTimeout.DEFAULT,
332                                     null);
333
334                             capi.commitTransaction(tx);
335                         } else {
336                             log.info("Not yet all pizzas prepared! Order with id "
337                                     + orderId + " has " + numberOfPizzas
338                                     + " pizzas, but only " + pizzasOfOrder.size()
339                                     + " pizzas are ready by now!");
340                             capi.rollbackTransaction(tx);
341                         }
342                     } catch (NullPointerException e) {
343
344                     } catch (Exception e) {
345                         capi.rollbackTransaction(tx);
346                     }
347                 }
348             }
349         };
350
351         createNotification(preparedPizzasListener, deliverPizzasContainer);
352     }
353
354     private void assignGroupToTable(GroupData lockedGroup,
355                                     Table lockedFreeTable, TransactionReference tx)
356             throws MzsCoreException {
357         // The new group sits down at the table
358         lockedFreeTable.setGroupId(lockedGroup.getId());
359
360         // The new group now wants to order
361         lockedGroup.setState(GroupState.SITTING);
362         lockedGroup.setTable(lockedFreeTable);
363         lockedGroup.setTableWaiter(waiterId);
364
365         final List<Table> freeTables = Arrays.asList(lockedFreeTable);
366         sendItemsToContainer(freeTables,
367                 tableAssignedContainer, RequestTimeout.ZERO, tx);
368         sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
369                 RequestTimeout.ZERO, tx);
370         sendItemsToContainer(freeTables,
371                 groupAgentTableAssignedContainer, RequestTimeout.ZERO, null);
372
373         try {
374             capi.commitTransaction(tx);
375             log.info("Assigned table to group with groupId {}",
376                     lockedGroup.getId());
377         } catch (Exception e) {
378             log.info("Assigning a table to group with groupId {} failed",
379                     lockedGroup.getId());
380             log.info(e.getMessage());
381         }
382     }
383 }