From d1b6b63ad2ce3562ea0299795637dd84bc8b5ffd Mon Sep 17 00:00:00 2001 From: Gregor Riegler Date: Fri, 10 May 2013 03:41:24 +0200 Subject: [PATCH] Space waiters pay and overall remaining space workflow refactoring --- .../tuwien/sbc/valesriegler/common/Util.java | 5 +- .../sbc/valesriegler/group/GroupAgent.java | 16 +- .../sbc/valesriegler/group/SpaceGroup.java | 17 + .../valesriegler/group/gui/GroupFrame.java | 1 + .../group/gui/GroupOverviewModel.java | 31 +- .../valesriegler/pizzeria/PizzeriaAgent.java | 4 +- .../gui/tablemodels/GroupsOverviewModel.java | 2 +- .../gui/tablemodels/OrdersOverviewModel.java | 59 ++- .../gui/tablemodels/TablesOverviewModel.java | 21 +- .../sbc/valesriegler/types/GroupData.java | 4 +- .../tuwien/sbc/valesriegler/types/Order.java | 8 +- .../tuwien/sbc/valesriegler/types/Pizza.java | 13 +- .../sbc/valesriegler/types/PizzaOrder.java | 9 +- .../xvsm/AbstractXVSMConnector.java | 72 ++- .../sbc/valesriegler/xvsm/CookXVSM.java | 26 +- .../sbc/valesriegler/xvsm/GroupAgentXVSM.java | 106 ++++- .../sbc/valesriegler/xvsm/GroupXVSM.java | 84 +++- .../valesriegler/xvsm/PizzeriaAgentXVSM.java | 115 ++++- .../sbc/valesriegler/xvsm/WaiterXVSM.java | 419 +++++++++++++----- .../sbc/valesriegler/xvsm/XVSMConnector.java | 151 ------- .../sbc/valesriegler/xvsm/cook/Cook.java | 2 - .../sbc/valesriegler/xvsm/waiter/Waiter.java | 20 +- 22 files changed, 799 insertions(+), 386 deletions(-) create mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/group/SpaceGroup.java delete mode 100644 src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/XVSMConnector.java diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java index b33a264..8c5efed 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/common/Util.java @@ -31,8 +31,11 @@ public abstract class Util { public static final String DELIVER_PIZZAS = "deliverPizzas"; public static final String PREPARE_PIZZAS = "preparePizzas"; public static final String PIZZAS_IN_PROGRESS = "pizzasInProgress"; + public static final String ORDER_COMPLETE = "orderComplete"; public static final String PAYMENT = "payment"; public static final String FREE_TABLES = "freeTables"; + public static final String IS_EATING = "isEating"; + public static final String HAS_PAID = "hasPaid"; public static final String SERVER_ADDR = "xvsm://localhost:9876"; @@ -49,7 +52,7 @@ public abstract class Util { } public static String getId(int id) { - return (id != 0 || id != -1) ? String.valueOf(id) : ""; + return (id != 0 && id != -1) ? String.valueOf(id) : ""; } public static int getIntSafe(Integer nr) { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java index 5125a33..e03c41d 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/GroupAgent.java @@ -1,16 +1,10 @@ package at.ac.tuwien.sbc.valesriegler.group; -import java.io.Serializable; -import java.rmi.server.Operation; import java.util.ArrayList; import java.util.List; -import javax.management.Notification; -import javax.management.NotificationListener; import javax.swing.SwingUtilities; -import org.mozartspaces.core.CapiUtil; -import org.mozartspaces.core.Entry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,9 +12,7 @@ import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.group.gui.GroupOverviewModel; import at.ac.tuwien.sbc.valesriegler.group.jms.JMSGroupConnector; import at.ac.tuwien.sbc.valesriegler.types.GroupData; -import at.ac.tuwien.sbc.valesriegler.xvsm.AbstractXVSMConnector; import at.ac.tuwien.sbc.valesriegler.xvsm.GroupAgentXVSM; -import at.ac.tuwien.sbc.valesriegler.xvsm.XVSMConnector; /** * The Main class of the Group component. @@ -57,6 +49,9 @@ public class GroupAgent { xvsm = new GroupAgentXVSM(); xvsm.listenForGroupDataChanges(); + xvsm.listenForDeliveredOrders(); + xvsm.listenForPaymentRequest(); + xvsm.listenForPayment(); } } @@ -82,6 +77,11 @@ public class GroupAgent { xvsm.sendNewGroupsToSpace(groupData); log.info("New Groups were sent to the space"); + + // start the space group in a new thread + for (GroupData group : groupData) { + new Thread(new SpaceGroup(group.getId())).start(); + } } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/SpaceGroup.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/SpaceGroup.java new file mode 100644 index 0000000..0f0ee39 --- /dev/null +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/SpaceGroup.java @@ -0,0 +1,17 @@ +package at.ac.tuwien.sbc.valesriegler.group; + +import at.ac.tuwien.sbc.valesriegler.xvsm.GroupXVSM; + +public class SpaceGroup implements Runnable { + private GroupXVSM xvsm; + + public SpaceGroup(int groupId) { + xvsm = new GroupXVSM(groupId); + } + + @Override + public void run() { + xvsm.waitForMyOrder(); + } + +} diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupFrame.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupFrame.java index 48ee7b7..b752e5b 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupFrame.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupFrame.java @@ -155,6 +155,7 @@ public class GroupFrame extends JFrame { pizzaOrder.setOrderId(order.getId()); } group.getGroupData().setOrder(order); + order.setNumberOfPizzas(order.getOrderedPizzas().size()); newGroups.add(group); } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupOverviewModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupOverviewModel.java index adf9167..e4ca48c 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupOverviewModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/group/gui/GroupOverviewModel.java @@ -12,6 +12,8 @@ import at.ac.tuwien.sbc.valesriegler.common.TableModel; import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.group.Group; import at.ac.tuwien.sbc.valesriegler.types.GroupData; +import at.ac.tuwien.sbc.valesriegler.types.GroupState; +import at.ac.tuwien.sbc.valesriegler.types.Order; import at.ac.tuwien.sbc.valesriegler.types.PizzaOrder; import at.ac.tuwien.sbc.valesriegler.types.PizzaType; @@ -54,11 +56,9 @@ public class GroupOverviewModel extends TableModel { switch (wantedColumn) { case ID: int groupId = group.getGroupData().getId(); -// log.info("This is the group id : {}", groupId); return groupId; case SIZE: int groupSize = group.getGroupData().getSize(); -// log.info("This is the size : {}", groupSize); return groupSize; case PIZZAS: if (group.getGroupData().getOrder() == null) @@ -129,4 +129,31 @@ public class GroupOverviewModel extends TableModel { } super.addItems(groups); } + + public void updateOrderDone(int groupId) { + if(stateIs(groupId, GroupState.GONE) || stateIs(groupId, GroupState.PAY)) return; + changeStateOfGroup(groupId, GroupState.EATING); + } + + public void updateGroupPaymentPending(int groupId) { + if(stateIs(groupId, GroupState.GONE)) return; + changeStateOfGroup(groupId, GroupState.PAY); + } + + private boolean stateIs(int groupId, GroupState state) { + return items.get(groupId).getGroupData().getState() == state; + } + + + public void updateGroupHasPaid(int groupId) { + + changeStateOfGroup(groupId, GroupState.GONE); + } + + private void changeStateOfGroup(int groupId, GroupState state) { + items.get(groupId).getGroupData().setState(state); + + fireTableDataChanged(); + } + } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java index 8551062..06973c5 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/PizzeriaAgent.java @@ -82,8 +82,10 @@ public class PizzeriaAgent { xvsm.listenForTables(); xvsm.listenForGroups(); - xvsm.listenForOrders(); xvsm.listenForPizzasInPreparation(); + xvsm.listenForDeliveredOrders(); + xvsm.listenForPreparedPizzas(); + xvsm.listenForPayment(); } private void initGUI() { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/GroupsOverviewModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/GroupsOverviewModel.java index 966cf22..b4c1482 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/GroupsOverviewModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/GroupsOverviewModel.java @@ -42,7 +42,7 @@ public class GroupsOverviewModel extends TableModel { while (it.hasNext()) { GroupData groupData = it.next(); // Show only the waiting groups! - if(groupData.getState() != GroupState.NEW) { + if(groupData.getState() == GroupState.NEW || groupData.getState() == GroupState.WAITING) { it.remove(); } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/OrdersOverviewModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/OrdersOverviewModel.java index 14d4bb8..e6547e8 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/OrdersOverviewModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/OrdersOverviewModel.java @@ -1,7 +1,6 @@ package at.ac.tuwien.sbc.valesriegler.pizzeria.gui.tablemodels; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; @@ -12,10 +11,10 @@ import at.ac.tuwien.sbc.valesriegler.common.TableModel; import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.types.GroupData; import at.ac.tuwien.sbc.valesriegler.types.Order; +import at.ac.tuwien.sbc.valesriegler.types.OrderStatus; import at.ac.tuwien.sbc.valesriegler.types.Pizza; import at.ac.tuwien.sbc.valesriegler.types.PizzaOrder; import at.ac.tuwien.sbc.valesriegler.types.PizzaOrderStatus; -import at.ac.tuwien.sbc.valesriegler.xvsm.PizzeriaAgentXVSM; public class OrdersOverviewModel extends TableModel { private static final Logger log = LoggerFactory.getLogger(OrdersOverviewModel.class); @@ -46,18 +45,7 @@ public class OrdersOverviewModel extends TableModel { throw new RuntimeException(UNHANDLEDCOLUMN); } } - - public Order getOrderById(int orderId) { - synchronized (items) { - List groups = new ArrayList(items.values()); - for (GroupData groupData : groups) { - if(groupData.getOrder().getId() == orderId) { - return groupData.getOrder(); - } - } - throw new RuntimeException(String.format("Order with orderId %d not found!", orderId)); - } - } + public GroupData getGroupOfRow(int rowIndex) { synchronized (items) { @@ -96,5 +84,48 @@ public class OrdersOverviewModel extends TableModel { fireTableDataChanged(); } + + public void updateStatusOfOrder(GroupData group) { + synchronized(items) { + Order order = group.getOrder(); + List groups = new ArrayList(items.values()); + for (GroupData groupData : groups) { + Order orderOfGroup = groupData.getOrder(); + if(order.getId() == orderOfGroup.getId()) { + orderOfGroup.setStatus(OrderStatus.DELIVERED); + groupData.setServingWaiter(group.getServingWaiter()); + } + } + } + + fireTableDataChanged(); + } + + + public void updateStatusOfPizzasDone(Pizza pizza) { + int orderId = pizza.getOrderId(); + synchronized(items) { + Order order = getOrderById(orderId); + List orderedPizzas = order.getOrderedPizzas(); + for (PizzaOrder pizzaOrder : orderedPizzas) { + if(pizzaOrder.getId() == pizza.getId()) { + pizzaOrder.setStatus(PizzaOrderStatus.DONE); + log.info("Status of pizza was set to DONE"); + } + } + } + + fireTableDataChanged(); + } + + private Order getOrderById(int orderId) { + List groups = new ArrayList(items.values()); + for (GroupData groupData : groups) { + if(groupData.getOrder().getId() == orderId) { + return groupData.getOrder(); + } + } + throw new RuntimeException(String.format("Order with orderId %d not found!", orderId)); + } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/TablesOverviewModel.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/TablesOverviewModel.java index ded871b..c85e0ca 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/TablesOverviewModel.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/pizzeria/gui/tablemodels/TablesOverviewModel.java @@ -5,6 +5,7 @@ import java.util.List; import at.ac.tuwien.sbc.valesriegler.common.TableModel; import at.ac.tuwien.sbc.valesriegler.common.Util; +import at.ac.tuwien.sbc.valesriegler.types.GroupData; import at.ac.tuwien.sbc.valesriegler.types.Table; public class TablesOverviewModel extends TableModel { @@ -12,7 +13,6 @@ public class TablesOverviewModel extends TableModel
{ private static final String STATUS = "Is free"; private static final String GROUP_ID = "Group ID"; private static final String[] COLUMNS = new String[] { TABLE_ID, STATUS, GROUP_ID }; - private int idCounter = 1; @Override protected String[] getColumns() { @@ -61,7 +61,7 @@ public class TablesOverviewModel extends TableModel
{ tables.add(table); } -// setItems(tables); + if(Util.useJMS) setItems(tables); return tables; } @@ -69,4 +69,21 @@ public class TablesOverviewModel extends TableModel
{ private Table createFreeTable() { return new Table(); } + + public int getTableIdOfGroup(GroupData group) { + synchronized (items) { + for (Table table : items.values()) { + if(table.getGroupId() == group.getId()) { + return table.getId(); + } + } + } + throw new RuntimeException("Could not find table with the wanted group"); + } + + public void makeTableFree(int tableId) { + items.put(tableId, new Table(tableId)); + + fireTableDataChanged(); + } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/GroupData.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/GroupData.java index 1fd577d..76c68d3 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/GroupData.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/GroupData.java @@ -23,7 +23,7 @@ public class GroupData implements Serializable, HasId { private static final Logger log = LoggerFactory.getLogger(GroupData.class); private Integer id; - private GroupState state = GroupState.NEW; + private GroupState state = GroupState.WAITING; private Integer size; private Table table; @@ -96,7 +96,7 @@ public class GroupData implements Serializable, HasId { } public void setOrder(Order order) { - order.setGroupId(id); +// order.setGroupId(Util.getIntSafe(id)); this.order = order; } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Order.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Order.java index 3d84368..7a09760 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Order.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Order.java @@ -1,9 +1,10 @@ package at.ac.tuwien.sbc.valesriegler.types; import java.io.Serializable; -import java.util.ArrayList; import java.util.List; +import org.mozartspaces.capi3.Queryable; + import at.ac.tuwien.sbc.valesriegler.common.HasId; import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.group.Group; @@ -15,6 +16,7 @@ import at.ac.tuwien.sbc.valesriegler.group.Group; * @author jan * */ +@Queryable(autoindex=true) public class Order implements Serializable, HasId { private static int idNext = 0; private Integer id; @@ -22,11 +24,13 @@ public class Order implements Serializable, HasId { private OrderStatus status; private List orderedPizzas; - private List cookedPizzas = new ArrayList<>(); + private List cookedPizzas; // this is necessary so that i can make a xvsm linda selection on it private Integer numberOfPizzas; + public Order() {} + public Order(int groupId, List orderedPizzas) { id = ++idNext; this.groupId = groupId; diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java index bbd1bfd..021176c 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/Pizza.java @@ -25,15 +25,22 @@ public class Pizza extends PizzaOrder implements Serializable { this.orderId = orderId; } + public Pizza() { + super(); + } + public static Pizza createPizzaFromPizzaOrder(PizzaOrder pizzaorder, int cookId) { return new Pizza(pizzaorder.getId(), pizzaorder.getPizzaType(), cookId, pizzaorder.getOrderId()); } - - @Override public String toString() { - return "Pizza [pizzaType=" + pizzaType + ", id=" + id + ", cookId=" + cookId + ", deliveryAgent=" + deliveryAgent + "]"; + return "Pizza [deliveryAgent=" + deliveryAgent + ", id=" + id + + ", orderId=" + orderId + ", pizzaType=" + pizzaType + + ", status=" + status + ", cookId=" + cookId + "]"; } + + + } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/PizzaOrder.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/PizzaOrder.java index f12742a..4a1929e 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/types/PizzaOrder.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/types/PizzaOrder.java @@ -18,8 +18,8 @@ public class PizzaOrder implements Serializable, HasId { protected Integer orderId; protected PizzaType pizzaType; protected PizzaOrderStatus status; - protected int cookId; - + protected Integer cookId; + public PizzaOrder(PizzaType pizzaType) { id = ++nextID; this.pizzaType = pizzaType; @@ -30,6 +30,9 @@ public class PizzaOrder implements Serializable, HasId { this.id = id; } + public PizzaOrder() { + } + public PizzaType getPizzaType() { return pizzaType; } @@ -43,7 +46,7 @@ public class PizzaOrder implements Serializable, HasId { } public int getCookId() { - return cookId; + return Util.getIntSafe(cookId); } public void setCookId(int cookId) { diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java index 649819c..89fff67 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/AbstractXVSMConnector.java @@ -1,6 +1,7 @@ package at.ac.tuwien.sbc.valesriegler.xvsm; import java.io.Serializable; +import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -15,6 +16,7 @@ import org.mozartspaces.core.CapiUtil; import org.mozartspaces.core.ContainerReference; import org.mozartspaces.core.DefaultMzsCore; import org.mozartspaces.core.Entry; +import org.mozartspaces.core.MzsConstants; import org.mozartspaces.core.MzsTimeoutException; import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.core.MzsCore; @@ -41,6 +43,9 @@ public abstract class AbstractXVSMConnector { protected ContainerReference paymentContainer; protected ContainerReference freeTablesContainer; protected ContainerReference pizzaInProgressContainer; + protected ContainerReference orderCompleteContainer; + protected ContainerReference isEatingContainer; + protected ContainerReference hasPaidContainer; protected Capi capi; protected NotificationManager notificationMgr; @@ -59,53 +64,17 @@ public abstract class AbstractXVSMConnector { } } - public void usePizzaInProgressContainer() { - pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useTablesContainer() { - tablesContainer = useContainer(Util.TABLES_CONTAINER, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void usePreparePizzasContainer() { - preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useTakeOrderContainer() { - takeOrderContainer = useContainer(Util.TAKE_ORDER, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useOrdersContainer() { - ordersContainer = useContainer(Util.ORDER, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useGroupsContainer() { - groupsContainer = useContainer(Util.GROUPS_CONTAINER, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useAssignTableContainer() { - assignTableContainer = useContainer(Util.ASSIGN_TABLE, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))) ; - } - - public void useFreeTablesContainer() { - freeTablesContainer = useContainer(Util.FREE_TABLES, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))); - } - - public void useDeliverPizzasContainer() { - deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS, createCoordinators(new AnyCoordinator(), new LindaCoordinator(false))); - } - - private ContainerReference useContainer(String containerName, List coordinators) { + protected ContainerReference useContainer(String containerName) { try { - return Util.getOrCreateNamedContainer(Util.SERVER_ADDR, containerName, capi, coordinators); + return CapiUtil.lookupOrCreateContainer(containerName, URI.create(Util.SERVER_ADDR), createCoordinators(new AnyCoordinator(), new LindaCoordinator(false)), null, capi); } catch (MzsCoreException e) { handleSpaceErrorAndTerminate(e); } - return null; + throw new RuntimeException("Could not Create container " + containerName); } - private List createCoordinators(Coordinator... coordinator) { + protected List createCoordinators(Coordinator... coordinator) { return Arrays.asList(coordinator); } @@ -131,12 +100,11 @@ public abstract class AbstractXVSMConnector { } @SuppressWarnings("unchecked") - protected T takeEntityByTemplateFromContainer( + protected T takeMatchingEntity( T entity, ContainerReference ref, TransactionReference tx, long timeout, String errorMsg) throws MzsCoreException { try { LindaSelector sel = LindaCoordinator.newSelector(entity, 1); - T singleEntity = null; ArrayList entities = capi.take(ref, sel, timeout, tx); @@ -151,6 +119,26 @@ public abstract class AbstractXVSMConnector { throw new EntityNotFoundByTemplate(errorMsg); } } + + protected List takeMatchingEntities( + T entity, ContainerReference ref, TransactionReference tx, long timeout, String errorMsg) + throws MzsCoreException { + try { + LindaSelector sel = LindaCoordinator.newSelector(entity, MzsConstants.Selecting.COUNT_MAX); + + ArrayList entities = capi.take(ref, sel, timeout, tx); + + return (List) entities; + } catch (CountNotMetException e) { + capi.rollbackTransaction(tx); + + throw new EntityNotFoundByTemplate(errorMsg); + } catch(MzsTimeoutException e) { + capi.rollbackTransaction(tx); + + throw new EntityNotFoundByTemplate(errorMsg); + } + } protected List castEntries(List entries) { List newList = new ArrayList(); diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java index c085312..3ad7327 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/CookXVSM.java @@ -6,6 +6,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.core.TransactionException; import org.mozartspaces.core.TransactionReference; @@ -29,11 +31,11 @@ public class CookXVSM extends AbstractXVSMConnector { super(); this.cookId = id; - useGroupsContainer(); - useOrdersContainer(); - useDeliverPizzasContainer(); - usePreparePizzasContainer(); - usePizzaInProgressContainer(); + groupsContainer = useContainer(Util.GROUPS_CONTAINER) ; + ordersContainer = useContainer(Util.ORDER) ; + deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS); + preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS) ; + pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS) ; } public void listenForPizzas() { @@ -44,11 +46,7 @@ public class CookXVSM extends AbstractXVSMConnector { log.info("New Pizzas to prepare!"); List pizzas = castEntries(entries); - for (PizzaOrder pizzaOrder : pizzas) { - log.info("I must prepare this fucking pizza:"); - log.info(pizzaOrder.toString()); - } - Collections.shuffle(pizzas); + Collections.rotate(pizzas, cookId); for (PizzaOrder pizzaOrder : pizzas) { try { try { @@ -56,7 +54,7 @@ public class CookXVSM extends AbstractXVSMConnector { String pizzaAlreadyCooked = String.format("Pizza with id %d has already been cooked by another cook", pizzaOrder.getId()); // Require the lock for preparing the pizza - PizzaOrder order = takeEntityByTemplateFromContainer(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, 1000, pizzaAlreadyCooked); + PizzaOrder order = takeMatchingEntity(new PizzaOrder(pizzaOrder.getId()), preparePizzasContainer, tx, 1000, pizzaAlreadyCooked); // tell the space that you prepare the pizza -> without a transaction!! Pizza pizzaInProgress = Pizza.createPizzaFromPizzaOrder(order, cookId); @@ -67,15 +65,19 @@ public class CookXVSM extends AbstractXVSMConnector { sendItemsToContainer(Arrays.asList(pizzaInProgress), pizzaInProgressContainer, RequestTimeout.DEFAULT, null); PizzaOrder pizza = createPizza(order); + sendItemsToContainer(Arrays.asList(pizza), deliverPizzasContainer, RequestTimeout.DEFAULT, tx); capi.commitTransaction(tx); + log.info("I have completed preparing a pizza for order {}!", pizza.getOrderId()); } catch (IllegalArgumentException e) { log.info("IllegalArgumentException"); e.printStackTrace(); } catch (EntityNotFoundByTemplate e) { log.info(e.getMessage()); - } catch (Exception e) { + } catch (NullPointerException e) { + // for some reason mozartspaces throws a npe but it doesn't seem to mean anything + } catch (Exception e) { log.error("AN INNER EXCEPTION"); e.printStackTrace(); } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java index 0f476d8..3baada2 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupAgentXVSM.java @@ -5,6 +5,8 @@ import java.util.List; import javax.swing.SwingUtilities; +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; import org.mozartspaces.core.MzsCoreException; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; @@ -12,16 +14,50 @@ import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.group.GroupAgent; +import at.ac.tuwien.sbc.valesriegler.group.SpaceGroup; +import at.ac.tuwien.sbc.valesriegler.pizzeria.PizzeriaAgent; import at.ac.tuwien.sbc.valesriegler.types.GroupData; +import at.ac.tuwien.sbc.valesriegler.types.Order; public class GroupAgentXVSM extends AbstractXVSMConnector { private static final Logger log = LoggerFactory.getLogger(GroupAgentXVSM.class); public GroupAgentXVSM() { super(); - useGroupsContainer(); - useAssignTableContainer(); + groupsContainer = useContainer(Util.GROUPS_CONTAINER) ; + assignTableContainer = useContainer(Util.ASSIGN_TABLE) ; + orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; + paymentContainer = useContainer(Util.PAYMENT) ; + hasPaidContainer = useContainer(Util.HAS_PAID) ; + } + + public void listenForDeliveredOrders() { + NotificationListener deliveredOrders = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + final List groups = castEntries(entries); + + log.info("{} order was delivered!", groups.size()); + if(groups.size() != 1) { + throw new RuntimeException("A waiter should only deliver one order at once!"); + } + final int groupId = groups.get(0).getOrder().getId(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GroupAgent.getInstance().getGroupModel().updateOrderDone(groupId); + } + }); + } + }; + try { + notificationMgr.createNotification(orderCompleteContainer, deliveredOrders, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } } public void listenForGroupDataChanges() { @@ -45,12 +81,68 @@ public class GroupAgentXVSM extends AbstractXVSMConnector { try { notificationMgr.createNotification(groupsContainer, groupDataListener, Operation.WRITE); log.info("Created groupsContainer notification for a waiter"); - } catch (MzsCoreException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } } + public void listenForPaymentRequest() { + NotificationListener paymentRequest = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + log.info("PAY REQUEST by"); + final List groups = castEntries(entries); + + if(groups.size() != 1) { + throw new RuntimeException("A group only says as a whole that it wants to pay"); + } + final GroupData group = groups.get(0); + log.info("PAY REQUEST by {}", group.getId()); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GroupAgent.getInstance().getGroupModel().updateGroupPaymentPending(group.getId()); + } + }); + + } + }; + try { + notificationMgr.createNotification(paymentContainer, paymentRequest, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + + public void listenForPayment() { + NotificationListener payment = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + + final List groups = castEntries(entries); + + if(groups.size() != 1) { + throw new RuntimeException("A group can only have paid as a whole!"); + } + final GroupData group = groups.get(0); + + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + GroupAgent.getInstance().getGroupModel().updateGroupHasPaid(group.getId()); + } + }); + + } + }; + try { + notificationMgr.createNotification(hasPaidContainer, payment, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java index 2c92586..aa7dacd 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/GroupXVSM.java @@ -1,8 +1,90 @@ package at.ac.tuwien.sbc.valesriegler.xvsm; +import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import javax.swing.SwingUtilities; + +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.core.MzsConstants.RequestTimeout; +import org.mozartspaces.notifications.Notification; +import org.mozartspaces.notifications.NotificationListener; +import org.mozartspaces.notifications.Operation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.ac.tuwien.sbc.valesriegler.common.Util; +import at.ac.tuwien.sbc.valesriegler.types.GroupData; +import at.ac.tuwien.sbc.valesriegler.types.Order; +import at.ac.tuwien.sbc.valesriegler.types.Table; + public class GroupXVSM extends AbstractXVSMConnector { + private static final Logger log = LoggerFactory.getLogger(GroupXVSM.class); + + private int groupId; + + private Random random = new Random(); - public GroupXVSM() { + public GroupXVSM(int groupId) { + super(); + this.groupId = groupId; + + paymentContainer = useContainer(Util.PAYMENT) ; + orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; + isEatingContainer = useContainer(Util.IS_EATING) ; + freeTablesContainer = useContainer(Util.FREE_TABLES) ; + } + + public void waitForMyOrder() { + log.info("Thred started for group {}", groupId); + NotificationListener deliveredOrders = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + final List groups = castEntries(entries); + + final Order order = groups.get(0).getOrder(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + + if(order.getGroupId() == groupId) { + eatAndThenPay(); + } + } + }); + + } + }; + try { + notificationMgr.createNotification(orderCompleteContainer, deliveredOrders, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + + private void eatAndThenPay() { + int timeToEat = getRandom(3, 5); + log.info("I eat {} seconds now...", timeToEat); + + GroupData groupData = new GroupData(); + groupData.setId(groupId); + + try { + Thread.sleep(timeToEat * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + sendItemsToContainer(Arrays.asList(groupData), paymentContainer, RequestTimeout.DEFAULT, null); + log.info("I sent my payment request to the space! GroupId: {}", groupId); + } + + private int getRandom(int min, int max){ + return random.nextInt(max - min + 1) + min; } } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java index 45a6854..0688823 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/PizzeriaAgentXVSM.java @@ -1,20 +1,29 @@ package at.ac.tuwien.sbc.valesriegler.xvsm; import java.io.Serializable; +import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.swing.SwingUtilities; +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.core.MzsCoreException; +import org.mozartspaces.core.TransactionReference; +import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.notifications.Notification; import org.mozartspaces.notifications.NotificationListener; import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.ac.tuwien.sbc.valesriegler.common.Util; import at.ac.tuwien.sbc.valesriegler.pizzeria.PizzeriaAgent; import at.ac.tuwien.sbc.valesriegler.types.GroupData; import at.ac.tuwien.sbc.valesriegler.types.GroupState; +import at.ac.tuwien.sbc.valesriegler.types.Order; import at.ac.tuwien.sbc.valesriegler.types.Pizza; import at.ac.tuwien.sbc.valesriegler.types.PizzaOrder; import at.ac.tuwien.sbc.valesriegler.types.Table; @@ -24,10 +33,13 @@ public class PizzeriaAgentXVSM extends AbstractXVSMConnector { public PizzeriaAgentXVSM() { super(); - useTablesContainer(); - useGroupsContainer(); - useFreeTablesContainer(); - usePizzaInProgressContainer(); + tablesContainer = useContainer(Util.TABLES_CONTAINER) ; + groupsContainer = useContainer(Util.GROUPS_CONTAINER) ; + freeTablesContainer = useContainer(Util.FREE_TABLES); + pizzaInProgressContainer = useContainer(Util.PIZZAS_IN_PROGRESS) ; + orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; + deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS); + hasPaidContainer = useContainer(Util.HAS_PAID) ; } public void listenForTables() { @@ -60,12 +72,6 @@ public class PizzeriaAgentXVSM extends AbstractXVSMConnector { public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { final List groups = castEntries(entries); -// log.info("{} group changes!", groups.size()); -// for (GroupData groupData : groups) { -// log.info(groupData.toString()); -// -// } - SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -90,9 +96,6 @@ public class PizzeriaAgentXVSM extends AbstractXVSMConnector { } } - public void listenForOrders() { - } - public void listenForPizzasInPreparation() { NotificationListener pizzasInProgress = new NotificationListener() { @Override @@ -120,5 +123,91 @@ public class PizzeriaAgentXVSM extends AbstractXVSMConnector { } } + public void listenForDeliveredOrders() { + NotificationListener deliveredOrders = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + final List groups = castEntries(entries); + + log.info("{} order was delivered!", groups.size()); + if(groups.size() != 1) { + throw new RuntimeException("A waiter should only deliver one order at once!"); + } + final GroupData group = groups.get(0); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + PizzeriaAgent.getInstance().getOrdersModel().updateStatusOfOrder(group); + } + }); + + } + }; + try { + notificationMgr.createNotification(orderCompleteContainer, deliveredOrders, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + + public void listenForPreparedPizzas() { + NotificationListener preparedPizzasListener = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + + List pizzas = castEntries(entries); + if(pizzas.size() != 1) throw new RuntimeException("Multiple pizzas in one notification?! That should not happen! A cook can only prepare one at the same time!"); + + final Pizza pizza = pizzas.get(0); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + PizzeriaAgent.getInstance().getOrdersModel().updateStatusOfPizzasDone(pizza); + } + }); + + } + }; + + try { + notificationMgr.createNotification(deliverPizzasContainer, preparedPizzasListener, Operation.WRITE); + log.info("Created deliverPizzasContainer notification for the pizzeria"); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + + public void listenForPayment() { + NotificationListener isGoneListener = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { + final List groups = castEntries(entries); + + final GroupData group = groups.get(0); + log.info("Group {} is gone", group.getId()); + + final int tableId = PizzeriaAgent.getInstance().getTablesModel().getTableIdOfGroup(group); + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + PizzeriaAgent.getInstance().getTablesModel().makeTableFree(tableId); + } + }); + + Table table = new Table(tableId); + + sendItemsToContainer(Arrays.asList(table), freeTablesContainer, RequestTimeout.DEFAULT, null); + } + }; + try { + notificationMgr.createNotification(hasPaidContainer, isGoneListener, Operation.WRITE); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java index 66c80cb..ff1f7a9 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/WaiterXVSM.java @@ -5,12 +5,16 @@ import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; import java.util.List; -import org.mozartspaces.capi3.CountNotMetException; +import javax.swing.text.html.parser.Entity; + +import org.mozartspaces.capi3.AnyCoordinator; +import org.mozartspaces.capi3.LindaCoordinator; +import org.mozartspaces.core.MzsConstants; import org.mozartspaces.core.MzsConstants.RequestTimeout; import org.mozartspaces.core.MzsCoreException; -import org.mozartspaces.core.MzsTimeoutException; import org.mozartspaces.core.TransactionException; import org.mozartspaces.core.TransactionReference; import org.mozartspaces.notifications.Notification; @@ -24,63 +28,81 @@ import at.ac.tuwien.sbc.valesriegler.types.GroupData; import at.ac.tuwien.sbc.valesriegler.types.GroupState; import at.ac.tuwien.sbc.valesriegler.types.Order; import at.ac.tuwien.sbc.valesriegler.types.OrderStatus; -import at.ac.tuwien.sbc.valesriegler.types.PizzaOrder; +import at.ac.tuwien.sbc.valesriegler.types.Pizza; import at.ac.tuwien.sbc.valesriegler.types.Table; public class WaiterXVSM extends AbstractXVSMConnector { private static final Logger log = LoggerFactory.getLogger(WaiterXVSM.class); private final int waiterId; - + public WaiterXVSM(int waiterId) { super(); - + this.waiterId = waiterId; - - useFreeTablesContainer(); - useAssignTableContainer(); - useTablesContainer(); - useTakeOrderContainer(); - useOrdersContainer(); - usePreparePizzasContainer(); - useGroupsContainer(); + + freeTablesContainer = useContainer(Util.FREE_TABLES); + assignTableContainer = useContainer(Util.ASSIGN_TABLE) ; + tablesContainer = useContainer(Util.TABLES_CONTAINER) ; + takeOrderContainer = useContainer(Util.TAKE_ORDER) ; + ordersContainer = useContainer(Util.ORDER) ; + preparePizzasContainer = useContainer(Util.PREPARE_PIZZAS) ; + groupsContainer = useContainer(Util.GROUPS_CONTAINER) ; + orderCompleteContainer = useContainer(Util.ORDER_COMPLETE) ; + deliverPizzasContainer = useContainer(Util.DELIVER_PIZZAS); + paymentContainer = useContainer(Util.PAYMENT) ; + hasPaidContainer = useContainer(Util.HAS_PAID) ; } - + public void listenForFreeTable() { - + NotificationListener freeTableListener = new NotificationListener() { - @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - + @Override + public void entryOperationFinished(final Notification notification, + final Operation operation, + final List entries) { + log.info("{} tables have become free", entries.size()); - + List
tables = castEntries(entries); Collections.shuffle(tables); - + for (Table table : tables) { try { - TransactionReference tx = capi.createTransaction(3000, URI.create(Util.SERVER_ADDR)); - + TransactionReference tx = capi.createTransaction(3000, + URI.create(Util.SERVER_ADDR)); + try { - // Acquire a lock for the free table in the FreeTableContainer + // Acquire a lock for the free table in the + // FreeTableContainer int id = table.getId(); log.info("Try to find the table with id {}", id); - + Table tableTemplate = new Table(id); - Table lockedFreeTable = takeEntityByTemplateFromContainer(tableTemplate, freeTablesContainer, tx, 1000, String.format("There was no free table found with id %d", id)); - + Table lockedFreeTable = takeMatchingEntity( + tableTemplate, + freeTablesContainer, + tx, + 1000, + String.format( + "There was no free table found with id %d", + id)); + log.info("Table with id {} was found", id); - + GroupData groupTemplate = new GroupData(); - GroupData lockedGroup = takeEntityByTemplateFromContainer(groupTemplate, assignTableContainer, tx, RequestTimeout.DEFAULT, "There is no group waiting for a table at the moment"); - + GroupData lockedGroup = takeMatchingEntity( + groupTemplate, assignTableContainer, tx, + RequestTimeout.DEFAULT, + "There is no group waiting for a table at the moment"); + assignGroupToTable(lockedGroup, lockedFreeTable, tx); - + } catch (IllegalArgumentException e) { log.info("IllegalArgumentException"); e.printStackTrace(); } catch (EntityNotFoundByTemplate e) { log.info(e.getMessage()); - } catch (Exception e) { + } catch (Exception e) { log.error("AN INNER EXCEPTION"); e.printStackTrace(); } @@ -89,49 +111,67 @@ public class WaiterXVSM extends AbstractXVSMConnector { } catch (Exception e) { log.error("OUTER EXCEPTION"); } - + } - } - }; - try { - notificationMgr.createNotification(freeTablesContainer, freeTableListener, Operation.WRITE); + } + }; + try { + notificationMgr.createNotification(freeTablesContainer, + freeTableListener, Operation.WRITE); log.info("Created freeTablesContainer notification for a waiter"); - } catch (Exception e) { + } catch (Exception e) { handleSpaceErrorAndTerminate(e); } - + } - + public void listenForNewGuests() { NotificationListener newGroupsListener = new NotificationListener() { - @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - + @Override + public void entryOperationFinished(final Notification notification, + final Operation operation, + final List entries) { + log.info("New guest groups have arrived"); - + List groups = castEntries(entries); Collections.shuffle(groups); - + for (GroupData group : groups) { try { - TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR)); - + TransactionReference tx = capi.createTransaction(1500, + URI.create(Util.SERVER_ADDR)); + try { - // Acquire a lock for the group in the AssignTableContainer - String groupNotFound = String.format("Group with id %d was already assigned a table by another waiter!", group.getId()); - - GroupData lockedGroup = takeEntityByTemplateFromContainer(new GroupData(group.getId()), assignTableContainer, tx, 1000, groupNotFound); - // Acquire a lock for one free table in the TablesContainer - Table lockedFreeTable = takeEntityByTemplateFromContainer(new Table(null), freeTablesContainer, tx, RequestTimeout.DEFAULT, String.format("No free table for group with id %d could be found", group.getId())); - + // Acquire a lock for the group in the + // AssignTableContainer + String groupNotFound = String + .format("Group with id %d was already assigned a table by another waiter!", + group.getId()); + + GroupData lockedGroup = takeMatchingEntity( + new GroupData(group.getId()), + assignTableContainer, tx, 1000, + groupNotFound); + // Acquire a lock for one free table in the + // TablesContainer + Table lockedFreeTable = takeMatchingEntity( + new Table(null), + freeTablesContainer, + tx, + RequestTimeout.DEFAULT, + String.format( + "No free table for group with id %d could be found", + group.getId())); + assignGroupToTable(lockedGroup, lockedFreeTable, tx); - + } catch (IllegalArgumentException e) { log.info("IllegalArgumentException"); e.printStackTrace(); } catch (EntityNotFoundByTemplate e) { log.info(e.getMessage()); - } catch (Exception e) { + } catch (Exception e) { log.error("AN INNER EXCEPTION"); e.printStackTrace(); } @@ -140,66 +180,230 @@ public class WaiterXVSM extends AbstractXVSMConnector { } catch (Exception e) { log.error("OUTER EXCEPTION"); } - + } - } - }; - try { - notificationMgr.createNotification(assignTableContainer, newGroupsListener, Operation.WRITE); + } + }; + try { + notificationMgr.createNotification(assignTableContainer, + newGroupsListener, Operation.WRITE); log.info("Created assingTableContainer notification for a waiter"); - } catch (Exception e) { + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } + } + + public void listenForPaymentRequest() { + log.info("INITIALIZE PAYMENT NOTIFICATION"); + NotificationListener paymentListener = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, + final Operation operation, + final List entries) { + log.info("A PAYMENT REQUEST HAS ARRIVED!"); + + List groups = castEntries(entries); + + GroupData groupData = groups.get(0); + + try { + TransactionReference tx = capi.createTransaction(1500, + URI.create(Util.SERVER_ADDR)); + GroupData entity = new GroupData(groupData.getId()); + + // Acquire the lock so that another waiter can't do the same + // thing! + takeMatchingEntity( + entity, + paymentContainer, + tx, + RequestTimeout.DEFAULT, + String.format( + "The payment request for group %d was already taken by an other waiter!", + groupData.getId())); + + + groupData.setPayingWaiter(waiterId); + + sendItemsToContainer(Arrays.asList(groupData), + hasPaidContainer, RequestTimeout.ZERO, tx); + + capi.commitTransaction(tx); + + } catch (MzsCoreException e) { + log.info("ERROR in listenForPaymentRequest"); + e.printStackTrace(); + } + } + }; + + try { + notificationMgr.createNotification(paymentContainer, + paymentListener, Operation.WRITE); + log.info("Created payment notification for a waiter"); + } catch (Exception e) { handleSpaceErrorAndTerminate(e); } } public void listenForOrders() { NotificationListener ordersListener = new NotificationListener() { - @Override - public void entryOperationFinished(final Notification notification, final Operation operation, final List entries) { - log.info("A new order has arrived!"); - - List groups = castEntries(entries); - if(groups.size() != 1) throw new RuntimeException("Multiple orders in one notification?! That should not happen!"); - - GroupData groupData = groups.get(0); - - try { - TransactionReference tx = capi.createTransaction(1500, URI.create(Util.SERVER_ADDR)); - GroupData entity = new GroupData(groupData.getId()); - entity.setState(GroupState.ORDER_PENDING); - takeEntityByTemplateFromContainer(entity, takeOrderContainer, tx, RequestTimeout.DEFAULT, String.format("The order for group %d was already taken by an other waiter!", groupData.getId())); - - - log.info("Will now write taken order from group {} to space", groupData.getId()); + @Override + public void entryOperationFinished(final Notification notification, + final Operation operation, + final List entries) { + log.info("A new order has arrived!"); + + List groups = castEntries(entries); + if (groups.size() != 1) + throw new RuntimeException( + "Multiple orders in one notification?! That should not happen!"); + + GroupData groupData = groups.get(0); + + try { + TransactionReference tx = capi.createTransaction(1500, + URI.create(Util.SERVER_ADDR)); + GroupData entity = new GroupData(groupData.getId()); + entity.setState(GroupState.SITTING); + + // Acquire the lock so that another waiter can't do the same + // thing! + takeMatchingEntity( + entity, + takeOrderContainer, + tx, + RequestTimeout.DEFAULT, + String.format( + "The order for group %d was already taken by an other waiter!", + groupData.getId())); + + log.info( + "Will now write taken order from group {} to space", + groupData.getId()); groupData.setOrderWaiter(waiterId); groupData.setState(GroupState.ORDERED); Order order = groupData.getOrder(); order.setStatus(OrderStatus.ORDERED); - - sendItemsToContainer(Arrays.asList(groupData), ordersContainer, RequestTimeout.ZERO, tx); - sendItemsToContainer(Arrays.asList(groupData), groupsContainer, RequestTimeout.ZERO, tx); - sendItemsToContainer(order.getOrderedPizzas(), preparePizzasContainer, RequestTimeout.ZERO, tx); + + sendItemsToContainer(Arrays.asList(groupData), + ordersContainer, RequestTimeout.ZERO, tx); + sendItemsToContainer(Arrays.asList(groupData), + groupsContainer, RequestTimeout.ZERO, tx); + sendItemsToContainer(order.getOrderedPizzas(), + preparePizzasContainer, RequestTimeout.ZERO, tx); capi.commitTransaction(tx); - - - log.info("Waiter has taken order from group {}", groupData.getId()); - } catch (MzsCoreException e) { - log.info("ERROR in listenForOrders"); - e.printStackTrace(); - } - } + + log.info("Waiter has taken order from group {}", + groupData.getId()); + } catch (MzsCoreException e) { + log.info("ERROR in listenForOrders"); + e.printStackTrace(); + } + } }; - - try { - notificationMgr.createNotification(takeOrderContainer, ordersListener, Operation.WRITE); + + try { + notificationMgr.createNotification(takeOrderContainer, + ordersListener, Operation.WRITE); log.info("Created takeOrderContainer notification for a waiter"); } catch (Exception e) { handleSpaceErrorAndTerminate(e); } } - + public void listenForPreparedPizzas() { - + /** + * A waiter gets informed when a new pizza is complete. He takes the + * orderId of the pizza and looks up the corresponding order from which + * he gets the number of necessary pizzas of the order. He then tries to + * fetch all pizzas with the corresponding orderId and compares the + * number of those pizzas with the number of necessary pizzas. If all + * pizzas of an order are complete he then delivers them! + */ + NotificationListener preparedPizzasListener = new NotificationListener() { + @Override + public void entryOperationFinished(final Notification notification, + final Operation operation, + final List entries) { + + List pizzas = castEntries(entries); + if (pizzas.size() != 1) + throw new RuntimeException( + "Multiple pizzas in one notification?! That should not happen! A cook can only prepare one at the same time!"); + + Pizza pizza = pizzas.get(0); + int orderId = pizza.getOrderId(); + + try { + TransactionReference tx = capi.createTransaction(1500, + URI.create(Util.SERVER_ADDR)); + + GroupData entity = new GroupData(); + entity.setState(null); + Order order = new Order(); + order.setId(orderId); + entity.setOrder(order); + + GroupData groupData = takeMatchingEntity(entity, + ordersContainer, tx, RequestTimeout.DEFAULT, + "Another waiter just checks if the order is complete"); + int groupId = groupData.getId(); + int numberOfPizzas = groupData.getOrder() + .getNumberOfPizzas(); + + Pizza pizzaTemplate = new Pizza(); + pizzaTemplate.setOrderId(orderId); + + List pizzasOfOrder = takeMatchingEntities( + pizzaTemplate, deliverPizzasContainer, tx, + RequestTimeout.DEFAULT, + "Cannot take the pizzas from the deliverPizzasContainer"); + + // for an unkown reason even pizzas not matching the orderid + // are returned. that's why we have to check again if the + // pizza really belongs to the order in question + Iterator it = pizzasOfOrder.iterator(); + while (it.hasNext()) { + Pizza nextPizza = it.next(); + if (nextPizza.getOrderId() != orderId) { + it.remove(); + } + } + + if (pizzasOfOrder.size() == numberOfPizzas) { + GroupData group = new GroupData(); + group.setServingWaiter(waiterId); + Order completeOrder = new Order(); + completeOrder.setId(orderId); + completeOrder.setGroupId(groupId); + group.setOrder(completeOrder); + sendItemsToContainer(Arrays.asList(group), + orderCompleteContainer, RequestTimeout.DEFAULT, + tx); + capi.commitTransaction(tx); + } else { + log.info("Not yet all pizzas prepared! Order with id " + + orderId + " has " + numberOfPizzas + + " pizzas, but only " + pizzasOfOrder.size() + + " pizzas are ready by now!"); + capi.rollbackTransaction(tx); + } + + } catch (MzsCoreException e) { + log.error("ERROR in listenForPreparedPizzas!"); + e.printStackTrace(); + } + } + }; + + try { + notificationMgr.createNotification(deliverPizzasContainer, + preparedPizzasListener, Operation.WRITE); + log.info("Created deliverPizzasContainer notification for a waiter"); + } catch (Exception e) { + handleSpaceErrorAndTerminate(e); + } } private void assignGroupToTable(GroupData lockedGroup, @@ -208,25 +412,26 @@ public class WaiterXVSM extends AbstractXVSMConnector { // The new group sits down at the table lockedFreeTable.setGroupId(lockedGroup.getId()); - // The new group now wants to order - lockedGroup.setState(GroupState.ORDER_PENDING); + lockedGroup.setState(GroupState.SITTING); lockedGroup.setTable(lockedFreeTable); lockedGroup.setTableWaiter(waiterId); - - sendItemsToContainer(Arrays.asList(lockedFreeTable), tablesContainer, RequestTimeout.ZERO, tx); - sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer, RequestTimeout.ZERO, tx); - sendItemsToContainer(Arrays.asList(lockedGroup), groupsContainer, RequestTimeout.ZERO, tx); - + + sendItemsToContainer(Arrays.asList(lockedFreeTable), tablesContainer, + RequestTimeout.ZERO, tx); + sendItemsToContainer(Arrays.asList(lockedGroup), takeOrderContainer, + RequestTimeout.ZERO, tx); + sendItemsToContainer(Arrays.asList(lockedGroup), groupsContainer, + RequestTimeout.ZERO, tx); + try { capi.commitTransaction(tx); - log.info("Assigned table to group with groupId {}", lockedGroup.getId()); + log.info("Assigned table to group with groupId {}", + lockedGroup.getId()); } catch (Exception e) { - log.info("Assigning a table to group with groupId {} failed", lockedGroup.getId()); + log.info("Assigning a table to group with groupId {} failed", + lockedGroup.getId()); } - } - - } diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/XVSMConnector.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/XVSMConnector.java deleted file mode 100644 index 2214022..0000000 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/XVSMConnector.java +++ /dev/null @@ -1,151 +0,0 @@ -package at.ac.tuwien.sbc.valesriegler.xvsm; - -import java.io.Serializable; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.bouncycastle.crypto.RuntimeCryptoException; -import org.mozartspaces.capi3.AnyCoordinator.AnySelector; -import org.mozartspaces.capi3.CountNotMetException; -import org.mozartspaces.capi3.FifoCoordinator; -import org.mozartspaces.capi3.LindaCoordinator; -import org.mozartspaces.capi3.LindaCoordinator.LindaSelector; -import org.mozartspaces.core.Entry; -import org.mozartspaces.core.MzsConstants.RequestTimeout; -import org.mozartspaces.core.MzsCoreException; -import org.mozartspaces.core.TransactionReference; -import org.mozartspaces.notifications.Notification; -import org.mozartspaces.notifications.NotificationListener; -import org.mozartspaces.notifications.Operation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import at.ac.tuwien.sbc.valesriegler.common.Util; -import at.ac.tuwien.sbc.valesriegler.types.GroupData; -import at.ac.tuwien.sbc.valesriegler.types.GroupState; -import at.ac.tuwien.sbc.valesriegler.types.Order; -import at.ac.tuwien.sbc.valesriegler.types.Table; - -/** - * Responsible for XVSM Communication - * - * @author Gregor Riegler - * - */ -public class XVSMConnector extends AbstractXVSMConnector { - static final Logger log = LoggerFactory.getLogger(XVSMConnector.class); - - @Deprecated - public void handleWaitingGroup(int id) { - - try { - TransactionReference tx = capi.createTransaction(RequestTimeout.INFINITE, URI.create(Util.SERVER_ADDR)); - Table table = null; - try { - ArrayList
tables = capi.take(tablesContainer, FifoCoordinator.newSelector(), RequestTimeout.ZERO, tx); - table = tables.get(0); - } catch (Exception e) { - log.info("There is no free table"); - capi.rollbackTransaction(tx); - return; - } - - GroupData groupData = new GroupData(null); - groupData.setState(GroupState.WAITING); - LindaSelector sel = LindaCoordinator.newSelector(groupData, 1); - ArrayList waitingGroups = null; - - try { - waitingGroups = capi.take(groupsContainer, sel, RequestTimeout.ZERO, tx); - } catch (Exception e) { - log.info("There is no waiting group"); - capi.rollbackTransaction(tx); - return; - } - - GroupData group = waitingGroups.get(0); - group.setTable(new Table(table.getGroupId())); - group.setTableWaiter(id); - group.setState(GroupState.SITTING); - - try { - capi.write(groupsContainer, RequestTimeout.TRY_ONCE, tx, new Entry(group)); - } catch (Exception e) { - e.printStackTrace(); - capi.rollbackTransaction(tx); - return; - } - - try { - capi.write(new Entry(table), tablesContainer, RequestTimeout.TRY_ONCE, tx); - } catch (Exception e) { - e.printStackTrace(); - capi.rollbackTransaction(tx); - return; - } - - capi.commitTransaction(tx); - } catch (MzsCoreException e) { - e.printStackTrace(); - } - } - - @Deprecated - public void handleOrderRequest(int id) { - try { - TransactionReference tx = capi.createTransaction(RequestTimeout.INFINITE, URI.create(Util.SERVER_ADDR)); - - GroupData groupData = new GroupData(null); - groupData.setState(GroupState.SITTING); - LindaSelector sel = LindaCoordinator.newSelector(groupData, 1); - ArrayList sittingGroups = null; - - try { - sittingGroups = capi.take(groupsContainer, sel, RequestTimeout.ZERO, tx); - } catch (Exception e) { - log.info("There is no sitting group"); - capi.rollbackTransaction(tx); - return; - } - GroupData sittingGroup = sittingGroups.get(0); - Order order = sittingGroup.getOrder(); - sittingGroup.setOrderWaiter(id); - sittingGroup.setState(GroupState.ORDERED); - - try { - capi.write(new Entry(sittingGroup), groupsContainer, RequestTimeout.TRY_ONCE, tx); - } catch (Exception e) { - e.printStackTrace(); - capi.rollbackTransaction(tx); - return; - } - - capi.commitTransaction(tx); - - } catch (MzsCoreException e) { - e.printStackTrace(); - } - } - - public void initTablesNotifications(NotificationListener listener) { - try { - notificationMgr.createNotification(tablesContainer, listener, Operation.WRITE); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } - } - - public void initGroupNotifications(NotificationListener listener) { - try { - notificationMgr.createNotification(groupsContainer, listener, Operation.WRITE); - } catch (Exception e) { - handleSpaceErrorAndTerminate(e); - } - } - - - -} diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/cook/Cook.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/cook/Cook.java index 79e7d26..9347184 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/cook/Cook.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/cook/Cook.java @@ -3,9 +3,7 @@ package at.ac.tuwien.sbc.valesriegler.xvsm.cook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.sbc.valesriegler.xvsm.AbstractXVSMConnector; import at.ac.tuwien.sbc.valesriegler.xvsm.CookXVSM; -import at.ac.tuwien.sbc.valesriegler.xvsm.XVSMConnector; public class Cook { private static final String USAGE = "Cook needs exactly one parameter: ID of type Integer"; diff --git a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/waiter/Waiter.java b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/waiter/Waiter.java index 7029664..77ca842 100644 --- a/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/waiter/Waiter.java +++ b/src/main/java/at/ac/tuwien/sbc/valesriegler/xvsm/waiter/Waiter.java @@ -1,23 +1,11 @@ package at.ac.tuwien.sbc.valesriegler.xvsm.waiter; import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import javax.swing.SwingUtilities; - -import org.mozartspaces.core.Entry; -import org.mozartspaces.notifications.Notification; -import org.mozartspaces.notifications.NotificationListener; -import org.mozartspaces.notifications.Operation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.ac.tuwien.sbc.valesriegler.pizzeria.PizzeriaAgent; -import at.ac.tuwien.sbc.valesriegler.types.GroupData; -import at.ac.tuwien.sbc.valesriegler.types.Table; import at.ac.tuwien.sbc.valesriegler.xvsm.WaiterXVSM; -import at.ac.tuwien.sbc.valesriegler.xvsm.XVSMConnector; /** * This is a waiter using XVSM @@ -54,6 +42,10 @@ public class Waiter implements Serializable { xvsm.listenForOrders(); + xvsm.listenForPaymentRequest(); + + xvsm.listenForPreparedPizzas(); + // when new guests arrive the waiter should try to assign a table to them xvsm.listenForNewGuests(); @@ -61,6 +53,10 @@ public class Waiter implements Serializable { xvsm.listenForFreeTable(); + + + + } -- 2.43.0