]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
[XVSM] Waiters, Cooks and Pizzerias can be parameterized with a Space port. Group...
[pub/jan/sbc.git] / src / main / java / at / ac / tuwien / sbc / valesriegler / xvsm / WaiterXVSM.java
1 package at.ac.tuwien.sbc.valesriegler.xvsm;
2
3 import java.io.Serializable;
4 import java.util.Arrays;
5 import java.util.List;
6
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;
14
15 import at.ac.tuwien.sbc.valesriegler.common.Util;
16
17 public class WaiterXVSM extends AbstractXVSMConnector {
18         private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
19         private final int waiterId;
20
21         public WaiterXVSM(int waiterId, int port) {
22                 super(port);
23
24                 this.waiterId = waiterId;
25
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);
37         }
38
39         public void listenForFreeTable() {
40                 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
41
42                         @Override
43                         void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
44
45                                 List<Table> tables = castEntries(entries);
46
47                                 for (Table table : tables) {
48
49                                         TransactionReference tx = getDefaultTransaction();
50
51                                         // Acquire a lock for the free table in the
52                                         // FreeTableContainer
53                                         int id = table.getId();
54
55                                         Table tableTemplate = new Table(id);
56                                         try {
57                                                 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
58                                                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
59                                                                 String.format("There was no free table found with id %d", id));
60
61
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");
66
67                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
68                                         } catch (Exception e) {
69 //                                              log.info(e.getMessage());
70                                         }
71                                 }
72                         }
73                 };
74
75                 createNotification(listener, freeTablesContainer);
76         }
77
78
79
80         public void listenForNewGuests() {
81                 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
82                         
83                         @Override
84                         void onEntriesWritten(List<? extends Serializable> entries)
85                                         throws Exception {
86                                 log.info("New guest groups have arrived");
87
88                                 List<GroupData> groups = castEntries(entries);
89
90                                 for (GroupData group : groups) {
91                                         
92                                         TransactionReference tx = getDefaultTransaction();
93
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());
97
98                                         try {
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
104                                                 // TablesContainer
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,
107                                                                 noFreeTable);
108
109                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
110                                         } catch (Exception e) {
111 //                                              log.info(e.getMessage());
112                                         }
113                                 }
114                         }
115                 };
116                 
117                 createNotification(listener, assignTableContainer);
118         }
119
120     public void listenForPaymentRequest() {
121                 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
122                         
123                         @Override
124                         void onEntriesWritten(List<? extends Serializable> entries)
125                                         throws Exception {
126
127                                 List<GroupData> groups = castEntries(entries);
128                                 
129                                 for (GroupData groupData : groups) {
130                                         TransactionReference tx = getDefaultTransaction();
131                                         GroupData entity = new GroupData(groupData.getId());
132
133                                         // Acquire the lock so that another waiter can't do the same
134                                         // thing!
135                                         String paymentRequestTakenByOtherWaiter = String.format(
136                                                         "The payment request for group %d was already taken by an other waiter!",
137                                                         groupData.getId());
138                                         try {
139                                                 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
140
141                                                 groupData.setPayingWaiter(waiterId);
142
143                                                 sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx);
144
145                                                 capi.commitTransaction(tx);
146                                         } catch (Exception e) {
147 //                                              log.info(e.getMessage());
148                                         }
149                                 }
150                         }
151                 };
152
153                 createNotification(paymentListener, paymentRequestContainer);
154         }
155
156         public void listenForOrderRequests() {
157                 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
158                         
159                         @Override
160                         void onEntriesWritten(List<? extends Serializable> entries)
161                                         throws Exception {
162
163                                 List<GroupData> groups = castEntries(entries);
164                 
165                                 for (GroupData groupData : groups) {
166
167                                         TransactionReference tx = getDefaultTransaction();
168                                         GroupData entity = new GroupData(groupData.getId());
169                                         entity.setState(GroupState.SITTING);
170
171                                         try {
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!",
175                                                                 groupData.getId());
176                                                 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
177
178                                                 groupData.setOrderWaiter(waiterId);
179                                                 groupData.setState(GroupState.ORDERED);
180                                                 Order order = groupData.getOrder();
181                                                 order.setStatus(OrderStatus.ORDERED);
182
183                         /*  get the id of the last order of the pizzeria and set the order accordingly and
184                             update the space */
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;
188                         order.setId(nextId);
189                         final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
190                         for (PizzaOrder orderedPizza : orderedPizzas) {
191                             orderedPizza.setOrderId(nextId);
192                         }
193                         sendItemsToContainer(Arrays.asList(new OrderId(nextId)), infoContainer, RequestTimeout.DEFAULT, tx);
194
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);
201
202                                                 log.info("Waiter has taken order from group {}",
203                                                                 groupData.getId());
204                                         } catch (Exception e) {
205 //                                              log.info(e.getMessage());
206                                         }
207                                 } 
208                         }
209                 };
210                 
211                 createNotification(ordersListener, takeOrderContainer);
212         }
213
214         public void listenForPreparedPizzas() {
215                 /**
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!
222                  */
223                 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
224                                         
225                         @Override
226                         void onEntriesWritten(List<? extends Serializable> entries)
227                                         throws Exception {
228
229                                 List<Pizza> pizzas = castEntries(entries);
230                 
231                                 for (Pizza pizza : pizzas) {
232                                         int orderId = pizza.getOrderId();
233
234                                         TransactionReference tx = getDefaultTransaction();
235
236                                         try {
237                                                 GroupData entity = new GroupData();
238                                                 entity.setState(null);
239                                                 Order order = new Order();
240                                                 order.setId(orderId);
241                                                 entity.setOrder(order);
242
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();
248
249                                                 Pizza pizzaTemplate = new Pizza();
250                                                 pizzaTemplate.setOrderId(orderId);
251
252                                                 List<Pizza> pizzasOfOrder = takeMatchingEntities(
253                                                                 pizzaTemplate, deliverPizzasContainer, tx,
254                                                                 RequestTimeout.DEFAULT,
255                                                                 "Cannot take the pizzas from the deliverPizzasContainer");
256
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,
266                                                                         tx);
267                                                         capi.commitTransaction(tx);
268                                                 } else {
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);
274                                                 }
275                                         } catch (NullPointerException e) {
276                                                 
277                                         } catch (Exception e) {
278                                                 capi.rollbackTransaction(tx);
279                                         }
280                                 }
281                         }
282                 };
283
284                 createNotification(preparedPizzasListener, deliverPizzasContainer);
285         }
286
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());
292
293                 // The new group now wants to order
294                 lockedGroup.setState(GroupState.SITTING);
295                 lockedGroup.setTable(lockedFreeTable);
296                 lockedGroup.setTableWaiter(waiterId);
297
298                 sendItemsToContainer(Arrays.asList(lockedFreeTable),
299                                 tableAssignedContainer, RequestTimeout.ZERO, tx);
300                 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
301                                 RequestTimeout.ZERO, tx);
302
303                 try {
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());
311                 }
312         }
313
314 }