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 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
33 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
34 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
35 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
36 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
37 pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
38 phoneCallsContainer = useContainer(Util.PHONE_CALLS);
41 public void listenForPhoneOrders() {
42 SpaceListener phoneListener = new SpaceListenerImpl(capi, phoneCallsContainer, true) {
44 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
45 final List<DeliveryGroupData> phoneOrders = castEntries(entries);
47 for (DeliveryGroupData phoneOrder : phoneOrders) {
48 final int id = phoneOrder.getId();
49 final DeliveryGroupData template = new DeliveryGroupData(id);
50 final String errorMsg = String.format("There was phone call with id %d", id);
52 final TransactionReference tx = getDefaultTransaction();
54 final DeliveryGroupData groupFromSpace = takeMatchingEntity(template, phoneCallsContainer, tx, RequestTimeout.DEFAULT, errorMsg);
55 groupFromSpace.setWaiterIdOfOrder(WaiterXVSM.this.waiterId);
56 final Order order = groupFromSpace.getOrder();
57 groupFromSpace.setDeliveryStatus(DeliveryStatus.ORDERED);
59 updatePizzeriaOrderNumber(order, tx);
62 // send the order as a whole to the space
63 final List<DeliveryGroupData> groupsWhoHaveOrdered = Arrays.asList(groupFromSpace);
64 sendItemsToContainer(groupsWhoHaveOrdered,
65 deliveryOrderTakenContainer, RequestTimeout.ZERO, tx);
66 sendItemsToContainer(order.getOrderedPizzas(),
67 preparePizzasContainer, RequestTimeout.ZERO, tx);
68 capi.commitTransaction(tx);
70 log.info("Waite has taken a phone delivery call!");
71 } catch (Exception e) {
79 createNotification(phoneListener, phoneCallsContainer);
82 private void updatePizzeriaOrderNumber(Order order, TransactionReference tx) throws MzsCoreException {
83 /* get the id of the last order of the pizzeria and set the order accordingly and
85 final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
86 final int id = orderId.getId();
87 final int nextId = id + 1;
89 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
90 for (PizzaOrder orderedPizza : orderedPizzas) {
91 orderedPizza.setOrderId(nextId);
93 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
97 public void listenForFreeTable() {
98 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
101 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
103 List<Table> tables = castEntries(entries);
105 for (Table table : tables) {
107 TransactionReference tx = getDefaultTransaction();
109 // Acquire a lock for the free table in the
110 // FreeTableContainer
111 int id = table.getId();
113 Table tableTemplate = new Table(id);
115 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
116 freeTablesContainer, tx, RequestTimeout.DEFAULT,
117 String.format("There was no free table found with id %d", id));
120 GroupData groupTemplate = new GroupData();
121 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
122 assignTableContainer, tx, RequestTimeout.DEFAULT,
123 "There is no group waiting for a table at the moment");
125 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
126 } catch (Exception e) {
127 // log.info(e.getMessage());
133 createNotification(listener, freeTablesContainer);
136 public void listenForNewGuests() {
137 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
140 void onEntriesWritten(List<? extends Serializable> entries)
142 log.info("New guest groups have arrived");
144 List<GroupData> groups = castEntries(entries);
146 for (GroupData group : groups) {
148 TransactionReference tx = getDefaultTransaction();
150 // Acquire a lock for the group in the
151 // AssignTableContainer
152 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
155 GroupData lockedGroup = takeMatchingEntity(
156 new GroupData(group.getId()),
157 assignTableContainer, tx,
158 RequestTimeout.DEFAULT, groupNotFound);
159 // Acquire a lock for one free table in the
161 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
162 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
165 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
166 } catch (Exception e) {
167 // log.info(e.getMessage());
173 createNotification(listener, assignTableContainer);
176 public void listenForPaymentRequest() {
177 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
180 void onEntriesWritten(List<? extends Serializable> entries)
183 List<GroupData> groups = castEntries(entries);
185 for (GroupData groupData : groups) {
186 TransactionReference tx = getDefaultTransaction();
187 GroupData entity = new GroupData(groupData.getId());
189 // Acquire the lock so that another waiter can't do the same
191 String paymentRequestTakenByOtherWaiter = String.format(
192 "The payment request for group %d was already taken by an other waiter!",
195 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
197 groupData.setPayingWaiter(waiterId);
199 final List<GroupData> groupsPayed = Arrays.asList(groupData);
200 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
202 capi.commitTransaction(tx);
203 } catch (Exception e) {
204 // log.info(e.getMessage());
210 createNotification(paymentListener, paymentRequestContainer);
213 public void listenForOrderRequests() {
214 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
217 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);
235 groupData.setOrderWaiter(waiterId);
236 groupData.setState(GroupState.ORDERED);
237 Order order = groupData.getOrder();
238 order.setStatus(OrderStatus.ORDERED);
240 /* get the id of the last order of the pizzeria and set the order accordingly and
242 updatePizzeriaOrderNumber(order, tx);
244 // send the order as a whole to the space
245 final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(groupData);
246 sendItemsToContainer(groupsWhoHaveOrdered,
247 orderTakenContainer, RequestTimeout.ZERO, tx);
248 sendItemsToContainer(order.getOrderedPizzas(),
249 preparePizzasContainer, RequestTimeout.ZERO, tx);
250 capi.commitTransaction(tx);
252 log.info("Waiter has taken order from group {}",
254 } catch (Exception e) {
255 // log.info(e.getMessage());
261 createNotification(ordersListener, takeOrderContainer);
264 public void listenForPreparedPizzas() {
266 * A waiter gets informed when a new pizza is complete. He takes the
267 * orderId of the pizza and looks up the corresponding order from which
268 * he gets the number of necessary pizzas of the order. He then tries to
269 * fetch all pizzas with the corresponding orderId and compares the
270 * number of those pizzas with the number of necessary pizzas. If all
271 * pizzas of an order are complete he then delivers them!
273 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
276 void onEntriesWritten(List<? extends Serializable> entries)
279 List<Pizza> pizzas = castEntries(entries);
281 for (Pizza pizza : pizzas) {
282 int orderId = pizza.getOrderId();
283 Order order = new Order();
284 order.setId(orderId);
286 TransactionReference tx = getDefaultTransaction();
287 final boolean isDeliveryPizza = pizza.isDeliveryPizza();
290 GroupData entity = new GroupData();
291 entity.setState(null);
292 entity.setOrder(order);
294 GroupData groupData = takeMatchingEntity(entity,
295 orderTakenContainer, tx, RequestTimeout.DEFAULT,
296 "Another waiter just checks if the order is complete");
297 int groupId = groupData.getId();
298 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
300 Pizza pizzaTemplate = new Pizza();
301 pizzaTemplate.setOrderId(orderId);
303 List<Pizza> pizzasOfOrder = takeMatchingEntities(
304 pizzaTemplate, deliverPizzasContainer, tx,
305 RequestTimeout.DEFAULT,
306 "Cannot take the pizzas from the deliverPizzasContainer");
308 if (pizzasOfOrder.size() == numberOfPizzas) {
309 GroupData group = new GroupData();
310 group.setServingWaiter(waiterId);
311 Order completeOrder = new Order();
312 completeOrder.setId(orderId);
313 completeOrder.setGroupId(groupId);
314 group.setOrder(completeOrder);
315 final List<GroupData> groupsWithCompleteOrder = Arrays.asList(group);
316 sendItemsToContainer(groupsWithCompleteOrder,
317 orderCompleteContainer, RequestTimeout.DEFAULT,
320 capi.commitTransaction(tx);
322 log.info("Not yet all pizzas prepared! Order with id "
323 + orderId + " has " + numberOfPizzas
324 + " pizzas, but only " + pizzasOfOrder.size()
325 + " pizzas are ready by now!");
326 capi.rollbackTransaction(tx);
328 } catch (NullPointerException e) {
330 } catch (Exception e) {
331 capi.rollbackTransaction(tx);
337 createNotification(preparedPizzasListener, deliverPizzasContainer);
340 private void assignGroupToTable(GroupData lockedGroup,
341 Table lockedFreeTable, TransactionReference tx)
342 throws MzsCoreException {
343 // The new group sits down at the table
344 lockedFreeTable.setGroupId(lockedGroup.getId());
346 // The new group now wants to order
347 lockedGroup.setState(GroupState.SITTING);
348 lockedGroup.setTable(lockedFreeTable);
349 lockedGroup.setTableWaiter(waiterId);
351 final List<Table> freeTables = Arrays.asList(lockedFreeTable);
352 sendItemsToContainer(freeTables,
353 tableAssignedContainer, RequestTimeout.ZERO, tx);
354 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
355 RequestTimeout.ZERO, tx);
358 capi.commitTransaction(tx);
359 log.info("Assigned table to group with groupId {}",
360 lockedGroup.getId());
361 } catch (Exception e) {
362 log.info("Assigning a table to group with groupId {} failed",
363 lockedGroup.getId());
364 log.info(e.getMessage());