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