From b9c5f9204562b67f5f173cbf2d65134cef347cf8 Mon Sep 17 00:00:00 2001 From: Nikita Iryupin Date: Sun, 27 Dec 2020 19:03:45 +0100 Subject: [PATCH 1/8] Added EAR diagram (Product State Machine) --- EAR diagrams/FoodChain.eap | Bin 1771520 -> 1787904 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EAR diagrams/FoodChain.eap b/EAR diagrams/FoodChain.eap index 88db85c1a6cb5b8c36f71b66fc002c04275f7d5d..961ec32ca4a9a79f366252f33c87623db7d09c66 100644 GIT binary patch delta 18022 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 From 1771fc0fdb8f2d0b10f2c857113fb91c8f134bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Musil?= Date: Sun, 27 Dec 2020 19:06:57 +0100 Subject: [PATCH 2/8] Added new ProductState and improved product state machine --- .../cz/cvut/fel/sit/omo/foodchain/product/Product.java | 9 +++++++-- .../cvut/fel/sit/omo/foodchain/product/ProductState.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java index 6252afd..9feee01 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java @@ -71,11 +71,16 @@ public class Product // "State machine methods" /** - * Set current product state to AVAILABLE + * Set current product state to AVAILABLE. Throws IllegalStateException if the product is not IN_ACTION, READY_FOR_RECEPTION or IN_REQUIREMENT. */ public void setStateToAvailable() { - this.productState = ProductState.AVAILABLE; + if (this.productState.equals(ProductState.IN_ACTION) || + this.productState.equals(ProductState.READY_FOR_RECEPTION) || + this.productState.equals(ProductState.IN_REQUIREMENT)) + this.productState = ProductState.AVAILABLE; + else + throw new IllegalStateException("Cannot set state AVAILABLE. Product is not IN_ACTION, READY_FOR_RECEPTION or IN_REQUIREMENT"); } /** diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductState.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductState.java index 906282e..7e4be38 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductState.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductState.java @@ -2,5 +2,5 @@ package cz.cvut.fel.sit.omo.foodchain.product; public enum ProductState { - AVAILABLE, READY_FOR_DISPATCH, IN_TRANSIT, READY_FOR_RECEPTION, IN_ACTION + AVAILABLE, READY_FOR_DISPATCH, IN_TRANSIT, READY_FOR_RECEPTION, IN_ACTION, IN_REQUIREMENT } From 4fba75b0e11a2e8b93d964f9f87295eb97a13567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Musil?= Date: Sun, 27 Dec 2020 19:11:07 +0100 Subject: [PATCH 3/8] Added setStateToInRequirement that I forgot earlier --- .../fel/sit/omo/foodchain/product/Product.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java index 9feee01..b556cb1 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/Product.java @@ -84,14 +84,14 @@ public class Product } /** - * Set current product state to READY_FOR_DISPATCH. Throws IllegalStateException if the product is not AVAILABLE. + * Set current product state to READY_FOR_DISPATCH. Throws IllegalStateException if the product is not IN_REQUIREMENT. */ public void setStateToReadyForDispatch() { - if(this.productState.equals(ProductState.AVAILABLE)) + if(this.productState.equals(ProductState.IN_REQUIREMENT)) this.productState = ProductState.READY_FOR_DISPATCH; else - throw new IllegalStateException("Cannot set state READY_FOR_DISPATCH. Product is not AVAILABLE!"); + throw new IllegalStateException("Cannot set state READY_FOR_DISPATCH. Product is not IN_REQUIREMENT!"); } /** @@ -127,6 +127,17 @@ public class Product throw new IllegalStateException("Cannot set state IN_ACTION. Product is not AVAILABLE!"); } + /** + * Set current product state to IN_REQUIREMENT. Throws IllegalStateException if the product is not AVAILABLE. + */ + public void setStateToInRequirement() + { + if(this.productState.equals(ProductState.AVAILABLE)) + this.productState = ProductState.IN_REQUIREMENT; + else + throw new IllegalStateException("Cannot set state IN_REQUIREMENT. Product is not AVAILABLE!"); + } + /* public void setProductState(ProductState productState) { From 1bea53d11b1fe57aa786d542efd1fee0dff6083f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Musil?= Date: Sun, 27 Dec 2020 20:42:02 +0100 Subject: [PATCH 4/8] Added refusedRequirements --- .../omo/foodchain/channel/ChannelBase.java | 3 ++ .../sit/omo/foodchain/node/base/NodeBase.java | 41 +++++++++++++++---- .../operation/ProductTransaction.java | 2 +- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java index 46d8095..54fad99 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java @@ -55,6 +55,9 @@ public abstract class ChannelBase implements Observable { public boolean tick() { requirements.forEach(Requirement::tick); + try { + requirements.stream().filter(r -> r.getTTL() == 0).forEach(re -> re.getCreator().getProductFromStorage(re.getProductName(), re.getProductType()).setStateToAvailable()); + } catch (Exception ignored) {} requirements = requirements.stream().filter(r -> r.getTTL() > 0).collect(Collectors.toCollection(LinkedList::new)); notifyAllObservers(); return requirements.size() != 0; diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java index 08f340c..8db8843 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java @@ -15,16 +15,14 @@ import org.javamoney.moneta.Money; import javax.money.MonetaryAmount; import javax.naming.InsufficientResourcesException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; public class NodeBase implements ChannelObserver { private final Map subscribedChannels; private final List products; private final List refusedTransactions; + private final List refusedRequirements; private MonetaryAmount money; @@ -37,6 +35,7 @@ public class NodeBase implements ChannelObserver { this.subscribedChannels = new HashMap<>(); this.products = new LinkedList<>(); this.refusedTransactions = new LinkedList<>(); + this.refusedRequirements = new LinkedList<>(); this.money = Money.of(0, "USD"); } @@ -44,6 +43,7 @@ public class NodeBase implements ChannelObserver { this.subscribedChannels = new HashMap<>(); this.products = new LinkedList<>(); this.refusedTransactions = new LinkedList<>(); + this.refusedRequirements = new LinkedList<>(); this.money = Money.of(m, "USD"); } @@ -55,7 +55,7 @@ public class NodeBase implements ChannelObserver { .filter(ch -> ch.getProductType().equals(product.getProductType())) .findAny().ifPresent(channel -> channel.addTransaction(transaction)); } catch (InsufficientResourcesException e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } } @@ -67,7 +67,7 @@ public class NodeBase implements ChannelObserver { .filter(ch -> ch.getProductType().equals(prevTransaction.getProduct().getProductType())) .findAny().ifPresent(channel -> channel.addTransaction(transaction)); } catch (InsufficientResourcesException e) { - e.printStackTrace(); + System.err.println(e.getMessage()); } } @@ -124,6 +124,16 @@ public class NodeBase implements ChannelObserver { price = getProductFromStorage(pName, pType).getPrice(); } catch (NullPointerException e) { + refusedRequirements.add(new RefusedRequirement(tType, pType, pName, price)); + throw new InsufficientResourcesException("product unavailable"); + } + } + if (tType == TransactionType.SALE) { + try { + getProductFromStorage(pName, pType).setStateToInRequirement(); + } + catch (NullPointerException | IllegalStateException e) { + refusedRequirements.add(new RefusedRequirement(tType, pType, pName, price)); throw new InsufficientResourcesException("product unavailable"); } } @@ -239,9 +249,10 @@ public class NodeBase implements ChannelObserver { } boolean requirementCheck(Requirement req) { + Product product = getProductFromStorage(req.getProductName(), req.getProductType()); return (req.getTransactionType() == TransactionType.SALE && money.isGreaterThanOrEqualTo(req.getPrice())) || - (req.getTransactionType() == TransactionType.PURCHASE && getProductFromStorage(req.getProductName(), req.getProductType()) != null && - getProductFromStorage(req.getProductName(), req.getProductType()).getProductState() == ProductState.AVAILABLE); + (req.getTransactionType() == TransactionType.PURCHASE && product != null && + ((product.getProductState() == ProductState.AVAILABLE) || product.getProductState() == ProductState.IN_REQUIREMENT)); } @Override @@ -261,3 +272,17 @@ public class NodeBase implements ChannelObserver { //System.out.println(this.getClass().getSimpleName() + ": " + money.getNumber()); } } + +class RefusedRequirement { + public final TransactionType tType; + public final ProductType pType; + public final String pName; + public final MonetaryAmount price; + + public RefusedRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) { + this.tType = tType; + this.pType = pType; + this.pName = pName; + this.price = price; + } +} diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java index 640ca63..68c5b69 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java @@ -17,7 +17,7 @@ public class ProductTransaction extends Transaction { this.product = product; type = null; lastOperation = product.getCurrentOperation(); - if (product == null || product.getProductState() != ProductState.AVAILABLE) throw new InsufficientResourcesException("product not available"); + if (product == null || product.getProductState() != ProductState.IN_REQUIREMENT) throw new InsufficientResourcesException("product unavailable"); product.setCurrentOperation(this); product.setStateToReadyForDispatch(); creator.getStorage().remove(product); From 63a4697a643a0386a56d1c982b2b2339cb626298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Musil?= Date: Mon, 28 Dec 2020 16:54:34 +0100 Subject: [PATCH 5/8] Changed NodeBase structure a bit --- .../sit/omo/foodchain/node/base/NodeBase.java | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java index 8db8843..7b8988f 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java @@ -19,10 +19,10 @@ import java.util.*; public class NodeBase implements ChannelObserver { - private final Map subscribedChannels; - private final List products; - private final List refusedTransactions; - private final List refusedRequirements; + private final Map subscribedChannels = new HashMap<>(); + private final List products = new LinkedList<>(); + private final List refusedTransactions = new LinkedList<>(); + private final List refusedRequirements = new LinkedList<>(); private MonetaryAmount money; @@ -32,18 +32,11 @@ public class NodeBase implements ChannelObserver { public NodeBase() { this.nodeType = NodeType.None; - this.subscribedChannels = new HashMap<>(); - this.products = new LinkedList<>(); - this.refusedTransactions = new LinkedList<>(); - this.refusedRequirements = new LinkedList<>(); this.money = Money.of(0, "USD"); } public NodeBase(double m) { - this.subscribedChannels = new HashMap<>(); - this.products = new LinkedList<>(); - this.refusedTransactions = new LinkedList<>(); - this.refusedRequirements = new LinkedList<>(); + this.nodeType = NodeType.None; this.money = Money.of(m, "USD"); } @@ -271,18 +264,18 @@ public class NodeBase implements ChannelObserver { receiveTransactions(); //System.out.println(this.getClass().getSimpleName() + ": " + money.getNumber()); } -} -class RefusedRequirement { - public final TransactionType tType; - public final ProductType pType; - public final String pName; - public final MonetaryAmount price; + private static class RefusedRequirement { + public final TransactionType tType; + public final ProductType pType; + public final String pName; + public final MonetaryAmount price; - public RefusedRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) { - this.tType = tType; - this.pType = pType; - this.pName = pName; - this.price = price; + public RefusedRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) { + this.tType = tType; + this.pType = pType; + this.pName = pName; + this.price = price; + } } } From ad71021bd5d90c85c17c9b4c8fa0adc5e98bdbc3 Mon Sep 17 00:00:00 2001 From: Daniel Poustka Date: Mon, 28 Dec 2020 18:49:58 +0100 Subject: [PATCH 6/8] Separated products into Storage entity (for each Node). Added some JavaDoc --- .../omo/foodchain/channel/ChannelBase.java | 2 +- .../fel/sit/omo/foodchain/node/Customer.java | 6 +- .../fel/sit/omo/foodchain/node/Farmer.java | 4 +- .../fel/sit/omo/foodchain/node/Storage.java | 113 ++++++++++++++++++ .../sit/omo/foodchain/node/base/NodeBase.java | 49 +++----- .../operation/ProductTransaction.java | 4 +- 6 files changed, 139 insertions(+), 39 deletions(-) create mode 100644 src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java index 54fad99..2d9f061 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java @@ -56,7 +56,7 @@ public abstract class ChannelBase implements Observable { public boolean tick() { requirements.forEach(Requirement::tick); try { - requirements.stream().filter(r -> r.getTTL() == 0).forEach(re -> re.getCreator().getProductFromStorage(re.getProductName(), re.getProductType()).setStateToAvailable()); + requirements.stream().filter(r -> r.getTTL() == 0).forEach(re -> re.getCreator().getStorage().getProduct(re.getProductName(), re.getProductType()).setStateToAvailable()); } catch (Exception ignored) {} requirements = requirements.stream().filter(r -> r.getTTL() > 0).collect(Collectors.toCollection(LinkedList::new)); notifyAllObservers(); diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Customer.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Customer.java index d94670a..64af596 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Customer.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Customer.java @@ -11,11 +11,11 @@ public class Customer extends BuyerNodeBase { super(startMoney); allowedSeller = NodeType.Distributor; allowedPurchaser = NodeType.None; - this.nodeType = NodeType.Customer; + nodeType = NodeType.Customer; } public void consumeProduct() { - int i = new Random().nextInt(getStorage().size()); - getStorage().remove(i); + int i = new Random().nextInt(getStorage().getNumberOfStoredProducts()); + getStorage().getProducts().remove(i); } } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Farmer.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Farmer.java index 76bf758..406a7d3 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Farmer.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Farmer.java @@ -13,11 +13,11 @@ public class Farmer extends SellerNodeBase { super(startMoney); allowedSeller = NodeType.None; allowedPurchaser = NodeType.Processor; - this.nodeType = NodeType.Farmer; + nodeType = NodeType.Farmer; } public void generateProduct(Product product) { - storeProduct(product); + this.storage.storeProduct(product); try { createRequirement(TransactionType.SALE, product.getProductType(), product.getName(), product.getPrice()); } catch (InsufficientResourcesException e) { diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java new file mode 100644 index 0000000..d8b2aed --- /dev/null +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java @@ -0,0 +1,113 @@ +package cz.cvut.fel.sit.omo.foodchain.node; + +import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; +import cz.cvut.fel.sit.omo.foodchain.operation.Action; +import cz.cvut.fel.sit.omo.foodchain.operation.ProductOperationType; +import cz.cvut.fel.sit.omo.foodchain.product.Product; +import cz.cvut.fel.sit.omo.foodchain.product.ProductType; + +import java.util.LinkedList; +import java.util.List; + +public class Storage +{ + private final NodeBase storageOwner; + private final List products = new LinkedList<>(); + + public Storage(NodeBase owner) + { + this.storageOwner = owner; + } + + /** + * Adds provided product into the storage + * @param product + */ + public void storeProduct(Product product) + { + this.products.add(product); + } + + /** + * Adds all of the provided products into the storage + * @param products + */ + public void storeProducts(List products) + { + this.products.addAll(products); + } + + /** + * Finds a product (first if there is multiple of them) based on its name and type + * @param name name of product to find + * @param type type of product to find + * @return product if found, null if product is not in storage + */ + public Product getProduct(String name, ProductType type) + { + return products.stream().filter(ch -> ch.getProductType() == type && ch.getName().equals(name)).findFirst().orElse(null); + } + + /** + * Returns List of all products in storage + * @return + */ + public List getProducts() + { + return products; + } + + /** + * Returns number of products in storage + * @return + */ + public int getNumberOfStoredProducts() + { + return this.products.size(); + } + + /** + * Checks whether storage contains provided product + * @param product product to check + * @return true if contains, false if not + */ + public boolean containsProduct(Product product) + { + return products.contains(product); + } + + /** + * Removes provided product from storage if storage contains this product. (Removes only first found) + * @param product product to remove + */ + public void removeProduct(Product product) + { + if (containsProduct(product)) + this.products.remove(product); + } + + /** + * Proceed specific type of action on provided product if its possible. + * @param action type of product operation to do + * @param product product to proceed + */ + public void doAction(ProductOperationType action, Product product) throws IllegalCallerException + { + if (action.getNode().equals(this.storageOwner.getNodeType())) + new Action(this.storageOwner, this.getProduct(product.getName(), product.getProductType()), action); + //new Action(this.storageOwner, product, action); //todo má se zpracovat produkt co přichází nebo na jeho základě najít tento produkt ve skladu a ten zpracovat??? + else + throw new IllegalCallerException("! IllegalCallerException in NodeBase. " + this.storageOwner.getNodeType().toString() + " cannot do action available only for " + action.getNode()); + } + + /** + * Calls specific ProductOperation on each product in stock + * @param action ProductOperationType + */ + public void doAction(ProductOperationType action) + { + this.products.forEach(t -> new Action(this.storageOwner, t, action)); + } + + +} diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java index 7b8988f..3d71c5d 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java @@ -2,13 +2,13 @@ package cz.cvut.fel.sit.omo.foodchain.node.base; import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase; import cz.cvut.fel.sit.omo.foodchain.channel.ChannelSubscriptionType; +import cz.cvut.fel.sit.omo.foodchain.node.Storage; import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType; import cz.cvut.fel.sit.omo.foodchain.operation.*; import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.ProductState; import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement; -import cz.cvut.fel.sit.omo.foodchain.signature.Signature; import cz.cvut.fel.sit.omo.foodchain.signature.SignatureManager; import cz.cvut.fel.sit.omo.foodchain.util.ChannelObserver; import org.javamoney.moneta.Money; @@ -20,23 +20,25 @@ import java.util.*; public class NodeBase implements ChannelObserver { private final Map subscribedChannels = new HashMap<>(); - private final List products = new LinkedList<>(); private final List refusedTransactions = new LinkedList<>(); private final List refusedRequirements = new LinkedList<>(); private MonetaryAmount money; + protected final Storage storage; protected NodeType nodeType; protected NodeType allowedSeller; protected NodeType allowedPurchaser; public NodeBase() { this.nodeType = NodeType.None; + this.storage = new Storage(this); this.money = Money.of(0, "USD"); } public NodeBase(double m) { this.nodeType = NodeType.None; + this.storage = new Storage(this); this.money = Money.of(m, "USD"); } @@ -114,7 +116,7 @@ public class NodeBase implements ChannelObserver { public void createRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) throws InsufficientResourcesException { if (price == null) { try { - price = getProductFromStorage(pName, pType).getPrice(); + price = storage.getProduct(pName, pType).getPrice(); } catch (NullPointerException e) { refusedRequirements.add(new RefusedRequirement(tType, pType, pName, price)); @@ -123,7 +125,7 @@ public class NodeBase implements ChannelObserver { } if (tType == TransactionType.SALE) { try { - getProductFromStorage(pName, pType).setStateToInRequirement(); + storage.getProduct(pName, pType).setStateToInRequirement(); } catch (NullPointerException | IllegalStateException e) { refusedRequirements.add(new RefusedRequirement(tType, pType, pName, price)); @@ -142,9 +144,9 @@ public class NodeBase implements ChannelObserver { createRequirement(TransactionType.PURCHASE, req.getProductType(), req.getProductName(), req.getPrice()); } else { - if (req.getPrice().isGreaterThanOrEqualTo(getProductFromStorage(req.getProductName(), req.getProductType()).getPrice().multiply(0.9))) { - getProductFromStorage(req.getProductName(), req.getProductType()).setPrice(req.getPrice()); - sendTransaction(getProductFromStorage(req.getProductName(), req.getProductType()), req.getCreator()); + if (req.getPrice().isGreaterThanOrEqualTo(storage.getProduct(req.getProductName(), req.getProductType()).getPrice().multiply(0.9))) { + storage.getProduct(req.getProductName(), req.getProductType()).setPrice(req.getPrice()); + sendTransaction(storage.getProduct(req.getProductName(), req.getProductType()), req.getCreator()); } else createRequirement(TransactionType.SALE, req.getProductType(), req.getProductName(), req.getPrice()); } @@ -163,45 +165,30 @@ public class NodeBase implements ChannelObserver { /** - * Proceed specific type of action on provided product if its possible. + * Proceed specific type of action on provided product if its possible. (Propagated to its storage) * @param action type of product operation to do * @param product product to proceed */ public void doAction(ProductOperationType action, Product product) throws IllegalCallerException { - if(action.getNode().equals(this.nodeType)) - new Action(this, product, action); - else - throw new IllegalCallerException("! IllegalCallerException in NodeBase. " + this.nodeType.toString() + " cannot do action available only for "+action.getNode()); + this.storage.doAction(action,product); } - /** - * Calls specific ProductOperation on each product in stock + * Calls specific ProductOperation on each product in stock (Propagated to its storage) * @param action ProductOperationType */ public void doAction(ProductOperationType action) { - this.products.forEach(t -> new Action(this, t, action)); + this.storage.doAction(action); } - - public void storeProduct(Product product) { - this.products.add(product); + public Storage getStorage() { + return storage; } - - public void storeProducts(List products) { - this.products.addAll(products); - } - - - public Product getProductFromStorage(String name, ProductType type) { - return products.stream().filter(ch -> ch.getProductType() == type && ch.getName().equals(name)).findFirst().orElse(null); - } - - public List getStorage() { - return products; + public NodeType getNodeType() { + return nodeType; } public MonetaryAmount getMoney() { @@ -242,7 +229,7 @@ public class NodeBase implements ChannelObserver { } boolean requirementCheck(Requirement req) { - Product product = getProductFromStorage(req.getProductName(), req.getProductType()); + Product product = storage.getProduct(req.getProductName(), req.getProductType()); return (req.getTransactionType() == TransactionType.SALE && money.isGreaterThanOrEqualTo(req.getPrice())) || (req.getTransactionType() == TransactionType.PURCHASE && product != null && ((product.getProductState() == ProductState.AVAILABLE) || product.getProductState() == ProductState.IN_REQUIREMENT)); diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java index 68c5b69..b6aef92 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java @@ -20,14 +20,14 @@ public class ProductTransaction extends Transaction { if (product == null || product.getProductState() != ProductState.IN_REQUIREMENT) throw new InsufficientResourcesException("product unavailable"); product.setCurrentOperation(this); product.setStateToReadyForDispatch(); - creator.getStorage().remove(product); + creator.getStorage().removeProduct(product); System.out.println(toString()); } @Override public void endTransaction() { super.endTransaction(); - getNodeReceiver().storeProduct(product); + getNodeReceiver().getStorage().storeProduct(product); product.setStateToAvailable(); } From d0457670278b13eb87e11178a8664cb20bc7074b Mon Sep 17 00:00:00 2001 From: Daniel Poustka Date: Sun, 3 Jan 2021 11:08:23 +0100 Subject: [PATCH 7/8] Added containsProduct in Storage. --- .../cvut/fel/sit/omo/foodchain/node/Storage.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java index d8b2aed..248f63b 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java @@ -76,6 +76,17 @@ public class Storage return products.contains(product); } + /** + * Checks whether storage contains provided product + * @param name name of product to check + * @param type type of product to check + * @return true if contains, false if not + */ + public boolean containsProduct(String name, ProductType type) + { + return this.getProduct(name,type) != null; + } + /** * Removes provided product from storage if storage contains this product. (Removes only first found) * @param product product to remove @@ -94,8 +105,7 @@ public class Storage public void doAction(ProductOperationType action, Product product) throws IllegalCallerException { if (action.getNode().equals(this.storageOwner.getNodeType())) - new Action(this.storageOwner, this.getProduct(product.getName(), product.getProductType()), action); - //new Action(this.storageOwner, product, action); //todo má se zpracovat produkt co přichází nebo na jeho základě najít tento produkt ve skladu a ten zpracovat??? + new Action(this.storageOwner, product, action); else throw new IllegalCallerException("! IllegalCallerException in NodeBase. " + this.storageOwner.getNodeType().toString() + " cannot do action available only for " + action.getNode()); } From 3d19e5591216644f0bf8b93940762f11f2936b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Musil?= Date: Sun, 3 Jan 2021 11:27:52 +0100 Subject: [PATCH 8/8] Added product type to actions --- conf/scenarios.xml | 1 + .../cvut/fel/sit/omo/foodchain/FoodChain.java | 2 -- .../fel/sit/omo/foodchain/node/Storage.java | 5 ++- .../operation/ProductOperationType.java | 36 ++++++++++--------- .../omo/foodchain/product/ProductType.java | 2 +- .../omo/foodchain/scenario/DoActionStep.java | 1 - .../sit/omo/foodchain/scenario/Scenario.java | 1 - 7 files changed, 25 insertions(+), 23 deletions(-) diff --git a/conf/scenarios.xml b/conf/scenarios.xml index d08dd00..5849fe1 100644 --- a/conf/scenarios.xml +++ b/conf/scenarios.xml @@ -10,6 +10,7 @@ generate consume doaction +doaction sell buy pass diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/FoodChain.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/FoodChain.java index d5e7717..9ef485e 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/FoodChain.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/FoodChain.java @@ -41,8 +41,6 @@ public class FoodChain return factoryManager; } - // todo maybe some refactoring needed? - // add other entities public static void parseChannels() { try diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java index 248f63b..a754ce7 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/Storage.java @@ -105,7 +105,10 @@ public class Storage public void doAction(ProductOperationType action, Product product) throws IllegalCallerException { if (action.getNode().equals(this.storageOwner.getNodeType())) - new Action(this.storageOwner, product, action); + if (action.getProduct().equals(product.getProductType()) || action.getProduct().equals(ProductType.ALL)) + new Action(this.storageOwner, product, action); + else + throw new IllegalCallerException("! IllegalCallerException in NodeBase. " + product.getProductType().toString() + " cannot be processed by action " + action.name() + " only for " + action.getProduct()); else throw new IllegalCallerException("! IllegalCallerException in NodeBase. " + this.storageOwner.getNodeType().toString() + " cannot do action available only for " + action.getNode()); } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductOperationType.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductOperationType.java index 594be25..4f8943f 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductOperationType.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductOperationType.java @@ -1,36 +1,36 @@ package cz.cvut.fel.sit.omo.foodchain.operation; import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType; +import cz.cvut.fel.sit.omo.foodchain.product.ProductType; public enum ProductOperationType { - STORE_MEAT(NodeType.All, 20, -8), - STORE_FRUIT(NodeType.All, 8, 2), - STORE_VEGETABLE(NodeType.All, 10, 2), - STORE_OTHER(NodeType.All, 30, 21), + STORE_MEAT(NodeType.All, ProductType.MEAT, 20, -8), + STORE_FRUIT(NodeType.All, ProductType.FRUIT, 8, 2), + STORE_VEGETABLE(NodeType.All, ProductType.VEGETABLE, 10, 2), + STORE_OTHER(NodeType.All, ProductType.OTHER, 30, 21), - WRAP_INTO_GIFT_PACKAGE(NodeType.Seller, 1, -8), - UNWRAP(NodeType.All, 1, 21), - CUT_TO_PIECES(NodeType.All, 1, 21), + WRAP_INTO_GIFT_PACKAGE(NodeType.Seller, ProductType.ALL, 1, -8), + UNWRAP(NodeType.All, ProductType.ALL, 1, 21), + CUT_TO_PIECES(NodeType.All, ProductType.ALL, 1, 21), - BOIL_MEAT(NodeType.All, 1, 21), - GRILL_MEAT(NodeType.All, 1, 21), - SMOKE_MEAT(NodeType.All, 1, 21), - DRY_MEAT(NodeType.All, 1, 21), + BOIL_MEAT(NodeType.All, ProductType.MEAT, 1, 21), + GRILL_MEAT(NodeType.All, ProductType.MEAT, 1, 21), + SMOKE_MEAT(NodeType.All, ProductType.MEAT, 1, 21), + DRY_MEAT(NodeType.All, ProductType.MEAT, 1, 21), - DRY_FRUIT(NodeType.All, 1, 21), - FREEZE_DRY_FRUIT(NodeType.All, 1, 21); - - - //todo add product type allowed for this action + DRY_FRUIT(NodeType.All, ProductType.FRUIT, 1, 21), + FREEZE_DRY_FRUIT(NodeType.All, ProductType.FRUIT, 1, 21); private final NodeType node; + private final ProductType product; private final int duration; private final int temperature; - ProductOperationType(NodeType node, int duration, int temperature) + ProductOperationType(NodeType node, ProductType product, int duration, int temperature) { this.node = node; + this.product = product; this.duration = duration; this.temperature = temperature; } @@ -49,4 +49,6 @@ public enum ProductOperationType { return node; } + + public ProductType getProduct() { return product; } } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductType.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductType.java index 533c3c3..683936c 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductType.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/product/ProductType.java @@ -2,5 +2,5 @@ package cz.cvut.fel.sit.omo.foodchain.product; public enum ProductType { - MEAT, FRUIT, VEGETABLE, OTHER; + MEAT, FRUIT, VEGETABLE, OTHER, ALL // ALL is used only for actions } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/DoActionStep.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/DoActionStep.java index f934978..97fef11 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/DoActionStep.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/DoActionStep.java @@ -22,7 +22,6 @@ public class DoActionStep extends ScenarioStep { @Override void execute() { - //todo maybe do a better error handling try { if (product != null) { nodeBase.doAction(productOperationType, product); diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/Scenario.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/Scenario.java index c7e3063..96bc592 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/Scenario.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/Scenario.java @@ -8,7 +8,6 @@ public class Scenario { Iterator stepIterator; public Scenario() { - //steps = //TODO init stepIterator = steps.listIterator(0); }