]> git.somenet.org - pub/jan/sbc.git/blob - src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java
[XVSM] Pizzeria notifies on start Group agent that it exists. So the pizzeria can...
[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                 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);
42         }
43
44         public void listenForFreeTable() {
45                 SpaceListener listener = new SpaceListenerImpl(capi, freeTablesContainer, false) {
46
47                         @Override
48                         void onEntriesWritten(List<? extends Serializable> entries) throws Exception {
49
50                                 List<Table> tables = castEntries(entries);
51
52                                 for (Table table : tables) {
53
54                                         TransactionReference tx = getDefaultTransaction();
55
56                                         // Acquire a lock for the free table in the
57                                         // FreeTableContainer
58                                         int id = table.getId();
59
60                                         Table tableTemplate = new Table(id);
61                                         try {
62                                                 Table lockedFreeTable = takeMatchingEntity(tableTemplate,
63                                                                 freeTablesContainer, tx, RequestTimeout.DEFAULT,
64                                                                 String.format("There was no free table found with id %d", id));
65
66
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");
71
72                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
73                                         } catch (Exception e) {
74 //                                              log.info(e.getMessage());
75                                         }
76                                 }
77                         }
78                 };
79
80                 createNotification(listener, freeTablesContainer);
81         }
82
83
84
85         public void listenForNewGuests() {
86                 SpaceListener listener = new SpaceListenerImpl(capi, assignTableContainer) {
87                         
88                         @Override
89                         void onEntriesWritten(List<? extends Serializable> entries)
90                                         throws Exception {
91                                 log.info("New guest groups have arrived");
92
93                                 List<GroupData> groups = castEntries(entries);
94
95                                 for (GroupData group : groups) {
96                                         
97                                         TransactionReference tx = getDefaultTransaction();
98
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());
102
103                                         try {
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
109                                                 // TablesContainer
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,
112                                                                 noFreeTable);
113
114                                                 assignGroupToTable(lockedGroup, lockedFreeTable, tx);
115                                         } catch (Exception e) {
116 //                                              log.info(e.getMessage());
117                                         }
118                                 }
119                         }
120                 };
121                 
122                 createNotification(listener, assignTableContainer);
123         }
124
125     public void listenForPaymentRequest() {
126                 SpaceListener paymentListener = new SpaceListenerImpl(capi, paymentRequestContainer) {
127                         
128                         @Override
129                         void onEntriesWritten(List<? extends Serializable> entries)
130                                         throws Exception {
131
132                                 List<GroupData> groups = castEntries(entries);
133                                 
134                                 for (GroupData groupData : groups) {
135                                         TransactionReference tx = getDefaultTransaction();
136                                         GroupData entity = new GroupData(groupData.getId());
137
138                                         // Acquire the lock so that another waiter can't do the same
139                                         // thing!
140                                         String paymentRequestTakenByOtherWaiter = String.format(
141                                                         "The payment request for group %d was already taken by an other waiter!",
142                                                         groupData.getId());
143                                         try {
144                                                 takeMatchingEntity(entity, paymentRequestContainer, tx, RequestTimeout.DEFAULT, paymentRequestTakenByOtherWaiter);
145
146                                                 groupData.setPayingWaiter(waiterId);
147
148                         final List<GroupData> groupsPayed = Arrays.asList(groupData);
149                         sendItemsToContainer(groupsPayed, paymentDoneContainer, RequestTimeout.ZERO, tx);
150                         sendItemsToContainer(groupsPayed, groupAgentPaymentDoneContainer, RequestTimeout.ZERO, null);
151
152                                                 capi.commitTransaction(tx);
153                                         } catch (Exception e) {
154 //                                              log.info(e.getMessage());
155                                         }
156                                 }
157                         }
158                 };
159
160                 createNotification(paymentListener, paymentRequestContainer);
161         }
162
163         public void listenForOrderRequests() {
164                 SpaceListener ordersListener = new SpaceListenerImpl(capi, takeOrderContainer) {
165                         
166                         @Override
167                         void onEntriesWritten(List<? extends Serializable> entries)
168                                         throws Exception {
169
170                                 List<GroupData> groups = castEntries(entries);
171                 
172                                 for (GroupData groupData : groups) {
173
174                                         TransactionReference tx = getDefaultTransaction();
175                                         GroupData entity = new GroupData(groupData.getId());
176                                         entity.setState(GroupState.SITTING);
177
178                                         try {
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!",
182                                                                 groupData.getId());
183                                                 takeMatchingEntity(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, orderTakenByOtherWaiter);
184
185                                                 groupData.setOrderWaiter(waiterId);
186                                                 groupData.setState(GroupState.ORDERED);
187                                                 Order order = groupData.getOrder();
188                                                 order.setStatus(OrderStatus.ORDERED);
189
190                         /*  get the id of the last order of the pizzeria and set the order accordingly and
191                             update the space */
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;
195                         order.setId(nextId);
196                         final List<PizzaOrder> orderedPizzas = order.getOrderedPizzas();
197                         for (PizzaOrder orderedPizza : orderedPizzas) {
198                             orderedPizza.setOrderId(nextId);
199                         }
200                         sendItemsToContainer(Arrays.asList(new OrderId(nextId)), pizzeriaInfoContainer, RequestTimeout.DEFAULT, tx);
201
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);
211
212                                                 log.info("Waiter has taken order from group {}",
213                                                                 groupData.getId());
214                                         } catch (Exception e) {
215 //                                              log.info(e.getMessage());
216                                         }
217                                 } 
218                         }
219                 };
220                 
221                 createNotification(ordersListener, takeOrderContainer);
222         }
223
224         public void listenForPreparedPizzas() {
225                 /**
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!
232                  */
233                 SpaceListener preparedPizzasListener = new SpaceListenerImpl(capi, deliverPizzasContainer) {
234                                         
235                         @Override
236                         void onEntriesWritten(List<? extends Serializable> entries)
237                                         throws Exception {
238
239                                 List<Pizza> pizzas = castEntries(entries);
240                 
241                                 for (Pizza pizza : pizzas) {
242                                         int orderId = pizza.getOrderId();
243
244                                         TransactionReference tx = getDefaultTransaction();
245
246                                         try {
247                                                 GroupData entity = new GroupData();
248                                                 entity.setState(null);
249                                                 Order order = new Order();
250                                                 order.setId(orderId);
251                                                 entity.setOrder(order);
252
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();
258
259                                                 Pizza pizzaTemplate = new Pizza();
260                                                 pizzaTemplate.setOrderId(orderId);
261
262                                                 List<Pizza> pizzasOfOrder = takeMatchingEntities(
263                                                                 pizzaTemplate, deliverPizzasContainer, tx,
264                                                                 RequestTimeout.DEFAULT,
265                                                                 "Cannot take the pizzas from the deliverPizzasContainer");
266
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,
277                                     tx);
278                             sendItemsToContainer(groupsWithCompleteOrder,
279                                     groupAgentOrderCompleteContainer, RequestTimeout.DEFAULT,
280                                     null);
281                                                         capi.commitTransaction(tx);
282                                                 } else {
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);
288                                                 }
289                                         } catch (NullPointerException e) {
290                                                 
291                                         } catch (Exception e) {
292                                                 capi.rollbackTransaction(tx);
293                                         }
294                                 }
295                         }
296                 };
297
298                 createNotification(preparedPizzasListener, deliverPizzasContainer);
299         }
300
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());
306
307                 // The new group now wants to order
308                 lockedGroup.setState(GroupState.SITTING);
309                 lockedGroup.setTable(lockedFreeTable);
310                 lockedGroup.setTableWaiter(waiterId);
311
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);
319
320                 try {
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());
328                 }
329         }
330
331 }