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 groupAgentOrderTakenContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_TAKEN, Util.GROUP_AGENT_PORT);
32 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
33 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
34 groupAgentOrderCompleteContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_COMPLETE, Util.GROUP_AGENT_PORT);
35 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
36 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
37 groupAgentPaymentRequestContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_REQUEST, Util.GROUP_AGENT_PORT);
38 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
39 groupAgentPaymentDoneContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_DONE, Util.GROUP_AGENT_PORT);
40 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
41 groupAgentTableAssignedContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_TABLE_ASSIGNED, Util.GROUP_AGENT_PORT);
42 pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
43 phoneCallsContainer = useContainer(Util.PHONE_CALLS);
44 groupAgentDeliveryOrderTakenContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_DELIVERY_ORDER_TAKEN, Util.GROUP_AGENT_PORT);
47 public void listenForPhoneOrders() {
48 SpaceListener phoneListener = new SpaceListenerImpl(capi, phoneCallsContainer, true) {
50 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 preparePizzasContainer, RequestTimeout.ZERO, tx);
74 sendItemsToContainer(groupsWhoHaveOrdered,
75 groupAgentDeliveryOrderTakenContainer, RequestTimeout.ZERO, null);
76 capi.commitTransaction(tx);
78 log.info("Waite has taken a phone delivery call!");
79 } catch (Exception e) {
87 createNotification(phoneListener, phoneCallsContainer);
90 private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
91 /* get the id of the last order of the pizzeria and set the order accordingly and
93 final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
94 final int id = orderId.getId();
95 final int nextId = id + 1;
97 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
98 for (PizzaOrder orderedPizza : orderedPizzas) {
99 orderedPizza.setOrderId(nextId);
101 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
105 public void listenForFreeTable() {
106 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
109 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
111 List<Table> tables = castEntries(entries);
113 for (Table table : tables) {
115 TransactionReference tx = getDefaultTransaction();
117 // Acquire a lock for the free table in the
118 // FreeTableContainer
119 int id = table.getId();
121 Table tableTemplate = new Table(id);
123 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
124 freeTablesContainer, tx, RequestTimeout.DEFAULT,
125 String.format("There was no free table found with id %d", id));
128 GroupData groupTemplate = new GroupData();
129 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
130 assignTableContainer, tx, RequestTimeout.DEFAULT,
131 "There is no group waiting for a table at the moment");
133 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
134 } catch (Exception e) {
135 // log.info(e.getMessage());
141 createNotification(listener, freeTablesContainer);
144 public void listenForNewGuests() {
145 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
148 void onEntriesWritten(List<? extends Serializable> entries)
150 log.info("New guest groups have arrived");
152 List<GroupData> groups = castEntries(entries);
154 for (GroupData group : groups) {
156 TransactionReference tx = getDefaultTransaction();
158 // Acquire a lock for the group in the
159 // AssignTableContainer
160 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
163 GroupData lockedGroup = takeMatchingEntity(
164 new GroupData(group.getId()),
165 assignTableContainer, tx,
166 RequestTimeout.DEFAULT, groupNotFound);
167 // Acquire a lock for one free table in the
169 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
170 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
173 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
174 } catch (Exception e) {
175 // log.info(e.getMessage());
181 createNotification(listener, assignTableContainer);
184 public void listenForPaymentRequest() {
185 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
188 void onEntriesWritten(List<? extends Serializable> entries)
191 List<GroupData> groups = castEntries(entries);
193 for (GroupData groupData : groups) {
194 TransactionReference tx = getDefaultTransaction();
195 GroupData entity = new GroupData(groupData.getId());
197 // Acquire the lock so that another waiter can't do the same
199 String paymentRequestTakenByOtherWaiter = String.format(
200 "The payment request for group %d was already taken by an other waiter!",
203 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
205 groupData.setPayingWaiter(waiterId);
207 final List<GroupData> groupsPayed = Arrays.asList(groupData);
208 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
209 sendItemsToContainer(groupsPayed, groupAgentPaymentDoneContainer, RequestTimeout.ZERO, null);
211 capi.commitTransaction(tx);
212 } catch (Exception e) {
213 // log.info(e.getMessage());
219 createNotification(paymentListener, paymentRequestContainer);
222 public void listenForOrderRequests() {
223 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
226 void onEntriesWritten(List<? extends Serializable> entries)
229 List<GroupData> groups = castEntries(entries);
231 for (GroupData groupData : groups) {
233 TransactionReference tx = getDefaultTransaction();
234 GroupData entity = new GroupData(groupData.getId());
235 entity.setState(GroupState.SITTING);
238 // Acquire the lock so that another waiter can't do the same thing!
239 String orderTakenByOtherWaiter = String.format(
240 "The order for group %d was already taken by an other waiter!",
242 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
244 groupData.setOrderWaiter(waiterId);
245 groupData.setState(GroupState.ORDERED);
246 Order order = groupData.getOrder();
247 order.setStatus(OrderStatus.ORDERED);
249 /* get the id of the last order of the pizzeria and set the order accordingly and
251 updatePizzeriaOrderNumber(order, tx);
253 // send the order as a whole to the space
254 final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(groupData);
255 sendItemsToContainer(groupsWhoHaveOrdered,
256 orderTakenContainer, RequestTimeout.ZERO, tx);
257 sendItemsToContainer(order.getOrderedPizzas(),
258 preparePizzasContainer, RequestTimeout.ZERO, tx);
259 sendItemsToContainer(groupsWhoHaveOrdered,
260 groupAgentOrderTakenContainer, RequestTimeout.ZERO, null);
261 capi.commitTransaction(tx);
263 log.info("Waiter has taken order from group {}",
265 } catch (Exception e) {
266 // log.info(e.getMessage());
272 createNotification(ordersListener, takeOrderContainer);
275 public void listenForPreparedPizzas() {
277 * A waiter gets informed when a new pizza is complete. He takes the
278 * orderId of the pizza and looks up the corresponding order from which
279 * he gets the number of necessary pizzas of the order. He then tries to
280 * fetch all pizzas with the corresponding orderId and compares the
281 * number of those pizzas with the number of necessary pizzas. If all
282 * pizzas of an order are complete he then delivers them!
284 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
287 void onEntriesWritten(List<? extends Serializable> entries)
290 List<Pizza> pizzas = castEntries(entries);
292 for (Pizza pizza : pizzas) {
293 int orderId = pizza.getOrderId();
294 Order order = new Order();
295 order.setId(orderId);
297 TransactionReference tx = getDefaultTransaction();
298 final boolean isDeliveryPizza = pizza.isDeliveryPizza();
301 GroupData entity = new GroupData();
302 entity.setState(null);
303 entity.setOrder(order);
305 GroupData groupData = takeMatchingEntity(entity,
306 orderTakenContainer, tx, RequestTimeout.DEFAULT,
307 "Another waiter just checks if the order is complete");
308 int groupId = groupData.getId();
309 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
311 Pizza pizzaTemplate = new Pizza();
312 pizzaTemplate.setOrderId(orderId);
314 List<Pizza> pizzasOfOrder = takeMatchingEntities(
315 pizzaTemplate, deliverPizzasContainer, tx,
316 RequestTimeout.DEFAULT,
317 "Cannot take the pizzas from the deliverPizzasContainer");
319 if (pizzasOfOrder.size() == numberOfPizzas) {
320 GroupData group = new GroupData();
321 group.setServingWaiter(waiterId);
322 Order completeOrder = new Order();
323 completeOrder.setId(orderId);
324 completeOrder.setGroupId(groupId);
325 group.setOrder(completeOrder);
326 final List<GroupData> groupsWithCompleteOrder = Arrays.asList(group);
327 sendItemsToContainer(groupsWithCompleteOrder,
328 orderCompleteContainer, RequestTimeout.DEFAULT,
330 sendItemsToContainer(groupsWithCompleteOrder,
331 groupAgentOrderCompleteContainer, RequestTimeout.DEFAULT,
334 capi.commitTransaction(tx);
336 log.info("Not yet all pizzas prepared! Order with id "
337 + orderId + " has " + numberOfPizzas
338 + " pizzas, but only " + pizzasOfOrder.size()
339 + " pizzas are ready by now!");
340 capi.rollbackTransaction(tx);
342 } catch (NullPointerException e) {
344 } catch (Exception e) {
345 capi.rollbackTransaction(tx);
351 createNotification(preparedPizzasListener, deliverPizzasContainer);
354 private void assignGroupToTable(GroupData lockedGroup,
355 Table lockedFreeTable, TransactionReference tx)
356 throws MzsCoreException {
357 // The new group sits down at the table
358 lockedFreeTable.setGroupId(lockedGroup.getId());
360 // The new group now wants to order
361 lockedGroup.setState(GroupState.SITTING);
362 lockedGroup.setTable(lockedFreeTable);
363 lockedGroup.setTableWaiter(waiterId);
365 final List<Table> freeTables = Arrays.asList(lockedFreeTable);
366 sendItemsToContainer(freeTables,
367 tableAssignedContainer, RequestTimeout.ZERO, tx);
368 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
369 RequestTimeout.ZERO, tx);
370 sendItemsToContainer(freeTables,
371 groupAgentTableAssignedContainer, RequestTimeout.ZERO, null);
374 capi.commitTransaction(tx);
375 log.info("Assigned table to group with groupId {}",
376 lockedGroup.getId());
377 } catch (Exception e) {
378 log.info("Assigning a table to group with groupId {} failed",
379 lockedGroup.getId());
380 log.info(e.getMessage());