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