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 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;
13 import java.io.Serializable;
14 import java.util.Arrays;
15 import java.util.List;
17 public class WaiterXVSM extends AbstractXVSMConnector {
18 private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
19 private final int waiterId;
21 public WaiterXVSM(int waiterId, int port) {
24 this.waiterId = waiterId;
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 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
32 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
33 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
34 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
35 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
36 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
37 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
38 pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
39 phoneCallsContainer = useContainer(Util.PHONE_CALLS);
40 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
41 deliverDeliveryOrder = useContainer(Util.DELIVER_DELIVERY_ORDER);
44 public void listenForPhoneOrders() {
45 SpaceListener phoneListener = new SpaceListenerImpl(capi, phoneCallsContainer, true) {
47 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
48 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
50 for (DeliveryGroupData phoneOrder : phoneOrders) {
51 final int id = phoneOrder.getId();
52 final DeliveryGroupData template = new DeliveryGroupData(id);
53 final String errorMsg = String.format("There was phone call with id %d", id);
55 final TransactionReference tx = getDefaultTransaction();
57 final DeliveryGroupData groupFromSpace = takeMatchingEntity(template, phoneCallsContainer, tx, RequestTimeout.DEFAULT, errorMsg);
58 groupFromSpace.setWaiterIdOfOrder(WaiterXVSM.this.waiterId);
59 final Order order = groupFromSpace.getOrder();
60 groupFromSpace.setDeliveryStatus(DeliveryStatus.ORDERED);
62 updatePizzeriaOrderNumber(order, tx);
65 // send the order as a whole to the space
66 final List<DeliveryGroupData> groupsWhoHaveOrdered = Arrays.asList(groupFromSpace);
67 sendItemsToContainer(groupsWhoHaveOrdered,
68 deliveryOrderTakenContainer, RequestTimeout.ZERO, tx);
69 sendItemsToContainer(order.getOrderedPizzas(),
70 prepareDeliveryPizzasContainer, RequestTimeout.ZERO, tx);
71 capi.commitTransaction(tx);
73 log.info("Waiter has taken a phone delivery call!");
74 } catch (Exception e) {
82 createNotification(phoneListener, phoneCallsContainer);
85 private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
86 /* get the id of the last order of the pizzeria and set the order accordingly and
88 final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
89 final int id = orderId.getId();
90 final int nextId = id + 1;
92 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
93 for (PizzaOrder orderedPizza : orderedPizzas) {
94 orderedPizza.setOrderId(nextId);
96 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
100 public void listenForFreeTable() {
101 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
104 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
106 List<Table> tables = castEntries(entries);
108 for (Table table : tables) {
110 TransactionReference tx = getDefaultTransaction();
112 // Acquire a lock for the free table in the
113 // FreeTableContainer
114 int id = table.getId();
116 Table tableTemplate = new Table(id);
118 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
119 freeTablesContainer, tx, RequestTimeout.DEFAULT,
120 String.format("There was no free table found with id %d", id));
123 GroupData groupTemplate = new GroupData();
124 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
125 assignTableContainer, tx, RequestTimeout.DEFAULT,
126 "There is no group waiting for a table at the moment");
128 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
129 } catch (Exception e) {
130 // log.info(e.getMessage());
136 createNotification(listener, freeTablesContainer);
139 public void listenForNewGuests() {
140 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
143 void onEntriesWritten(List<? extends Serializable> entries)
145 log.info("New guest groups have arrived");
147 List<GroupData> groups = castEntries(entries);
149 for (GroupData group : groups) {
151 TransactionReference tx = getDefaultTransaction();
153 // Acquire a lock for the group in the
154 // AssignTableContainer
155 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
158 GroupData lockedGroup = takeMatchingEntity(
159 new GroupData(group.getId()),
160 assignTableContainer, tx,
161 RequestTimeout.DEFAULT, groupNotFound);
162 // Acquire a lock for one free table in the
164 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
165 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
168 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
169 } catch (Exception e) {
170 // log.info(e.getMessage());
176 createNotification(listener, assignTableContainer);
179 public void listenForPaymentRequest() {
180 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
183 void onEntriesWritten(List<? extends Serializable> entries)
186 List<GroupData> groups = castEntries(entries);
188 for (GroupData groupData : groups) {
189 TransactionReference tx = getDefaultTransaction();
190 GroupData entity = new GroupData(groupData.getId());
192 // Acquire the lock so that another waiter can't do the same
194 String paymentRequestTakenByOtherWaiter = String.format(
195 "The payment request for group %d was already taken by an other waiter!",
198 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
200 groupData.setPayingWaiter(waiterId);
202 final List<GroupData> groupsPayed = Arrays.asList(groupData);
203 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
205 capi.commitTransaction(tx);
206 } catch (Exception e) {
207 // log.info(e.getMessage());
213 createNotification(paymentListener, paymentRequestContainer);
216 public void listenForOrderRequests() {
217 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
220 void onEntriesWritten(List<? extends Serializable> entries)
223 List<GroupData> groups = castEntries(entries);
225 for (GroupData groupData : groups) {
227 TransactionReference tx = getDefaultTransaction();
228 GroupData entity = new GroupData(groupData.getId());
229 entity.setState(GroupState.SITTING);
232 // Acquire the lock so that another waiter can't do the same thing!
233 String orderTakenByOtherWaiter = String.format(
234 "The order for group %d was already taken by an other waiter!",
236 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
238 groupData.setOrderWaiter(waiterId);
239 groupData.setState(GroupState.ORDERED);
240 Order order = groupData.getOrder();
241 order.setStatus(OrderStatus.ORDERED);
243 /* get the id of the last order of the pizzeria and set the order accordingly and
245 updatePizzeriaOrderNumber(order, tx);
247 // send the order as a whole to the space
248 final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(groupData);
249 sendItemsToContainer(groupsWhoHaveOrdered,
250 orderTakenContainer, 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());
264 createNotification(ordersListener, takeOrderContainer);
267 public void listenForPreparedPizzas() {
269 * A waiter gets informed when a new pizza is complete. He takes the
270 * orderId of the pizza and looks up the corresponding order from which
271 * he gets the number of necessary pizzas of the order. He then tries to
272 * fetch all pizzas with the corresponding orderId and compares the
273 * number of those pizzas with the number of necessary pizzas. If all
274 * pizzas of an order are complete he then delivers them!
276 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, preparedPizzasContainer) {
279 void onEntriesWritten(List<? extends Serializable> entries)
282 List<Pizza> pizzas = castEntries(entries);
284 for (Pizza pizza : pizzas) {
285 int orderId = pizza.getOrderId();
286 Order order = new Order();
287 order.setId(orderId);
289 TransactionReference tx = getDefaultTransaction();
290 final boolean isDeliveryPizza = pizza.isDeliveryPizza();
293 GroupData entity = new GroupData();
294 entity.setState(null);
295 entity.setOrder(order);
297 GroupData groupData = takeMatchingEntity(entity,
298 orderTakenContainer, tx, RequestTimeout.DEFAULT,
299 "Another waiter just checks if the order is complete");
300 int groupId = groupData.getId();
301 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
303 Pizza pizzaTemplate = new Pizza();
304 pizzaTemplate.setOrderId(orderId);
306 List<Pizza> pizzasOfOrder = takeMatchingEntities(
307 pizzaTemplate, preparedPizzasContainer, tx,
308 RequestTimeout.DEFAULT,
309 "Cannot take the pizzas from the preparedPizzasContainer");
311 if (pizzasOfOrder.size() == numberOfPizzas) {
312 GroupData group = new GroupData();
313 group.setServingWaiter(waiterId);
314 Order completeOrder = new Order();
315 completeOrder.setId(orderId);
316 completeOrder.setGroupId(groupId);
317 group.setOrder(completeOrder);
318 final List<GroupData> groupsWithCompleteOrder = Arrays.asList(group);
319 sendItemsToContainer(groupsWithCompleteOrder,
320 orderCompleteContainer, RequestTimeout.DEFAULT,
323 capi.commitTransaction(tx);
325 log.info("Not yet all pizzas prepared! Order with id "
326 + orderId + " has " + numberOfPizzas
327 + " pizzas, but only " + pizzasOfOrder.size()
328 + " pizzas are ready by now!");
329 capi.rollbackTransaction(tx);
331 } catch (NullPointerException e) {
333 } catch (Exception e) {
334 capi.rollbackTransaction(tx);
340 createNotification(preparedPizzasListener, preparedPizzasContainer);
344 public void listenForPreparedDeliveryPizzas() {
346 * A waiter gets informed when a new pizza is complete. He takes the
347 * orderId of the pizza and looks up the corresponding order from which
348 * he gets the number of necessary pizzas of the order. He then tries to
349 * fetch all pizzas with the corresponding orderId and compares the
350 * number of those pizzas with the number of necessary pizzas. If all
351 * pizzas of an order are complete he then delivers them!
353 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, preparedDeliveryPizzasContainer, true) {
356 void onEntriesWritten(List<? extends Serializable> entries)
359 List<Pizza> pizzas = castEntries(entries);
361 for (Pizza pizza : pizzas) {
362 int orderId = pizza.getOrderId();
363 Order order = new Order();
364 order.setId(orderId);
366 TransactionReference tx = getDefaultTransaction();
369 DeliveryGroupData entity = new DeliveryGroupData();
370 entity.setDeliveryStatus(null);
371 entity.setOrder(order);
373 DeliveryGroupData groupData = takeMatchingEntity(entity,
374 deliveryOrderTakenContainer, tx, MzsConstants.RequestTimeout.DEFAULT,
375 "Another driver just checks if the delivery order is complete");
376 int groupId = groupData.getId();
377 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
379 Pizza pizzaTemplate = new Pizza();
380 pizzaTemplate.setOrderId(orderId);
382 List<Pizza> pizzasOfOrder = takeMatchingEntities(
383 pizzaTemplate, preparedDeliveryPizzasContainer, tx,
384 MzsConstants.RequestTimeout.DEFAULT,
385 "Cannot take the pizzas from the preparedDeliveryPizzasContainer");
387 if (pizzasOfOrder.size() == numberOfPizzas) {
388 DeliveryGroupData group = new DeliveryGroupData();
389 Order completeOrder = new Order();
390 completeOrder.setId(orderId);
391 completeOrder.setGroupId(groupId);
392 group.setOrder(completeOrder);
393 final List<DeliveryGroupData> groupsWithCompleteOrder = Arrays.asList(group);
394 sendItemsToContainer(groupsWithCompleteOrder,
395 deliverDeliveryOrder, MzsConstants.RequestTimeout.DEFAULT,
398 capi.commitTransaction(tx);
400 log.info("Not yet all pizzas prepared! Order with id "
401 + orderId + " has " + numberOfPizzas
402 + " pizzas, but only " + pizzasOfOrder.size()
403 + " pizzas are ready by now!");
404 capi.rollbackTransaction(tx);
406 } catch (NullPointerException e) {
408 } catch (Exception e) {
409 capi.rollbackTransaction(tx);
415 createNotification(preparedPizzasListener, preparedDeliveryPizzasContainer);
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 tableAssignedContainer, RequestTimeout.ZERO, tx);
432 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
433 RequestTimeout.ZERO, tx);
436 capi.commitTransaction(tx);
437 log.info("Assigned table to group with groupId {}",
438 lockedGroup.getId());
439 } catch (Exception e) {
440 log.info("Assigning a table to group with groupId {} failed",
441 lockedGroup.getId());
442 log.info(e.getMessage());