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 groupAgentOrderTakenContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_TAKEN, Util.GROUP_AGENT_PORT);
31 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
32 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
33 groupAgentOrderCompleteContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_ORDER_COMPLETE, Util.GROUP_AGENT_PORT);
34 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
35 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
36 groupAgentPaymentRequestContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_REQUEST, Util.GROUP_AGENT_PORT);
37 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
38 groupAgentPaymentDoneContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_PAYMENT_DONE, Util.GROUP_AGENT_PORT);
39 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
40 groupAgentTableAssignedContainer = useContainerOfSpaceWithPort(Util.GROUP_AGENT_TABLE_ASSIGNED, Util.GROUP_AGENT_PORT);
41 pizzeriaInfoContainer = useContainer(Util.PIZZERIA_INFO);
44 public void listenForFreeTable() {
45 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
48 void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
50 List<Table> tables = castEntries(entries);
52 for (Table table : tables) {
54 TransactionReference tx = getDefaultTransaction();
56 // Acquire a lock for the free table in the
58 int id = table.getId();
60 Table tableTemplate = new Table(id);
62 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
63 freeTablesContainer, tx, RequestTimeout.DEFAULT,
64 String.format("There was no free table found with id %d", id));
67 GroupData groupTemplate = new GroupData();
68 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
69 assignTableContainer, tx, RequestTimeout.DEFAULT,
70 "There is no group waiting for a table at the moment");
72 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
73 } catch (Exception e) {
74 // log.info(e.getMessage());
80 createNotification(listener, freeTablesContainer);
85 public void listenForNewGuests() {
86 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
89 void onEntriesWritten(List<? extends Serializable> entries)
91 log.info("New guest groups have arrived");
93 List<GroupData> groups = castEntries(entries);
95 for (GroupData group : groups) {
97 TransactionReference tx = getDefaultTransaction();
99 // Acquire a lock for the group in the
100 // AssignTableContainer
101 String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
104 GroupData lockedGroup = takeMatchingEntity(
105 new GroupData(group.getId()),
106 assignTableContainer, tx,
107 RequestTimeout.DEFAULT, groupNotFound);
108 // Acquire a lock for one free table in the
110 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
111 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
114 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
115 } catch (Exception e) {
116 // log.info(e.getMessage());
122 createNotification(listener, assignTableContainer);
125 public void listenForPaymentRequest() {
126 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
129 void onEntriesWritten(List<? extends Serializable> entries)
132 List<GroupData> groups = castEntries(entries);
134 for (GroupData groupData : groups) {
135 TransactionReference tx = getDefaultTransaction();
136 GroupData entity = new GroupData(groupData.getId());
138 // Acquire the lock so that another waiter can't do the same
140 String paymentRequestTakenByOtherWaiter = String.format(
141 "The payment request for group %d was already taken by an other waiter!",
144 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
146 groupData.setPayingWaiter(waiterId);
148 final List<GroupData> groupsPayed = Arrays.asList(groupData);
149 sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
150 sendItemsToContainer(groupsPayed, groupAgentPaymentDoneContainer, RequestTimeout.ZERO, null);
152 capi.commitTransaction(tx);
153 } catch (Exception e) {
154 // log.info(e.getMessage());
160 createNotification(paymentListener, paymentRequestContainer);
163 public void listenForOrderRequests() {
164 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
167 void onEntriesWritten(List<? extends Serializable> entries)
170 List<GroupData> groups = castEntries(entries);
172 for (GroupData groupData : groups) {
174 TransactionReference tx = getDefaultTransaction();
175 GroupData entity = new GroupData(groupData.getId());
176 entity.setState(GroupState.SITTING);
179 // Acquire the lock so that another waiter can't do the same thing!
180 String orderTakenByOtherWaiter = String.format(
181 "The order for group %d was already taken by an other waiter!",
183 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
185 groupData.setOrderWaiter(waiterId);
186 groupData.setState(GroupState.ORDERED);
187 Order order = groupData.getOrder();
188 order.setStatus(OrderStatus.ORDERED);
190 /* get the id of the last order of the pizzeria and set the order accordingly and
192 final OrderId orderId = takeMatchingEntity(new OrderId(null), pizzeriaInfoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
193 final int id = orderId.getId();
194 final int nextId = id+1;
196 final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
197 for (PizzaOrder orderedPizza : orderedPizzas) {
198 orderedPizza.setOrderId(nextId);
200 sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
202 // send the order as a whole to the space
203 final List<GroupData> groupsWhoHaveOrdered = Arrays.asList(groupData);
204 sendItemsToContainer(groupsWhoHaveOrdered,
205 orderTakenContainer, RequestTimeout.ZERO, tx);
206 sendItemsToContainer(order.getOrderedPizzas(),
207 preparePizzasContainer, RequestTimeout.ZERO, tx);
208 sendItemsToContainer(groupsWhoHaveOrdered,
209 groupAgentOrderTakenContainer, RequestTimeout.ZERO, null);
210 capi.commitTransaction(tx);
212 log.info("Waiter has taken order from group {}",
214 } catch (Exception e) {
215 // log.info(e.getMessage());
221 createNotification(ordersListener, takeOrderContainer);
224 public void listenForPreparedPizzas() {
226 * A waiter gets informed when a new pizza is complete. He takes the
227 * orderId of the pizza and looks up the corresponding order from which
228 * he gets the number of necessary pizzas of the order. He then tries to
229 * fetch all pizzas with the corresponding orderId and compares the
230 * number of those pizzas with the number of necessary pizzas. If all
231 * pizzas of an order are complete he then delivers them!
233 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
236 void onEntriesWritten(List<? extends Serializable> entries)
239 List<Pizza> pizzas = castEntries(entries);
241 for (Pizza pizza : pizzas) {
242 int orderId = pizza.getOrderId();
244 TransactionReference tx = getDefaultTransaction();
247 GroupData entity = new GroupData();
248 entity.setState(null);
249 Order order = new Order();
250 order.setId(orderId);
251 entity.setOrder(order);
253 GroupData groupData = takeMatchingEntity(entity,
254 orderTakenContainer, tx, RequestTimeout.DEFAULT,
255 "Another waiter just checks if the order is complete");
256 int groupId = groupData.getId();
257 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
259 Pizza pizzaTemplate = new Pizza();
260 pizzaTemplate.setOrderId(orderId);
262 List<Pizza> pizzasOfOrder = takeMatchingEntities(
263 pizzaTemplate, deliverPizzasContainer, tx,
264 RequestTimeout.DEFAULT,
265 "Cannot take the pizzas from the deliverPizzasContainer");
267 if (pizzasOfOrder.size() == numberOfPizzas) {
268 GroupData group = new GroupData();
269 group.setServingWaiter(waiterId);
270 Order completeOrder = new Order();
271 completeOrder.setId(orderId);
272 completeOrder.setGroupId(groupId);
273 group.setOrder(completeOrder);
274 final List<GroupData> groupsWithCompleteOrder = Arrays.asList(group);
275 sendItemsToContainer(groupsWithCompleteOrder,
276 orderCompleteContainer, RequestTimeout.DEFAULT,
278 sendItemsToContainer(groupsWithCompleteOrder,
279 groupAgentOrderCompleteContainer, RequestTimeout.DEFAULT,
281 capi.commitTransaction(tx);
283 log.info("Not yet all pizzas prepared! Order with id "
284 + orderId + " has " + numberOfPizzas
285 + " pizzas, but only " + pizzasOfOrder.size()
286 + " pizzas are ready by now!");
287 capi.rollbackTransaction(tx);
289 } catch (NullPointerException e) {
291 } catch (Exception e) {
292 capi.rollbackTransaction(tx);
298 createNotification(preparedPizzasListener, deliverPizzasContainer);
301 private void assignGroupToTable(GroupData lockedGroup,
302 Table lockedFreeTable, TransactionReference tx)
303 throws MzsCoreException {
304 // The new group sits down at the table
305 lockedFreeTable.setGroupId(lockedGroup.getId());
307 // The new group now wants to order
308 lockedGroup.setState(GroupState.SITTING);
309 lockedGroup.setTable(lockedFreeTable);
310 lockedGroup.setTableWaiter(waiterId);
312 final List<Table> freeTables = Arrays.asList(lockedFreeTable);
313 sendItemsToContainer(freeTables,
314 tableAssignedContainer, RequestTimeout.ZERO, tx);
315 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
316 RequestTimeout.ZERO, tx);
317 sendItemsToContainer(freeTables,
318 groupAgentTableAssignedContainer, RequestTimeout.ZERO, null);
321 capi.commitTransaction(tx);
322 log.info("Assigned table to group with groupId {}",
323 lockedGroup.getId());
324 } catch (Exception e) {
325 log.info("Assigning a table to group with groupId {} failed",
326 lockedGroup.getId());
327 log.info(e.getMessage());