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 1/2] 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 2/2] 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(); }