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 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);
45 public void listenForPhoneOrders() {
46 SpaceListener phoneListener = getDefaultBuilder().setCref(phoneCallsContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
48 public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
49 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
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);
56 final TransactionReference tx = getDefaultTransaction();
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);
63 updatePizzeriaOrderNumber(order, tx);
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);
74 log.info("Waiter has taken a phone delivery call!");
75 } catch (Exception e) {
80 }).createSpaceListenerImpl();
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
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;
90 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
91 for (PizzaOrder orderedPizza : orderedPizzas) {
92 orderedPizza.setOrderId(nextId);
94 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
98 public void listenForFreeTable() {
99 SpaceListener listener = getDefaultBuilder().setCref(freeTablesContainer).setSpaceAction(new SpaceAction() {
102 public void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
104 List<Table> tables = castEntries(entries);
106 for (Table table : tables) {
108 TransactionReference tx = getDefaultTransaction();
110 // Acquire a lock for the free table in the
111 // FreeTableContainer
112 int id = table.getId();
114 Table tableTemplate = new Table(id);
116 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
117 freeTablesContainer, tx, RequestTimeout.DEFAULT,
118 String.format("There was no free table found with id %d", id));
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");
126 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
127 } catch (Exception e) {
128 // log.info(e.getMessage());
132 }).createSpaceListenerImpl();
135 public void listenForNewGuests() {
136 SpaceListener listener = getDefaultBuilder().setCref(assignTableContainer).setSpaceAction(new SpaceAction() {
139 public void onEntriesWritten(List<? extends Serializable> entries)
141 log.info("New guest groups have arrived");
143 List<GroupData> groups = castEntries(entries);
145 for (GroupData group : groups) {
147 TransactionReference tx = getDefaultTransaction();
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());
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
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,
164 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
165 } catch (Exception e) {
166 // log.info(e.getMessage());
170 }).createSpaceListenerImpl();
173 public void listenForPaymentRequest() {
174 SpaceListener paymentListener = getDefaultBuilder().setCref(paymentRequestContainer).setSpaceAction(new SpaceAction() {
177 public void onEntriesWritten(List<? extends Serializable> entries)
180 List<GroupData> groups = castEntries(entries);
182 for (GroupData groupData : groups) {
183 TransactionReference tx = getDefaultTransaction();
184 GroupData entity = new GroupData(groupData.getId());
186 // Acquire the lock so that another waiter can't do the same
188 String paymentRequestTakenByOtherWaiter = String.format(
189 "The payment request for group %d was already taken by an other waiter!",
192 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
194 groupData.setPayingWaiter(waiterId);
196 final List<GroupData> groupsPayed = Arrays.asList(groupData);
197 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
199 capi.commitTransaction(tx);
200 } catch (Exception e) {
201 // log.info(e.getMessage());
205 }).createSpaceListenerImpl();
208 public void listenForOrderRequests() {
209 SpaceListener ordersListener = getDefaultBuilder().setCref(takeOrderContainer).setSpaceAction(new SpaceAction() {
212 public void onEntriesWritten(List<? extends Serializable> entries)
215 List<GroupData> groups = castEntries(entries);
217 for (GroupData groupData : groups) {
219 TransactionReference tx = getDefaultTransaction();
220 GroupData entity = new GroupData(groupData.getId());
221 entity.setState(GroupState.SITTING);
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!",
228 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
230 groupData.setOrderWaiter(waiterId);
231 groupData.setState(GroupState.ORDERED);
232 Order order = groupData.getOrder();
233 order.setStatus(OrderStatus.ORDERED);
235 /* get the id of the last order of the pizzeria and set the order accordingly and
237 updatePizzeriaOrderNumber(order, tx);
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);
247 log.info("Waiter has taken order from group {}",
249 } catch (Exception e) {
250 // log.info(e.getMessage());
254 }).createSpaceListenerImpl();
257 public void listenForPreparedPizzas() {
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!
266 SpaceListener preparedPizzasListener = getDefaultBuilder().setCref(preparedPizzasContainer).setSpaceAction(new SpaceAction() {
269 public void onEntriesWritten(List<? extends Serializable> entries)
272 List<Pizza> pizzas = castEntries(entries);
274 for (Pizza pizza : pizzas) {
275 int orderId = pizza.getOrderId();
276 Order order = new Order();
277 order.setId(orderId);
279 TransactionReference tx = getDefaultTransaction();
280 final boolean isDeliveryPizza = pizza.isDeliveryPizza();
283 GroupData entity = new GroupData();
284 entity.setState(null);
285 entity.setOrder(order);
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();
293 Pizza pizzaTemplate = new Pizza();
294 pizzaTemplate.setOrderId(orderId);
296 List<Pizza> pizzasOfOrder = takeMatchingEntities(
297 pizzaTemplate, preparedPizzasContainer, tx,
298 RequestTimeout.DEFAULT,
299 "Cannot take the pizzas from the preparedPizzasContainer");
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,
313 capi.commitTransaction(tx);
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);
321 } catch (NullPointerException e) {
323 } catch (Exception e) {
324 capi.rollbackTransaction(tx);
328 }).createSpaceListenerImpl();
332 public void listenForPreparedDeliveryPizzas() {
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!
341 SpaceListener preparedPizzasListener = getDefaultBuilder().setCref(preparedDeliveryPizzasContainer).setLookaround(true).setSpaceAction(new SpaceAction() {
344 public void onEntriesWritten(List<? extends Serializable> entries)
347 List<Pizza> pizzas = castEntries(entries);
349 for (Pizza pizza : pizzas) {
350 int orderId = pizza.getOrderId();
351 Order order = new Order();
352 order.setId(orderId);
354 TransactionReference tx = getDefaultTransaction();
357 DeliveryGroupData entity = new DeliveryGroupData();
358 entity.setDeliveryStatus(null);
359 entity.setOrder(order);
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();
367 Pizza pizzaTemplate = new Pizza();
368 pizzaTemplate.setOrderId(orderId);
370 List<Pizza> pizzasOfOrder = takeMatchingEntities(
371 pizzaTemplate, preparedDeliveryPizzasContainer, tx,
372 RequestTimeout.DEFAULT,
373 "Cannot take the pizzas from the preparedDeliveryPizzasContainer");
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,
386 capi.commitTransaction(tx);
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);
394 } catch (NullPointerException e) {
396 } catch (Exception e) {
397 capi.rollbackTransaction(tx);
401 }).createSpaceListenerImpl();
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());
410 // The new group now wants to order
411 lockedGroup.setState(GroupState.SITTING);
412 lockedGroup.setTable(lockedFreeTable);
413 lockedGroup.setTableWaiter(waiterId);
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);
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());