1 package at.ac.tuwien.sbc.valesriegler.xvsm;
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;
14 import java.io.Serializable;
15 import java.util.Arrays;
16 import java.util.List;
18 public class WaiterXVSM extends AbstractXVSMConnector {
19 private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
20 private final int waiterId;
22 public WaiterXVSM(int waiterId, int port) {
25 this.waiterId = waiterId;
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);
47 public void listenForPhoneOrders() {
48 SpaceListener phoneListener = getDefaultBuilder().setCref(phoneCallsContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
50 public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
51 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
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);
58 final TransactionReference tx = getDefaultTransaction();
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);
65 updatePizzeriaOrderNumber(order, tx);
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);
76 log.info("Waiter has taken a phone delivery call!");
77 } catch (Exception e) {
82 }).createSpaceListenerImpl();
85 public void listenForFreeTable() {
86 SpaceListener listener = getDefaultBuilder().setCref(freeTablesContainer).setSpaceAction(new SpaceAction() {
89 public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
91 List<Table> tables = castEntries(entries);
93 for (Table table : tables) {
95 TransactionReference tx = getDefaultTransaction();
97 // Acquire a lock for the free table in the
99 int id = table.getId();
101 Table tableTemplate = new Table(id);
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);
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);
114 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
115 } catch (Exception e) {
116 // log.info(e.getMessage());
120 }).createSpaceListenerImpl();
124 public void listenForNewGuests() {
125 SpaceListener listener = getDefaultBuilder().setLookaround(true).setCref(assignTableContainer).setSpaceAction(new SpaceAction() {
128 public void onEntriesWritten(List<? extends Serializable> entries)
130 log.info("New guest groups have arrived");
132 List<GroupData> groups = castEntries(entries);
134 for (GroupData group : groups) {
136 TransactionReference tx = getDefaultTransaction();
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());
143 final GroupData templateGroup = new GroupData(group.getId());
144 GroupData lockedGroup = takeMatchingEntity(
146 assignTableContainer, tx,
147 RequestTimeout.DEFAULT, groupNotFound);
148 takeMatchingEntityIfItExists(templateGroup, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
149 // Acquire a lock for one free table in the
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,
156 takeMatchingEntityIfItExists(lockedFreeTable, pizzeriaTableContainer, tx, RequestTimeout.DEFAULT);
158 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
159 } catch (Exception e) {
160 // log.info(e.getMessage());
164 }).createSpaceListenerImpl();
167 public void listenForPaymentRequest() {
168 SpaceListener paymentListener = getDefaultBuilder().setCref(paymentRequestContainer).setSpaceAction(new SpaceAction() {
171 public void onEntriesWritten(List<? extends Serializable> entries)
174 List<GroupData> groups = castEntries(entries);
176 for (GroupData groupData : groups) {
177 TransactionReference tx = getDefaultTransaction();
178 GroupData entity = new GroupData(groupData.getId());
179 entity.setState(GroupState.PAY);
181 // Acquire the lock so that another waiter can't do the same
183 String paymentRequestTakenByOtherWaiter = String.format(
184 "The payment request for group %d was already taken by an other waiter!",
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);
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);
200 final List<GroupData> groupsPayed = Arrays.asList(group);
201 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.DEFAULT, tx);
202 sendItemsToContainer(groupsPayed, pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
204 capi.commitTransaction(tx);
205 } catch (Exception e) {
206 log.info(e.getMessage());
210 }).createSpaceListenerImpl();
213 public void listenForOrderRequests() {
214 SpaceListener ordersListener = getDefaultBuilder().setCref(takeOrderContainer).setSpaceAction(new SpaceAction() {
217 public void onEntriesWritten(List<? extends Serializable> entries)
220 List<GroupData> groups = castEntries(entries);
222 for (GroupData groupData : groups) {
224 TransactionReference tx = getDefaultTransaction();
225 GroupData entity = new GroupData(groupData.getId());
226 entity.setState(GroupState.SITTING);
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!",
233 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
234 GroupData group = takeMatchingEntityIfItExists(entity, pizzeriaGroupContainer, tx, RequestTimeout.DEFAULT);
236 group.setOrderWaiter(waiterId);
237 group.setState(GroupState.ORDERED);
238 Order order = group.getOrder();
239 order.setStatus(OrderStatus.ORDERED);
241 /* get the id of the last order of the pizzeria and set the order accordingly and
243 updatePizzeriaOrderNumber(order, tx);
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);
255 log.info("Waiter has taken order from group {}",
257 } catch (Exception e) {
258 // log.info(e.getMessage());
262 }).createSpaceListenerImpl();
265 public void listenForPreparedPizzas() {
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!
274 SpaceListener preparedPizzasListener = getDefaultBuilder().setLookaround(true).setCref(preparedPizzasContainer).setSpaceAction(new SpaceAction() {
277 public void onEntriesWritten(List<? extends Serializable> entries)
279 log.info("NEW PIZZAS ARRived");
281 List<Pizza> pizzas = castEntries(entries);
283 for (Pizza pizza : pizzas) {
284 int orderId = pizza.getOrderId();
285 Order order = new Order();
286 order.setId(orderId);
288 TransactionReference tx = getDefaultTransaction();
289 final boolean isDeliveryPizza = pizza.isDeliveryPizza();
292 GroupData entity = new GroupData();
293 entity.setState(GroupState.ORDERED);
294 entity.setOrder(order);
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();
304 Pizza pizzaTemplate = new Pizza();
305 pizzaTemplate.setOrderId(orderId);
307 List<Pizza> pizzasOfOrder = takeMatchingEntities(
308 pizzaTemplate, preparedPizzasContainer, tx,
309 RequestTimeout.DEFAULT,
310 "Cannot take the pizzas from the preparedPizzasContainer");
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());
317 groupData.setServingWaiter(waiterId);
318 groupData.setState(GroupState.EATING);
319 groupData.getOrder().setStatus(OrderStatus.DELIVERED);
320 sendItemsToContainer(groupsWithCompleteOrder,
321 orderDeliveredContainer, RequestTimeout.DEFAULT,
323 sendItemsToContainer(groupsWithCompleteOrder,
324 pizzeriaGroupContainer, RequestTimeout.DEFAULT,
327 capi.commitTransaction(tx);
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);
335 } catch (NullPointerException e) {
337 } catch (Exception e) {
338 capi.rollbackTransaction(tx);
342 }).createSpaceListenerImpl();
345 public void listenForPreparedDeliveryPizzas() {
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!
354 SpaceListener preparedPizzasListener = getDefaultBuilder().setCref(preparedDeliveryPizzasContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
357 public void onEntriesWritten(List<? extends Serializable> entries)
360 List<Pizza> pizzas = castEntries(entries);
362 for (Pizza pizza : pizzas) {
363 int orderId = pizza.getOrderId();
364 Order order = new Order();
365 order.setId(orderId);
367 TransactionReference tx = getDefaultTransaction();
370 DeliveryGroupData entity = new DeliveryGroupData();
371 entity.setDeliveryStatus(null);
372 entity.setOrder(order);
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();
380 Pizza pizzaTemplate = new Pizza();
381 pizzaTemplate.setOrderId(orderId);
383 List<Pizza> pizzasOfOrder = takeMatchingEntities(
384 pizzaTemplate, preparedDeliveryPizzasContainer, tx,
385 RequestTimeout.DEFAULT,
386 "Cannot take the pizzas from the preparedDeliveryPizzasContainer");
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,
399 capi.commitTransaction(tx);
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);
407 } catch (NullPointerException e) {
409 } catch (Exception e) {
410 capi.rollbackTransaction(tx);
414 }).createSpaceListenerImpl();
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());
424 // The new group now wants to order
425 lockedGroup.setState(GroupState.SITTING);
426 lockedGroup.setTable(lockedFreeTable);
427 lockedGroup.setTableWaiter(waiterId);
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);
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());
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
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;
457 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
458 for (PizzaOrder orderedPizza : orderedPizzas) {
459 orderedPizza.setOrderId(nextId);
461 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);