1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import java.io.Serializable;
4 import java.util.Arrays;
7 import at.ac.tuwien.sbc.valesriegler.common.OrderId;
8 import at.ac.tuwien.sbc.valesriegler.types.*;
9 import org.mozartspaces.core.MzsConstants.RequestTimeout;
10 import org.mozartspaces.core.MzsCoreException;
11 import org.mozartspaces.core.TransactionReference;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
15 import at.ac.tuwien.sbc.valesriegler.common.Util;
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 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
31 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
32 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
33 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
34 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
35 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
36 infoContainer = useContainer(Util.INFO);
39 public void listenForFreeTable() {
40 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
43 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
45 List<Table> tables = castEntries(entries);
47 for (Table table : tables) {
49 TransactionReference tx = getDefaultTransaction();
51 // Acquire a lock for the free table in the
53 int id = table.getId();
55 Table tableTemplate = new Table(id);
57 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
58 freeTablesContainer, tx, RequestTimeout.DEFAULT,
59 String.format("There was no free table found with id %d", id));
62 GroupData groupTemplate = new GroupData();
63 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
64 assignTableContainer, tx, RequestTimeout.DEFAULT,
65 "There is no group waiting for a table at the moment");
67 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
68 } catch (Exception e) {
69 // log.info(e.getMessage());
75 createNotification(listener, freeTablesContainer);
80 public void listenForNewGuests() {
81 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
84 void onEntriesWritten(List<? extends Serializable> entries)
86 log.info("New guest groups have arrived");
88 List<GroupData> groups = castEntries(entries);
90 for (GroupData group : groups) {
92 TransactionReference tx = getDefaultTransaction();
94 // Acquire a lock for the group in the
95 // AssignTableContainer
96 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
99 GroupData lockedGroup = takeMatchingEntity(
100 new GroupData(group.getId()),
101 assignTableContainer, tx,
102 RequestTimeout.DEFAULT, groupNotFound);
103 // Acquire a lock for one free table in the
105 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
106 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
109 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
110 } catch (Exception e) {
111 // log.info(e.getMessage());
117 createNotification(listener, assignTableContainer);
120 public void listenForPaymentRequest() {
121 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
124 void onEntriesWritten(List<? extends Serializable> entries)
127 List<GroupData> groups = castEntries(entries);
129 for (GroupData groupData : groups) {
130 TransactionReference tx = getDefaultTransaction();
131 GroupData entity = new GroupData(groupData.getId());
133 // Acquire the lock so that another waiter can't do the same
135 String paymentRequestTakenByOtherWaiter = String.format(
136 "The payment request for group %d was already taken by an other waiter!",
139 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
141 groupData.setPayingWaiter(waiterId);
143 sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx);
145 capi.commitTransaction(tx);
146 } catch (Exception e) {
147 // log.info(e.getMessage());
153 createNotification(paymentListener, paymentRequestContainer);
156 public void listenForOrderRequests() {
157 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
160 void onEntriesWritten(List<? extends Serializable> entries)
163 List<GroupData> groups = castEntries(entries);
165 for (GroupData groupData : groups) {
167 TransactionReference tx = getDefaultTransaction();
168 GroupData entity = new GroupData(groupData.getId());
169 entity.setState(GroupState.SITTING);
172 // Acquire the lock so that another waiter can't do the same thing!
173 String orderTakenByOtherWaiter = String.format(
174 "The order for group %d was already taken by an other waiter!",
176 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
178 groupData.setOrderWaiter(waiterId);
179 groupData.setState(GroupState.ORDERED);
180 Order order = groupData.getOrder();
181 order.setStatus(OrderStatus.ORDERED);
183 /* get the id of the last order of the pizzeria and set the order accordingly and
185 final OrderId orderId = takeMatchingEntity(new OrderId(null), infoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
186 final int id = orderId.getId();
187 final int nextId = id+1;
189 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
190 for (PizzaOrder orderedPizza : orderedPizzas) {
191 orderedPizza.setOrderId(nextId);
193 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), infoContainer, RequestTimeout.DEFAULT, tx);
195 // send the order as a whole to the space
196 sendItemsToContainer(Arrays.asList(groupData),
197 orderTakenContainer, RequestTimeout.ZERO, tx);
198 sendItemsToContainer(order.getOrderedPizzas(),
199 preparePizzasContainer, RequestTimeout.ZERO, tx);
200 capi.commitTransaction(tx);
202 log.info("Waiter has taken order from group {}",
204 } catch (Exception e) {
205 // log.info(e.getMessage());
211 createNotification(ordersListener, takeOrderContainer);
214 public void listenForPreparedPizzas() {
216 * A waiter gets informed when a new pizza is complete. He takes the
217 * orderId of the pizza and looks up the corresponding order from which
218 * he gets the number of necessary pizzas of the order. He then tries to
219 * fetch all pizzas with the corresponding orderId and compares the
220 * number of those pizzas with the number of necessary pizzas. If all
221 * pizzas of an order are complete he then delivers them!
223 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
226 void onEntriesWritten(List<? extends Serializable> entries)
229 List<Pizza> pizzas = castEntries(entries);
231 for (Pizza pizza : pizzas) {
232 int orderId = pizza.getOrderId();
234 TransactionReference tx = getDefaultTransaction();
237 GroupData entity = new GroupData();
238 entity.setState(null);
239 Order order = new Order();
240 order.setId(orderId);
241 entity.setOrder(order);
243 GroupData groupData = takeMatchingEntity(entity,
244 orderTakenContainer, tx, RequestTimeout.DEFAULT,
245 "Another waiter just checks if the order is complete");
246 int groupId = groupData.getId();
247 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
249 Pizza pizzaTemplate = new Pizza();
250 pizzaTemplate.setOrderId(orderId);
252 List<Pizza> pizzasOfOrder = takeMatchingEntities(
253 pizzaTemplate, deliverPizzasContainer, tx,
254 RequestTimeout.DEFAULT,
255 "Cannot take the pizzas from the deliverPizzasContainer");
257 if (pizzasOfOrder.size() == numberOfPizzas) {
258 GroupData group = new GroupData();
259 group.setServingWaiter(waiterId);
260 Order completeOrder = new Order();
261 completeOrder.setId(orderId);
262 completeOrder.setGroupId(groupId);
263 group.setOrder(completeOrder);
264 sendItemsToContainer(Arrays.asList(group),
265 orderCompleteContainer, RequestTimeout.DEFAULT,
267 capi.commitTransaction(tx);
269 log.info("Not yet all pizzas prepared! Order with id "
270 + orderId + " has " + numberOfPizzas
271 + " pizzas, but only " + pizzasOfOrder.size()
272 + " pizzas are ready by now!");
273 capi.rollbackTransaction(tx);
275 } catch (NullPointerException e) {
277 } catch (Exception e) {
278 capi.rollbackTransaction(tx);
284 createNotification(preparedPizzasListener, deliverPizzasContainer);
287 private void assignGroupToTable(GroupData lockedGroup,
288 Table lockedFreeTable, TransactionReference tx)
289 throws MzsCoreException {
290 // The new group sits down at the table
291 lockedFreeTable.setGroupId(lockedGroup.getId());
293 // The new group now wants to order
294 lockedGroup.setState(GroupState.SITTING);
295 lockedGroup.setTable(lockedFreeTable);
296 lockedGroup.setTableWaiter(waiterId);
298 sendItemsToContainer(Arrays.asList(lockedFreeTable),
299 tableAssignedContainer, RequestTimeout.ZERO, tx);
300 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
301 RequestTimeout.ZERO, tx);
304 capi.commitTransaction(tx);
305 log.info("Assigned table to group with groupId {}",
306 lockedGroup.getId());
307 } catch (Exception e) {
308 log.info("Assigning a table to group with groupId {} failed",
309 lockedGroup.getId());
310 log.info(e.getMessage());