1 package at.ac.tuwien.sbc.valesriegler.xvsm;
3 import at.ac.tuwien.sbc.valesriegler.common.Util;
4 import at.ac.tuwien.sbc.valesriegler.types.*;
5 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceAction;
6 import at.ac.tuwien.sbc.valesriegler.xvsm.spacehelpers.SpaceListener;
7 import org.mozartspaces.core.MzsConstants.RequestTimeout;
8 import org.mozartspaces.core.MzsCoreException;
9 import org.mozartspaces.core.TransactionReference;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
13 import java.io.Serializable;
15 import java.util.Arrays;
16 import java.util.Collections;
17 import java.util.List;
19 public class CookXVSM extends AbstractXVSMConnector {
20 private static final Logger log = LoggerFactory.getLogger(CookXVSM.class);
24 public CookXVSM(int id, int port) {
28 orderTakenContainer = useContainer(Util.ORDER_TAKEN);
29 deliveryOrderTakenContainer = useContainer(Util.DELIVERY_ORDER_TAKEN);
30 preparedPizzasContainer = useContainer(Util.DELIVER_PIZZAS);
31 preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS);
32 prepareDeliveryPizzasContainer = useContainer(Util.PREPARE_DELIVERY_PIZZAS);
33 pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS);
34 preparedDeliveryPizzasContainer = useContainer(Util.DELIVER_DELIVERY_PIZZAS);
35 pizzeriaGroupContainer = useContainer(Util.PIZZERIA_GROUP);
36 pizzeriaDeliveryContainer = useContainer(Util.PIZZERIA_DELIVERY);
39 public void listenForPizzas() {
40 getDefaultBuilder().setLookaround(true).enableCountAll().setCref(preparePizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
43 public void onEntriesWritten(List<? extends Serializable> entries)
46 List<PizzaOrder> pizzas = castEntries(entries);
48 if (inNotification.get()) Collections.shuffle(pizzas);
50 for (PizzaOrder pizzaOrder : pizzas) {
52 TransactionReference tx = capi.createTransaction(9000, URI.create(String.format(Util.SERVER_ADDR, port)));
53 String pizzaAlreadyCooked = String.format("Normal pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
56 if (!mayPrepareCustomerPizza(pizzaOrder, tx)) {
57 capi.rollbackTransaction(tx);
61 // Require the lock for preparing the pizza
62 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
65 // tell the space that you prepare the pizza -> without a transaction!!
66 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
67 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
69 notifyCustomerPizzaInProgress(order, pizzaInProgress);
71 PizzaOrder pizza = createPizza(order);
73 notifyCustomerPizzaDone(pizza, tx);
74 capi.commitTransaction(tx);
75 log.debug("I have completed preparing a pizza for order {}!", pizza.getOrderId());
76 } catch (NullPointerException e) {
77 // the strange nullpointer exception from the space
78 } catch (EntityNotFoundByTemplate e) {
80 } catch (Exception e) {
81 log.info("outer cook");
82 log.info(e.getMessage());
88 }).createSpaceListenerImpl();
92 public void listenForDeliveryPizzas() {
93 SpaceListener pizzasListener = getDefaultBuilder().setLookaround(true).setCref(prepareDeliveryPizzasContainer).setTimeout(15000).setSpaceAction(new SpaceAction() {
96 public void onEntriesWritten(List<? extends Serializable> entries)
99 List<PizzaOrder> pizzas = castEntries(entries);
101 if (inNotification.get()) Collections.shuffle(pizzas);
103 for (PizzaOrder pizzaOrder : pizzas) {
105 TransactionReference tx = capi.createTransaction(12000, URI.create(String.format(Util.SERVER_ADDR, port)));
106 String pizzaAlreadyCooked = String.format("Delivery Pizza with id %d has already been cooked by another cook", pizzaOrder.getId());
109 if (!mayPrepareDeliveryPizza(pizzaOrder, tx)) {
110 capi.rollbackTransaction(tx);
114 // Require the lock for preparing the pizza
115 PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), prepareDeliveryPizzasContainer, tx, RequestTimeout.DEFAULT, pizzaAlreadyCooked);
117 // tell the space that you prepare the pizza -> without a transaction!!
118 Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId, true);
119 pizzaInProgress.setStatus(PizzaOrderStatus.IN_PREPARATION);
121 notifyDeliveryPizzaInProgress(order, pizzaInProgress);
123 PizzaOrder pizza = createPizza(order);
125 sendItemsToContainer(Arrays.asList(pizza), preparedDeliveryPizzasContainer, RequestTimeout.DEFAULT, tx);
127 notifyDeliveryPizzaDone(pizza, tx);
129 capi.commitTransaction(tx);
130 log.info("I have completed preparing a delivery pizza for order {}!", pizza.getOrderId());
131 } catch (NullPointerException e) {
132 // the strange nullpointer exception from the space
133 } catch (EntityNotFoundByTemplate e) {
135 } catch (Exception e) {
136 log.info("outer cook");
137 log.info(e.getMessage());
143 }).createSpaceListenerImpl();
148 * A cook may prepare a pizza if there is no current delivery order or if at least a pizza of the same order is
149 * in preparation or has been done!
151 private boolean mayPrepareCustomerPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
152 List<PizzaOrder> deliveryPizzas = readMatchingEntities(new PizzaOrder(), prepareDeliveryPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access prepareDeliveryPizzasContainer");
153 if (!deliveryPizzas.isEmpty()) {
154 final PizzaOrder template = new PizzaOrder();
155 template.setOrderId(pizzaOrder.getOrderId());
156 final List<PizzaOrder> pizzasAlreadyDone = readMatchingEntities(template, preparedPizzasContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA: Cannot access preparedPizzasContainer");
157 if(! pizzasAlreadyDone.isEmpty()) return true;
158 final List<PizzaOrder> pizzasOfOrderInProgress = readMatchingEntities(template, pizzaInProgressContainer, tx, RequestTimeout.INFINITE, "MAYPREPAREPIZZA:: Cannot access pizzaInProgressContainer");
159 if (! pizzasOfOrderInProgress.isEmpty()) return true;
167 private boolean mayPrepareDeliveryPizza(PizzaOrder pizzaOrder, TransactionReference tx) throws MzsCoreException {
168 // TODO: return false if a cook has already started cooking pizzas of an open order
172 private void notifyCustomerPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
173 sendItemsToContainer(Arrays.asList(pizza), preparedPizzasContainer, RequestTimeout.DEFAULT, tx);
174 final GroupData group = new GroupData();
175 final Order groupOrder = new Order();
176 groupOrder.setId(pizza.getOrderId());
177 group.setOrder(groupOrder);
178 group.setState(GroupState.ORDERED);
179 GroupData groupData = takeMatchingEntity(group, pizzeriaGroupContainer, tx, RequestTimeout.INFINITE, "Cannot take the group from pizzeriaGroupContainer");
180 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
181 for (PizzaOrder orderedPizza : orderedPizzas) {
182 if (orderedPizza.getId() == pizza.getId()) {
183 orderedPizza.setStatus(PizzaOrderStatus.DONE);
184 orderedPizza.setCookId(pizza.getCookId());
187 sendItemsToContainer(Arrays.asList(groupData), pizzeriaGroupContainer, RequestTimeout.DEFAULT, tx);
190 private void notifyDeliveryPizzaDone(PizzaOrder pizza, TransactionReference tx) throws MzsCoreException {
191 final DeliveryGroupData group = new DeliveryGroupData();
192 final Order groupOrder = new Order();
193 groupOrder.setId(pizza.getOrderId());
194 group.setOrder(groupOrder);
195 group.setDeliveryStatus(null);
196 DeliveryGroupData groupData = takeMatchingEntity(group, pizzeriaDeliveryContainer, tx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
197 final List<PizzaOrder> orderedPizzas = groupData.getOrder().getOrderedPizzas();
198 for (PizzaOrder orderedPizza : orderedPizzas) {
199 if (orderedPizza.getId() == pizza.getId()) {
200 orderedPizza.setStatus(PizzaOrderStatus.DONE);
201 orderedPizza.setCookId(pizza.getCookId());
204 sendItemsToContainer(Arrays.asList(groupData), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, tx);
207 private void notifyDeliveryPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) throws MzsCoreException {
208 log.info("I say that I now prepare a delivery pizza for order {}", pizzaInProgress.getOrderId());
209 final DeliveryGroupData groupTemplate = new DeliveryGroupData();
210 final Order groupOrder = new Order();
211 groupOrder.setId(order.getOrderId());
212 groupTemplate.setOrder(groupOrder);
213 groupTemplate.setDeliveryStatus(null);
214 final TransactionReference inPreparationTx = getDefaultTransaction();
215 final DeliveryGroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaDeliveryContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the delivery order from pizzeriaDeliveryContainer");
216 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
217 for (PizzaOrder orderedPizza : orderedPizzas) {
218 if (orderedPizza.getId() == pizzaInProgress.getId()) {
219 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
220 orderedPizza.setCookId(pizzaInProgress.getCookId());
223 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaDeliveryContainer, RequestTimeout.DEFAULT, inPreparationTx);
224 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
225 capi.commitTransaction(inPreparationTx);
228 private void notifyCustomerPizzaInProgress(PizzaOrder order, Pizza pizzaInProgress) {
230 log.info("I say that I now prepare a pizza for order {}", pizzaInProgress.getOrderId());
231 final GroupData groupTemplate = new GroupData();
232 final Order groupOrder = new Order();
233 groupOrder.setId(order.getOrderId());
234 groupTemplate.setOrder(groupOrder);
235 groupTemplate.setState(null);
236 final TransactionReference inPreparationTx = getDefaultTransaction();
237 final GroupData groupFromSpace = takeMatchingEntity(groupTemplate, pizzeriaGroupContainer, inPreparationTx, RequestTimeout.INFINITE, "Cannot take the order from pizzeriaGroupContainer");
238 final List<PizzaOrder> orderedPizzas = groupFromSpace.getOrder().getOrderedPizzas();
239 for (PizzaOrder orderedPizza : orderedPizzas) {
240 if (orderedPizza.getId() == pizzaInProgress.getId()) {
241 orderedPizza.setStatus(PizzaOrderStatus.IN_PREPARATION);
242 orderedPizza.setCookId(pizzaInProgress.getCookId());
245 sendItemsToContainer(Arrays.asList(groupFromSpace), pizzeriaGroupContainer, RequestTimeout.DEFAULT, inPreparationTx);
246 sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, inPreparationTx);
247 capi.commitTransaction(inPreparationTx);
248 } catch (Exception e) {
249 log.error("This error has occurred: {}", e.getMessage());
254 private PizzaOrder createPizza(PizzaOrder order) throws InterruptedException {
255 long duration = order.getPizzaType().duration;
256 Thread.sleep(duration * 1000);
258 PizzaOrder pizza = Pizza.createPizzaFromPizzaOrder(order, cookId, false);
259 pizza.setStatus(PizzaOrderStatus.DONE);