]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
[XVSM] Crucial container communication changes
[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 at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceListener;
8 import org.mozartspaces.core.MzsConstants.RequestTimeout;
9 import org.mozartspaces.core.MzsCoreException;
10 import org.mozartspaces.core.TransactionReference;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import java.io.Serializable;
15 import java.util.Arrays;
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     }
46
47     public void listenForPhoneOrders() {
48         SpaceListener phoneListener = getDefaultBuilder().setCref(phoneCallsContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
49             @Override
50             public 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                                 prepareDeliveryPizzasContainer, RequestTimeout.ZERO, tx);
74                         capi.commitTransaction(tx);
75
76                         log.info("Waiter has taken a phone delivery call!");
77                     } catch (Exception e) {
78                     }
79                 }
80
81             }
82         }).createSpaceListenerImpl();
83     }
84
85     public void listenForFreeTable() {
86         SpaceListener listener = getDefaultBuilder().setCref(freeTablesContainer).setSpaceAction(new SpaceAction() {
87
88             @Override
89             public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
90
91                 List<Table> tables = castEntries(entries);
92
93                 for (Table table : tables) {
94
95                     TransactionReference tx = getDefaultTransaction();
96
97                     // Acquire a lock for the free table in the
98                     // FreeTableContainer
99                     int id = table.getId();
100
101                     Table tableTemplate = new Table(id);
102                     try {
103                         Table lockedFreeTable = takeMatchingEntity(tableTemplate,
104                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
105                                 String.format("There was no free table found with id %d", id));
106                         takeMatchingEntityIfItExists(tableTemplate, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT);
107
108                         GroupData groupTemplate = new GroupData();
109                         GroupData lockedGroup = takeMatchingEntity(groupTemplate,
110                                 assignTableContainer, tx, RequestTimeout.DEFAULT,
111                                 "There is no group waiting for a table at the moment");
112                         takeMatchingEntityIfItExists(lockedGroup, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
113
114                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
115                     } catch (Exception e) {
116 //                                              log.info(e.getMessage());
117                     }
118                 }
119             }
120         }).createSpaceListenerImpl();
121     }
122
123
124     public void listenForNewGuests() {
125         SpaceListener listener = getDefaultBuilder().setLookaround(true).setCref(assignTableContainer).setSpaceAction(new SpaceAction() {
126
127             @Override
128             public void onEntriesWritten(List<? extends Serializable> entries)
129                     throws Exception {
130                 log.info("New guest groups have arrived");
131
132                 List<GroupData> groups = castEntries(entries);
133
134                 for (GroupData group : groups) {
135
136                     TransactionReference tx = getDefaultTransaction();
137
138                     // Acquire a lock for the group in the
139                     // AssignTableContainer
140                     String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
141
142                     try {
143                         final GroupData templateGroup = new GroupData(group.getId());
144                         GroupData lockedGroup = takeMatchingEntity(
145                                 templateGroup,
146                                 assignTableContainer, tx,
147                                 RequestTimeout.DEFAULT, groupNotFound);
148                         takeMatchingEntityIfItExists(templateGroup, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
149                         // Acquire a lock for one free table in the
150                         // TablesContainer
151                         String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
152                         final Table freeTable = new Table(null);
153                         freeTable.setFree(true);
154                         Table lockedFreeTable = takeMatchingEntity(freeTable, freeTablesContainer, tx, RequestTimeout.DEFAULT,
155                                 noFreeTable);
156                         takeMatchingEntityIfItExists(lockedFreeTable, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT);
157
158                         assignGroupToTable(lockedGroup, lockedFreeTable, tx);
159                     } catch (Exception e) {
160 //                                              log.info(e.getMessage());
161                     }
162                 }
163             }
164         }).createSpaceListenerImpl();
165     }
166
167     public void listenForPaymentRequest() {
168         SpaceListener paymentListener = getDefaultBuilder().setCref(paymentRequestContainer).setSpaceAction(new SpaceAction() {
169
170             @Override
171             public void onEntriesWritten(List<? extends Serializable> entries)
172                     throws Exception {
173
174                 List<GroupData> groups = castEntries(entries);
175
176                 for (GroupData groupData : groups) {
177                     TransactionReference tx = getDefaultTransaction();
178                     GroupData entity = new GroupData(groupData.getId());
179                     entity.setState(GroupState.PAY);
180
181                     // Acquire the lock so that another waiter can't do the same
182                     // thing!
183                     String paymentRequestTakenByOtherWaiter = String.format(
184                             "The payment request for group %d was already taken by an other waiter!",
185                             groupData.getId());
186                     try {
187                         takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
188                         GroupData group = takeMatchingEntity(entity, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT, "Cannot get paying group!");
189                         group.setPayingWaiter(waiterId);
190                         group.setState(GroupState.GONE);
191
192                         final Table tableTemplate = new Table(null);
193                         tableTemplate.setGroupId(group.getId());
194                         final Table table = takeMatchingEntity(tableTemplate, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT, "Table was not found!");
195                         table.setGroupId(-1);
196                         final List<Table> tables = Arrays.asList(table);
197                         sendItemsToContainer(tables, pizzeriaTableContainer, RequestTimeout.DEFAULT, tx);
198                         sendItemsToContainer(tables, freeTablesContainer, RequestTimeout.DEFAULT, tx);
199
200                         final List<GroupData> groupsPayed = Arrays.asList(group);
201                         sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.DEFAULT, tx);
202                         sendItemsToContainer(groupsPayed, pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
203
204                         capi.commitTransaction(tx);
205                     } catch (Exception e) {
206                                                 log.info(e.getMessage());
207                     }
208                 }
209             }
210         }).createSpaceListenerImpl();
211     }
212
213     public void listenForOrderRequests() {
214         SpaceListener ordersListener = getDefaultBuilder().setCref(takeOrderContainer).setSpaceAction(new SpaceAction() {
215
216             @Override
217             public void onEntriesWritten(List<? extends Serializable> entries)
218                     throws Exception {
219
220                 List<GroupData> groups = castEntries(entries);
221
222                 for (GroupData groupData : groups) {
223
224                     TransactionReference tx = getDefaultTransaction();
225                     GroupData entity = new GroupData(groupData.getId());
226                     entity.setState(GroupState.SITTING);
227
228                     try {
229                         // Acquire the lock so that another waiter can't do the same thing!
230                         String orderTakenByOtherWaiter = String.format(
231                                 "The order for group %d was already taken by an other waiter!",
232                                 groupData.getId());
233                         takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
234                         GroupData group = takeMatchingEntityIfItExists(entity, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
235
236                         group.setOrderWaiter(waiterId);
237                         group.setState(GroupState.ORDERED);
238                         Order order = group.getOrder();
239                         order.setStatus(OrderStatus.ORDERED);
240
241                         /*  get the id of the last order of the pizzeria and set the order accordingly and
242                             update the space */
243                         updatePizzeriaOrderNumber(order, tx);
244
245                         // send the order as a whole to the space
246                         final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(group);
247                         sendItemsToContainer(groupsWhoHaveOrdered,
248                                 orderTakenContainer, RequestTimeout.ZERO, tx);
249                         sendItemsToContainer(groupsWhoHaveOrdered,
250                                 pizzeriaGroupContainer, RequestTimeout.ZERO, tx);
251                         sendItemsToContainer(order.getOrderedPizzas(),
252                                 preparePizzasContainer, RequestTimeout.ZERO, tx);
253                         capi.commitTransaction(tx);
254
255                         log.info("Waiter has taken order from group {}",
256                                 group.getId());
257                     } catch (Exception e) {
258 //                                              log.info(e.getMessage());
259                     }
260                 }
261             }
262         }).createSpaceListenerImpl();
263     }
264
265     public void listenForPreparedPizzas() {
266         /**
267          * A waiter gets informed when a new pizza is complete. He takes the
268          * orderId of the pizza and looks up the corresponding order from which
269          * he gets the number of necessary pizzas of the order. He then tries to
270          * fetch all pizzas with the corresponding orderId and compares the
271          * number of those pizzas with the number of necessary pizzas. If all
272          * pizzas of an order are complete he then delivers them!
273          */
274         SpaceListener preparedPizzasListener = getDefaultBuilder().setLookaround(true).setCref(preparedPizzasContainer).setSpaceAction(new SpaceAction() {
275
276             @Override
277             public void onEntriesWritten(List<? extends Serializable> entries)
278                     throws Exception {
279                 log.info("NEW PIZZAS ARRived");
280
281                 List<Pizza> pizzas = castEntries(entries);
282
283                 for (Pizza pizza : pizzas) {
284                     int orderId = pizza.getOrderId();
285                     Order order = new Order();
286                     order.setId(orderId);
287
288                     TransactionReference tx = getDefaultTransaction();
289                     final boolean isDeliveryPizza = pizza.isDeliveryPizza();
290
291                     try {
292                         GroupData entity = new GroupData();
293                         entity.setState(GroupState.ORDERED);
294                         entity.setOrder(order);
295
296                         takeMatchingEntity(entity,
297                                 orderTakenContainer, tx, RequestTimeout.DEFAULT,
298                                 "Another waiter just checks if the order is complete");
299                         GroupData groupData = takeMatchingEntityIfItExists(entity,
300                                 pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
301                         int groupId = groupData.getId();
302                         int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
303
304                         Pizza pizzaTemplate = new Pizza();
305                         pizzaTemplate.setOrderId(orderId);
306
307                         List<Pizza> pizzasOfOrder = takeMatchingEntities(
308                                 pizzaTemplate, preparedPizzasContainer, tx,
309                                 RequestTimeout.DEFAULT,
310                                 "Cannot take the pizzas from the preparedPizzasContainer");
311
312                         final List<GroupData> groupsWithCompleteOrder = Arrays.asList(groupData);
313                         if (pizzasOfOrder.size() == numberOfPizzas) {
314                             for (PizzaOrder pizza1 : groupData.getOrder().getOrderedPizzas()) {
315                                 log.info("STAtus of pizza: {}", pizza1.getStatus());
316                             }
317                             groupData.setServingWaiter(waiterId);
318                             groupData.setState(GroupState.EATING);
319                             groupData.getOrder().setStatus(OrderStatus.DELIVERED);
320                             sendItemsToContainer(groupsWithCompleteOrder,
321                                     orderDeliveredContainer, RequestTimeout.DEFAULT,
322                                     tx);
323                             sendItemsToContainer(groupsWithCompleteOrder,
324                                     pizzeriaGroupContainer, RequestTimeout.DEFAULT,
325                                     tx);
326
327                             capi.commitTransaction(tx);
328                         } else {
329                             log.info("Not yet all pizzas prepared! Order with id "
330                                     + orderId + " has " + numberOfPizzas
331                                     + " pizzas, but only " + pizzasOfOrder.size()
332                                     + " pizzas are ready by now!");
333                             capi.rollbackTransaction(tx);
334                         }
335                     } catch (NullPointerException e) {
336
337                     } catch (Exception e) {
338                         capi.rollbackTransaction(tx);
339                     }
340                 }
341             }
342         }).createSpaceListenerImpl();
343     }
344
345     public void listenForPreparedDeliveryPizzas() {
346         /**
347          * A waiter gets informed when a new pizza is complete. He takes the
348          * orderId of the pizza and looks up the corresponding order from which
349          * he gets the number of necessary pizzas of the order. He then tries to
350          * fetch all pizzas with the corresponding orderId and compares the
351          * number of those pizzas with the number of necessary pizzas. If all
352          * pizzas of an order are complete he then delivers them!
353          */
354         SpaceListener preparedPizzasListener = getDefaultBuilder().setCref(preparedDeliveryPizzasContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
355
356             @Override
357             public void onEntriesWritten(List<? extends Serializable> entries)
358                     throws Exception {
359
360                 List<Pizza> pizzas = castEntries(entries);
361
362                 for (Pizza pizza : pizzas) {
363                     int orderId = pizza.getOrderId();
364                     Order order = new Order();
365                     order.setId(orderId);
366
367                     TransactionReference tx = getDefaultTransaction();
368
369                     try {
370                         DeliveryGroupData entity = new DeliveryGroupData();
371                         entity.setDeliveryStatus(null);
372                         entity.setOrder(order);
373
374                         DeliveryGroupData groupData = takeMatchingEntity(entity,
375                                 deliveryOrderTakenContainer, tx, RequestTimeout.DEFAULT,
376                                 "Another driver just checks if the delivery order is complete");
377                         int groupId = groupData.getId();
378                         int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
379
380                         Pizza pizzaTemplate = new Pizza();
381                         pizzaTemplate.setOrderId(orderId);
382
383                         List<Pizza> pizzasOfOrder = takeMatchingEntities(
384                                 pizzaTemplate, preparedDeliveryPizzasContainer, tx,
385                                 RequestTimeout.DEFAULT,
386                                 "Cannot take the pizzas from the preparedDeliveryPizzasContainer");
387
388                         if (pizzasOfOrder.size() == numberOfPizzas) {
389                             DeliveryGroupData group = new DeliveryGroupData();
390                             Order completeOrder = new Order();
391                             completeOrder.setId(orderId);
392                             completeOrder.setGroupId(groupId);
393                             group.setOrder(completeOrder);
394                             final List<DeliveryGroupData> groupsWithCompleteOrder = Arrays.asList(group);
395                             sendItemsToContainer(groupsWithCompleteOrder,
396                                     deliverDeliveryOrderContainer, RequestTimeout.DEFAULT,
397                                     tx);
398
399                             capi.commitTransaction(tx);
400                         } else {
401                             log.info("Not yet all pizzas prepared! Order with id "
402                                     + orderId + " has " + numberOfPizzas
403                                     + " pizzas, but only " + pizzasOfOrder.size()
404                                     + " pizzas are ready by now!");
405                             capi.rollbackTransaction(tx);
406                         }
407                     } catch (NullPointerException e) {
408
409                     } catch (Exception e) {
410                         capi.rollbackTransaction(tx);
411                     }
412                 }
413             }
414         }).createSpaceListenerImpl();
415     }
416
417
418     private void assignGroupToTable(GroupData lockedGroup,
419                                     Table lockedFreeTable, TransactionReference tx)
420             throws MzsCoreException {
421         // The new group sits down at the table
422         lockedFreeTable.setGroupId(lockedGroup.getId());
423
424         // The new group now wants to order
425         lockedGroup.setState(GroupState.SITTING);
426         lockedGroup.setTable(lockedFreeTable);
427         lockedGroup.setTableWaiter(waiterId);
428
429         final List<Table> freeTables = Arrays.asList(lockedFreeTable);
430         sendItemsToContainer(freeTables,
431                 pizzeriaTableContainer, RequestTimeout.ZERO, tx);
432         sendItemsToContainer(freeTables,
433                 tableAssignedContainer, RequestTimeout.ZERO, tx);
434         sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
435                 RequestTimeout.ZERO, tx);
436         sendItemsToContainer(Arrays.asList(lockedGroup), pizzeriaGroupContainer,
437                 RequestTimeout.ZERO, tx);
438
439         try {
440             capi.commitTransaction(tx);
441             log.info("Assigned table to group with groupId {}",
442                     lockedGroup.getId());
443         } catch (Exception e) {
444             log.info("Assigning a table to group with groupId {} failed",
445                     lockedGroup.getId());
446             log.info(e.getMessage());
447         }
448     }
449
450     private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
451     /*  get the id of the last order of the pizzeria and set the order accordingly and
452         update the space */
453         final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
454         final int id = orderId.getId();
455         final int nextId = id + 1;
456         order.setId(nextId);
457         final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
458         for (PizzaOrder orderedPizza : orderedPizzas) {
459             orderedPizza.setOrderId(nextId);
460         }
461         sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
462     }
463 }