]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
Make order ids pizzeria specific in XVSM implementation
[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.net.URI;
5 import java.util.Arrays;
6 import java.util.Collections;
7 import java.util.Iterator;
8 import java.util.List;
9
10 import at.ac.tuwien.sbc.valesriegler.common.OrderId;
11 import org.mozartspaces.capi3.AnyCoordinator;
12 import org.mozartspaces.capi3.FifoCoordinator;
13 import org.mozartspaces.capi3.LindaCoordinator;
14 import org.mozartspaces.core.ContainerReference;
15 import org.mozartspaces.core.MzsConstants;
16 import org.mozartspaces.core.MzsConstants.RequestTimeout;
17 import org.mozartspaces.core.MzsCoreException;
18 import org.mozartspaces.core.TransactionException;
19 import org.mozartspaces.core.TransactionReference;
20 import org.mozartspaces.notifications.Notification;
21 import org.mozartspaces.notifications.NotificationListener;
22 import org.mozartspaces.notifications.Operation;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import at.ac.tuwien.sbc.valesriegler.common.Util;
27 import at.ac.tuwien.sbc.valesriegler.types.GroupData;
28 import at.ac.tuwien.sbc.valesriegler.types.GroupState;
29 import at.ac.tuwien.sbc.valesriegler.types.Order;
30 import at.ac.tuwien.sbc.valesriegler.types.OrderStatus;
31 import at.ac.tuwien.sbc.valesriegler.types.Pizza;
32 import at.ac.tuwien.sbc.valesriegler.types.Table;
33
34 public class WaiterXVSM extends AbstractXVSMConnector {
35         private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class);
36         private final int waiterId;
37
38         public WaiterXVSM(int waiterId) {
39                 super();
40
41                 this.waiterId = waiterId;
42
43                 freeTablesContainer = useContainer(Util.FREE_TABLES);
44                 assignTableContainer = useContainer(Util.ASSIGN_TABLE);
45                 takeOrderContainer = useContainer(Util.TAKE_ORDER);
46                 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
47                 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
48                 orderCompleteContainer = useContainer(Util.ORDER_COMPLETE);
49                 deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
50                 paymentRequestContainer = useContainer(Util.PAYMENT_REQUEST);
51                 paymentDoneContainer = useContainer(Util.PAYMENT_DONE);
52                 tableAssignedContainer = useContainer(Util.TABLE_ASSIGNED);
53                 infoContainer = useContainer(Util.INFO);
54         }
55
56         public void listenForFreeTable() {
57                 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
58
59                         @Override
60                         void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
61
62                                 List<Table> tables = castEntries(entries);
63
64                                 for (Table table : tables) {
65
66                                         TransactionReference tx = capi.createTransaction(
67                                                         Util.SPACE_TRANSACTION_TIMEOUT,
68                                                         URI.create(Util.SERVER_ADDR));
69
70                                         // Acquire a lock for the free table in the
71                                         // FreeTableContainer
72                                         int id = table.getId();
73
74                                         Table tableTemplate = new Table(id);
75                                         try {
76                                                 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
77                                                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
78                                                                 String.format("There was no free table found with id %d", id));
79
80
81                                                 GroupData groupTemplate = new GroupData();
82                                                 GroupData lockedGroup = takeMatchingEntity(groupTemplate,
83                                                                 assignTableContainer, tx, RequestTimeout.DEFAULT,
84                                                                 "There is no group waiting for a table at the moment");
85
86                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
87                                         } catch (Exception e) {
88 //                                              log.info(e.getMessage());
89                                         }
90                                 }
91                         }
92                 };
93
94                 createNotification(listener, freeTablesContainer);
95         }
96
97
98
99         public void listenForNewGuests() {
100                 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
101                         
102                         @Override
103                         void onEntriesWritten(List<? extends Serializable> entries)
104                                         throws Exception {
105                                 log.info("New guest groups have arrived");
106
107                                 List<GroupData> groups = castEntries(entries);
108
109                                 for (GroupData group : groups) {
110                                         
111                                         TransactionReference tx = capi.createTransaction(
112                                                 Util.SPACE_TRANSACTION_TIMEOUT,
113                                                 URI.create(Util.SERVER_ADDR));
114
115                                         // Acquire a lock for the group in the
116                                         // AssignTableContainer
117                                         String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId());
118
119                                         try {
120                                                 GroupData lockedGroup = takeMatchingEntity(
121                                                                 new GroupData(group.getId()),
122                                                                 assignTableContainer, tx,
123                                                                 RequestTimeout.DEFAULT, groupNotFound);
124                                                 // Acquire a lock for one free table in the
125                                                 // TablesContainer
126                                                 String noFreeTable = String.format("No free table for group with id %d could be found", group.getId());
127                                                 Table lockedFreeTable = takeMatchingEntity(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT,
128                                                                 noFreeTable);
129
130                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
131                                         } catch (Exception e) {
132 //                                              log.info(e.getMessage());
133                                         }
134                                 }
135                         }
136                 };
137                 
138                 createNotification(listener, assignTableContainer);
139         }
140
141         public void listenForPaymentRequest() {
142                 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
143                         
144                         @Override
145                         void onEntriesWritten(List<? extends Serializable> entries)
146                                         throws Exception {
147
148                                 List<GroupData> groups = castEntries(entries);
149                                 
150                                 for (GroupData groupData : groups) {
151                                         TransactionReference tx = capi.createTransaction(
152                                                         Util.SPACE_TRANSACTION_TIMEOUT,
153                                                         URI.create(Util.SERVER_ADDR));
154                                         GroupData entity = new GroupData(groupData.getId());
155
156                                         // Acquire the lock so that another waiter can't do the same
157                                         // thing!
158                                         String paymentRequestTakenByOtherWaiter = String.format(
159                                                         "The payment request for group %d was already taken by an other waiter!",
160                                                         groupData.getId());
161                                         try {
162                                                 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
163
164                                                 groupData.setPayingWaiter(waiterId);
165
166                                                 sendItemsToContainer(Arrays.asList(groupData), paymentDoneContainer, RequestTimeout.ZERO, tx);
167
168                                                 capi.commitTransaction(tx);
169                                         } catch (Exception e) {
170 //                                              log.info(e.getMessage());
171                                         }
172                                 }
173                         }
174                 };
175
176                 createNotification(paymentListener, paymentRequestContainer);
177         }
178
179         public void listenForOrderRequests() {
180                 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
181                         
182                         @Override
183                         void onEntriesWritten(List<? extends Serializable> entries)
184                                         throws Exception {
185
186                                 List<GroupData> groups = castEntries(entries);
187                 
188                                 for (GroupData groupData : groups) {
189
190                                         TransactionReference tx = capi.createTransaction(
191                                                         Util.SPACE_TRANSACTION_TIMEOUT,
192                                                         URI.create(Util.SERVER_ADDR));
193                                         GroupData entity = new GroupData(groupData.getId());
194                                         entity.setState(GroupState.SITTING);
195
196                                         try {
197                                                 // Acquire the lock so that another waiter can't do the same thing!
198                                                 String orderTakenByOtherWaiter = String.format(
199                                                                 "The order for group %d was already taken by an other waiter!",
200                                                                 groupData.getId());
201                                                 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
202
203                                                 groupData.setOrderWaiter(waiterId);
204                                                 groupData.setState(GroupState.ORDERED);
205                                                 Order order = groupData.getOrder();
206                                                 order.setStatus(OrderStatus.ORDERED);
207
208                         /*  get the id of the last order of the pizzeria and set the order accordingly and
209                             update the space */
210                         final OrderId orderId = takeMatchingEntity(new OrderId(null), infoContainer, tx, RequestTimeout.INFINITE, "The Order id object could not be taken from the space!");
211                         final int id = orderId.getId();
212                         order.setId(id+100);
213                         sendItemsToContainer(Arrays.asList(new OrderId(id+1)), infoContainer, RequestTimeout.DEFAULT, tx);
214
215                         // send the order as a whole to the space
216                                                 sendItemsToContainer(Arrays.asList(groupData),
217                                 orderTakenContainer, RequestTimeout.ZERO, tx);
218                                                 sendItemsToContainer(order.getOrderedPizzas(),
219                                                                 preparePizzasContainer, RequestTimeout.ZERO, tx);
220                                                 capi.commitTransaction(tx);
221
222                                                 log.info("Waiter has taken order from group {}",
223                                                                 groupData.getId());
224                                         } catch (Exception e) {
225 //                                              log.info(e.getMessage());
226                                         }
227                                 } 
228                         }
229                 };
230                 
231                 createNotification(ordersListener, takeOrderContainer);
232         }
233
234         public void listenForPreparedPizzas() {
235                 /**
236                  * A waiter gets informed when a new pizza is complete. He takes the
237                  * orderId of the pizza and looks up the corresponding order from which
238                  * he gets the number of necessary pizzas of the order. He then tries to
239                  * fetch all pizzas with the corresponding orderId and compares the
240                  * number of those pizzas with the number of necessary pizzas. If all
241                  * pizzas of an order are complete he then delivers them!
242                  */
243                 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
244                                         
245                         @Override
246                         void onEntriesWritten(List<? extends Serializable> entries)
247                                         throws Exception {
248
249                                 List<Pizza> pizzas = castEntries(entries);
250                 
251                                 for (Pizza pizza : pizzas) {
252                                         int orderId = pizza.getOrderId();
253
254                                         TransactionReference tx = capi.createTransaction(
255                                                         Util.SPACE_TRANSACTION_TIMEOUT,
256                                                         URI.create(Util.SERVER_ADDR));
257
258                                         try {
259                                                 GroupData entity = new GroupData();
260                                                 entity.setState(null);
261                                                 Order order = new Order();
262                                                 order.setId(orderId);
263                                                 entity.setOrder(order);
264
265                                                 GroupData groupData = takeMatchingEntity(entity,
266                                                                 orderTakenContainer, tx, RequestTimeout.DEFAULT,
267                                                                 "Another waiter just checks if the order is complete");
268                                                 int groupId = groupData.getId();
269                                                 int numberOfPizzas = groupData.getOrder().getNumberOfPizzas();
270
271                                                 Pizza pizzaTemplate = new Pizza();
272                                                 pizzaTemplate.setOrderId(orderId);
273
274                                                 List<Pizza> pizzasOfOrder = takeMatchingEntities(
275                                                                 pizzaTemplate, deliverPizzasContainer, tx,
276                                                                 RequestTimeout.DEFAULT,
277                                                                 "Cannot take the pizzas from the deliverPizzasContainer");
278
279                                                 if (pizzasOfOrder.size() == numberOfPizzas) {
280                                                         GroupData group = new GroupData();
281                                                         group.setServingWaiter(waiterId);
282                                                         Order completeOrder = new Order();
283                                                         completeOrder.setId(orderId);
284                                                         completeOrder.setGroupId(groupId);
285                                                         group.setOrder(completeOrder);
286                                                         sendItemsToContainer(Arrays.asList(group),
287                                                                         orderCompleteContainer, RequestTimeout.DEFAULT,
288                                                                         tx);
289                                                         capi.commitTransaction(tx);
290                                                 } else {
291                                                         log.info("Not yet all pizzas prepared! Order with id "
292                                                                         + orderId + " has " + numberOfPizzas
293                                                                         + " pizzas, but only " + pizzasOfOrder.size()
294                                                                         + " pizzas are ready by now!");
295                                                         capi.rollbackTransaction(tx);
296                                                 }
297                                         } catch (NullPointerException e) {
298                                                 
299                                         } catch (Exception e) {
300                                                 capi.rollbackTransaction(tx);
301                                         }
302                                 }
303                         }
304                 };
305
306                 createNotification(preparedPizzasListener, deliverPizzasContainer);
307         }
308
309         private void assignGroupToTable(GroupData lockedGroup,
310                         Table lockedFreeTable, TransactionReference tx)
311                         throws MzsCoreException {
312                 // The new group sits down at the table
313                 lockedFreeTable.setGroupId(lockedGroup.getId());
314
315                 // The new group now wants to order
316                 lockedGroup.setState(GroupState.SITTING);
317                 lockedGroup.setTable(lockedFreeTable);
318                 lockedGroup.setTableWaiter(waiterId);
319
320                 sendItemsToContainer(Arrays.asList(lockedFreeTable),
321                                 tableAssignedContainer, RequestTimeout.ZERO, tx);
322                 sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer,
323                                 RequestTimeout.ZERO, tx);
324
325                 try {
326                         capi.commitTransaction(tx);
327                         log.info("Assigned table to group with groupId {}",
328                                         lockedGroup.getId());
329                 } catch (Exception e) {
330                         log.info("Assigning a table to group with groupId {} failed",
331                                         lockedGroup.getId());
332                         log.info(e.getMessage());
333                 }
334         }
335
336 }