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