Merge branch 'develop' into feature/text_report_impl

# Conflicts:
#	src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java
#	src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/OperationBase.java
This commit is contained in:
Nikita Iryupin 2021-01-04 13:22:06 +01:00
commit 099dd81246
60 changed files with 525 additions and 117 deletions

View File

@ -9,12 +9,16 @@ import cz.cvut.fel.sit.omo.foodchain.parser.ParserResultElement;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
import cz.cvut.fel.sit.omo.foodchain.reporting.ReportingManager; import cz.cvut.fel.sit.omo.foodchain.reporting.ReportingManager;
import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario; import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario;
import cz.cvut.fel.sit.omo.foodchain.util.ReportLogger;
import cz.cvut.fel.sit.omo.foodchain.util.Ticker; import cz.cvut.fel.sit.omo.foodchain.util.Ticker;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class FoodChain public class FoodChain
{ {
@ -23,12 +27,19 @@ public class FoodChain
public static void main(String[] args) public static void main(String[] args)
{ {
LogManager.getLogManager().reset();
Logger rootLogger = LogManager.getLogManager().getLogger("");
rootLogger.addHandler(new ReportLogger());
if(args.length < 4) if(args.length < 4)
{ {
parseChannels("conf/channels.xml"); parseChannels("conf/channels.xml");
parseNodes("conf/nodes.xml"); parseNodes("conf/nodes.xml");
parseProducts("conf/products.xml"); parseProducts("conf/products.xml");
parseScenarios("conf/scenarios.xml"); parseScenarios("conf/scenarios.xml");
rootLogger.log(Level.CONFIG,"Parsed default scenarios");
} }
else else
{ {
@ -36,6 +47,8 @@ public class FoodChain
parseNodes(args[2]); parseNodes(args[2]);
parseProducts(args[3]); parseProducts(args[3]);
parseScenarios(args[4]); parseScenarios(args[4]);
rootLogger.log(Level.CONFIG,"Parsed non-default scenarios");
} }
// getFactoryManager().getPoolDatabaseInstance().getChannelPoolInstance().findAll().stream().forEach(ch -> System.out.println(ch.getProductType())); // getFactoryManager().getPoolDatabaseInstance().getChannelPoolInstance().findAll().stream().forEach(ch -> System.out.println(ch.getProductType()));
@ -68,6 +81,7 @@ public class FoodChain
catch (ParserConfigurationException | SAXException | IOException e) catch (ParserConfigurationException | SAXException | IOException e)
{ {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
} }
return ConfigurationParser.getElements(rootElementTag); return ConfigurationParser.getElements(rootElementTag);

View File

@ -12,6 +12,9 @@ import cz.cvut.fel.sit.omo.foodchain.util.Observable;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* Base class for all channels
*/
public abstract class ChannelBase implements Observable { public abstract class ChannelBase implements Observable {
protected ProductType productType; protected ProductType productType;
protected Queue<Requirement> requirements; protected Queue<Requirement> requirements;
@ -46,7 +49,7 @@ public abstract class ChannelBase implements Observable {
} }
/** /**
* Adds new requirement to the requirement Queue * Adds new requirement to the requirement Queue.
* @param requirement requirement * @param requirement requirement
*/ */
public void addRequirement(Requirement requirement) public void addRequirement(Requirement requirement)
@ -54,6 +57,10 @@ public abstract class ChannelBase implements Observable {
this.requirements.add(requirement); this.requirements.add(requirement);
} }
/**
* Passes tick onto every requirement in channel, if requirement has TTL= 0 deletes it, notifies all nodes with current requirements.
* @return if there are any requirements
*/
public boolean tick() { public boolean tick() {
requirements.forEach(Requirement::tick); requirements.forEach(Requirement::tick);
try { try {
@ -64,23 +71,32 @@ public abstract class ChannelBase implements Observable {
return requirements.size() != 0; return requirements.size() != 0;
} }
/**
* Notifies all nodes apart from creator about a requirement.
*/
@Override @Override
public void notifyAllObservers(){ public void notifyAllObservers(){
subscribers.forEach(subscriber -> new LinkedList<>(requirements).forEach(r -> subscriber.update(r, this))); subscribers.forEach(subscriber -> new LinkedList<>(requirements).forEach(r -> subscriber.update(r, this)));
} }
/**
* Adds observer to list of subscribed nodes.
* @param observer channelobserver
*/
@Override @Override
public void attach(ChannelObserver observer){ public void attach(ChannelObserver observer){
subscribers.add(observer); subscribers.add(observer);
} }
/**
* Removes observer from list of subscribed nodes.
* @param observer channelobserver
*/
@Override @Override
public void detach(ChannelObserver observer){ public void detach(ChannelObserver observer){ subscribers.remove(observer); }
subscribers.remove(observer);
}
/** /**
* Adds new transaction to the transaction Queue * Adds new transaction to the transaction Queue.
* @param transaction transaction * @param transaction transaction
*/ */
public void addTransaction(Transaction transaction) public void addTransaction(Transaction transaction)
@ -92,12 +108,20 @@ public abstract class ChannelBase implements Observable {
catch (Exception ignored) {} catch (Exception ignored) {}
} }
/**
* Removes requirement from list of active requirements.
* @param requirement requirement
*/
public void disposeOf(Requirement requirement) { this.requirements.remove(requirement); } public void disposeOf(Requirement requirement) { this.requirements.remove(requirement); }
/**
* Removes transaction from list of unprocessed transactions.
* @param transaction transaction
*/
public void disposeOf(Transaction transaction) { this.transactions.remove(transaction); } public void disposeOf(Transaction transaction) { this.transactions.remove(transaction); }
/** /**
* Clears all requirements from this channel * Clears all active requirements from this channel.
*/ */
public void clearRequirements() public void clearRequirements()
{ {

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.channel; package cz.cvut.fel.sit.omo.foodchain.channel;
/**
* Enum class for different subscription types
*/
public enum ChannelSubscriptionType { public enum ChannelSubscriptionType {
SALE, PURCHASE, SALE_AND_PURCHASE SALE, PURCHASE, SALE_AND_PURCHASE

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.channel;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Channel for transporting fruit
*/
public class FruitChannel extends ChannelBase public class FruitChannel extends ChannelBase
{ {
public FruitChannel() public FruitChannel()

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.channel;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Channel for transporting meat
*/
public class MeatChannel extends ChannelBase public class MeatChannel extends ChannelBase
{ {
public MeatChannel() public MeatChannel()

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.channel;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Channel for transporting other products
*/
public class OtherChannel extends ChannelBase public class OtherChannel extends ChannelBase
{ {
public OtherChannel() public OtherChannel()

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.channel;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Channel for transporting vegetable
*/
public class VegetableChannel extends ChannelBase public class VegetableChannel extends ChannelBase
{ {
public VegetableChannel() public VegetableChannel()

View File

@ -2,14 +2,22 @@ package cz.cvut.fel.sit.omo.foodchain.factory;
import cz.cvut.fel.sit.omo.foodchain.channel.*; import cz.cvut.fel.sit.omo.foodchain.channel.*;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.parser.ParserResultElement; import cz.cvut.fel.sit.omo.foodchain.parser.ParserResultElement;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Factory for creating channels
*/
public class ChannelFactory public class ChannelFactory
{ {
private static final Logger LOGGER = Logger.getLogger(ChannelFactory.class.getName());
/** /**
* Creates channel based on channel type (Fruit, Vegetable, Meat, Other) * Creates channel based on channel type (Fruit, Vegetable, Meat, Other).
* @param input data from channel is created * @param input data from channel that is created
* @return created Channel (FruitChannel, VegetableChannel, MeatChannel, OtherChannel) * @return created Channel (FruitChannel, VegetableChannel, MeatChannel, OtherChannel)
*/ */
public ChannelBase makeChannel(ParserResultElement input) public ChannelBase makeChannel(ParserResultElement input)
@ -23,15 +31,20 @@ public class ChannelFactory
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
System.err.println("! Wrong type of enum in ChannelFactory: " + e); LOGGER.log(Level.SEVERE, "! Wrong type of enum in ChannelFactory: " + e);
} }
catch (Exception e) catch (Exception e)
{ {
System.err.println("! Fatal error in ChannelFactory: " + e); LOGGER.log(Level.SEVERE, "! Fatal error in ChannelFactory: " + e);
} }
return c; return c;
} }
/**
* Creates channel based on channel type (Fruit, Vegetable, Meat, Other).
* @param typeOfChannel channel type to be created
* @return created Channel (FruitChannel, VegetableChannel, MeatChannel, OtherChannel)
*/
private ChannelBase makeChannelFromChannelType(ProductType typeOfChannel) private ChannelBase makeChannelFromChannelType(ProductType typeOfChannel)
{ {
switch (typeOfChannel) switch (typeOfChannel)

View File

@ -5,6 +5,9 @@ import cz.cvut.fel.sit.omo.foodchain.util.Singleton;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
/**
* Manager class for all factories and pool database
*/
public class FactoryManager public class FactoryManager
{ {
public NodeFactory getNodeFactoryInstance() public NodeFactory getNodeFactoryInstance()

View File

@ -10,13 +10,18 @@ import cz.cvut.fel.sit.omo.foodchain.pool.ChannelPool;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import java.util.Objects; import java.util.Objects;
import java.util.logging.Level;
public class NodeFactory import java.util.logging.Logger;
{
/** /**
* Creates Node based on input ParserResultElement * Factory for creating nodes
* @param input data from Node is created */
public class NodeFactory
{
private static final Logger LOGGER = Logger.getLogger(NodeFactory.class.getName());
/**
* Creates Node based on input ParserResultElement.
* @param input data from Node that is created
* @return created Node * @return created Node
*/ */
public NodeBase makeNode(ParserResultElement input) public NodeBase makeNode(ParserResultElement input)
@ -35,11 +40,11 @@ public class NodeFactory
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
System.err.println("! Wrong type of enum in NodeFactory: " + e.getMessage()); LOGGER.log(Level.SEVERE, "! Wrong type of enum in NodeFactory: " + e.getMessage());
} }
catch (Exception e) catch (Exception e)
{ {
System.err.println("! Fatal error in NodeFactory: " + e.getMessage()); LOGGER.log(Level.SEVERE, "! Fatal error in NodeFactory: " + e.getMessage());
} }
switch (Objects.requireNonNull(nodeType)) switch (Objects.requireNonNull(nodeType))

View File

@ -5,12 +5,20 @@ 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.ProductState;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Factory for creating products
*/
public class ProductFactory public class ProductFactory
{ {
private static final Logger LOGGER = Logger.getLogger(ProductFactory.class.getName());
/** /**
* Creates Product based on input ParserResultElement * Creates Product based on input ParserResultElement.
* @param input data from Product is created * @param input data from Product that is created
* @return created Product * @return created Product
*/ */
public Product makeProduct(ParserResultElement input) public Product makeProduct(ParserResultElement input)
@ -28,11 +36,11 @@ public class ProductFactory
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
System.err.println("! Wrong type of enum in ProductFactory: " + e); LOGGER.log(Level.SEVERE, "! Wrong type of enum in ProductFactory: " + e.getMessage());
} }
catch (Exception e) catch (Exception e)
{ {
System.err.println("! Fatal error in ProductFactory: " + e); LOGGER.log(Level.SEVERE, "! Fatal error in ProductFactory: " + e.getMessage());
} }
return p; return p;
} }

View File

@ -14,13 +14,18 @@ import cz.cvut.fel.sit.omo.foodchain.scenario.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
public class ScenarioFactory import java.util.logging.Logger;
{
/** /**
* Creates Scenario based on input ParserResultElement * Factory for creating scenarios
* @param input data from Scenario is created */
public class ScenarioFactory
{
private static final Logger LOGGER = Logger.getLogger(ScenarioFactory.class.getName());
/**
* Creates Scenario based on input ParserResultElement.
* @param input data from Scenario that is created
* @return created Scenario * @return created Scenario
*/ */
public Scenario makeScenario(ParserResultElement input) public Scenario makeScenario(ParserResultElement input)
@ -76,7 +81,7 @@ public class ScenarioFactory
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
System.err.println("! Wrong type of enum in ScenarioFactory: " + e); LOGGER.log(Level.SEVERE, "! Wrong type of enum in ScenarioFactory: " + e.getMessage());
} }
return s; return s;

View File

@ -5,6 +5,9 @@ import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType;
import java.util.Random; import java.util.Random;
/**
* Customer node
*/
public class Customer extends BuyerNodeBase { public class Customer extends BuyerNodeBase {
public Customer(double startMoney) { public Customer(double startMoney) {

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.node;
import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase;
import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType; import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType;
/**
* Distributor node
*/
public class Distributor extends RetailerNodeBase { public class Distributor extends RetailerNodeBase {
public Distributor(double startMoney) { public Distributor(double startMoney) {

View File

@ -6,7 +6,11 @@ import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.logging.Level;
/**
* Farmer node
*/
public class Farmer extends SellerNodeBase { public class Farmer extends SellerNodeBase {
public Farmer(double startMoney) { public Farmer(double startMoney) {
@ -21,7 +25,7 @@ public class Farmer extends SellerNodeBase {
try { try {
createRequirement(TransactionType.SALE, product.getProductType(), product.getName(), product.getPrice()); createRequirement(TransactionType.SALE, product.getProductType(), product.getName(), product.getPrice());
} catch (InsufficientResourcesException e) { } catch (InsufficientResourcesException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.WARNING, e.getMessage());
} }
} }
} }

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.node;
import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase;
import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType; import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType;
/**
* Processor node
*/
public class Processor extends RetailerNodeBase { public class Processor extends RetailerNodeBase {
public Processor(double startMoney) { public Processor(double startMoney) {

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.node;
import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.RetailerNodeBase;
import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType; import cz.cvut.fel.sit.omo.foodchain.node.enums.NodeType;
/**
* Seller node
*/
public class Seller extends RetailerNodeBase { public class Seller extends RetailerNodeBase {
public Seller(double startMoney) { public Seller(double startMoney) {

View File

@ -9,6 +9,9 @@ import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
/**
* Storage sub-node for storing products of other nodes
*/
public class Storage public class Storage
{ {
private final NodeBase storageOwner; private final NodeBase storageOwner;
@ -20,7 +23,7 @@ public class Storage
} }
/** /**
* Adds provided product into the storage * Adds provided product into the storage.
* @param product * @param product
*/ */
public void storeProduct(Product product) public void storeProduct(Product product)
@ -29,7 +32,7 @@ public class Storage
} }
/** /**
* Adds all of the provided products into the storage * Adds all of the provided products into the storage.
* @param products * @param products
*/ */
public void storeProducts(List<Product> products) public void storeProducts(List<Product> products)
@ -38,7 +41,7 @@ public class Storage
} }
/** /**
* Finds a product (first if there is multiple of them) based on its name and type * Finds a product (first if there is multiple of them) based on its name and type.
* @param name name of product to find * @param name name of product to find
* @param type type of product to find * @param type type of product to find
* @return product if found, null if product is not in storage * @return product if found, null if product is not in storage
@ -48,17 +51,13 @@ public class Storage
return products.stream().filter(ch -> ch.getProductType() == type && ch.getName().equals(name)).findFirst().orElse(null); 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<Product> getProducts() public List<Product> getProducts()
{ {
return products; return products;
} }
/** /**
* Returns number of products in storage * Returns number of products in storage.
* @return * @return
*/ */
public int getNumberOfStoredProducts() public int getNumberOfStoredProducts()
@ -67,7 +66,7 @@ public class Storage
} }
/** /**
* Checks whether storage contains provided product * Checks whether storage contains provided product.
* @param product product to check * @param product product to check
* @return true if contains, false if not * @return true if contains, false if not
*/ */
@ -77,7 +76,7 @@ public class Storage
} }
/** /**
* Checks whether storage contains provided product * Checks whether storage contains provided product.
* @param name name of product to check * @param name name of product to check
* @param type type of product to check * @param type type of product to check
* @return true if contains, false if not * @return true if contains, false if not
@ -88,7 +87,7 @@ public class Storage
} }
/** /**
* Removes provided product from storage if storage contains this product. (Removes only first found) * Removes provided product from storage if storage contains this product. (Removes only first found).
* @param product product to remove * @param product product to remove
*/ */
public void removeProduct(Product product) public void removeProduct(Product product)
@ -114,7 +113,7 @@ public class Storage
} }
/** /**
* Calls specific ProductOperation on each product in stock * Calls specific ProductOperation on each product in stock.
* @param action ProductOperationType * @param action ProductOperationType
*/ */
public void doAction(ProductOperationType action) public void doAction(ProductOperationType action)

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.node.base;
import cz.cvut.fel.sit.omo.foodchain.node.interfaces.IBuyerNode; import cz.cvut.fel.sit.omo.foodchain.node.interfaces.IBuyerNode;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Base class for all buyer nodes
*/
public class BuyerNodeBase extends NodeBase implements IBuyerNode { public class BuyerNodeBase extends NodeBase implements IBuyerNode {
public BuyerNodeBase(double m){ public BuyerNodeBase(double m){
super(m); super(m);

View File

@ -17,9 +17,16 @@ import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.*; import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Base class for all nodes
*/
public class NodeBase implements ChannelObserver { public class NodeBase implements ChannelObserver {
protected static final Logger LOGGER = Logger.getLogger(NodeBase.class.getName());
private final Map<ChannelBase, ChannelSubscriptionType> subscribedChannels = new HashMap<>(); private final Map<ChannelBase, ChannelSubscriptionType> subscribedChannels = new HashMap<>();
private final List<Transaction> refusedTransactions = new LinkedList<>(); private final List<Transaction> refusedTransactions = new LinkedList<>();
private final List<RefusedRequirement> refusedRequirements = new LinkedList<>(); private final List<RefusedRequirement> refusedRequirements = new LinkedList<>();
@ -44,6 +51,11 @@ public class NodeBase implements ChannelObserver {
} }
/**
* Sends product transaction to node through a channel based on its type.
* @param product product to be sent
* @param node receiver node
*/
public void sendTransaction(Product product, NodeBase node) { public void sendTransaction(Product product, NodeBase node) {
try { try {
Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product); Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product);
@ -51,11 +63,17 @@ public class NodeBase implements ChannelObserver {
.filter(ch -> ch.getProductType().equals(product.getProductType())) .filter(ch -> ch.getProductType().equals(product.getProductType()))
.findAny().ifPresent(channel -> channel.addTransaction(transaction)); .findAny().ifPresent(channel -> channel.addTransaction(transaction));
} catch (InsufficientResourcesException e) { } catch (InsufficientResourcesException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.WARNING, e.getMessage());
} }
} }
/**
* Sends financial transaction to node through a channel based on previous transaction type.
* @param amount amount to be sent
* @param node receiver node
* @param prevTransaction previous product transaction
*/
public void sendTransaction(MonetaryAmount amount, NodeBase node, ProductTransaction prevTransaction) { public void sendTransaction(MonetaryAmount amount, NodeBase node, ProductTransaction prevTransaction) {
try { try {
Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction); Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction);
@ -63,10 +81,14 @@ public class NodeBase implements ChannelObserver {
.filter(ch -> ch.getProductType().equals(prevTransaction.getProduct().getProductType())) .filter(ch -> ch.getProductType().equals(prevTransaction.getProduct().getProductType()))
.findAny().ifPresent(channel -> channel.addTransaction(transaction)); .findAny().ifPresent(channel -> channel.addTransaction(transaction));
} catch (InsufficientResourcesException e) { } catch (InsufficientResourcesException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.WARNING, e.getMessage());
} }
} }
/**
* Receives (processes) transaction.
* @param transaction transaction to be received
*/
public void receiveTransaction(Transaction transaction) { public void receiveTransaction(Transaction transaction) {
try { try {
receiveTransaction((ProductTransaction) transaction); receiveTransaction((ProductTransaction) transaction);
@ -76,11 +98,15 @@ public class NodeBase implements ChannelObserver {
receiveTransaction((FinancialTransaction) transaction); receiveTransaction((FinancialTransaction) transaction);
} }
catch (Exception ex) { catch (Exception ex) {
System.err.println(ex.getMessage()); LOGGER.log(Level.WARNING, e.getMessage());
} }
} }
} }
/**
* Receives (validates) product transaction and sends financial transaction as response.
* @param transaction transaction to be received
*/
public void receiveTransaction(ProductTransaction transaction) { public void receiveTransaction(ProductTransaction transaction) {
if (validateSignature(transaction)) { if (validateSignature(transaction)) {
transaction.getProduct().setStateToReadyForReception(); transaction.getProduct().setStateToReadyForReception();
@ -91,29 +117,40 @@ public class NodeBase implements ChannelObserver {
else refuseTransaction(transaction); else refuseTransaction(transaction);
} }
/**
* Receives (validates) financial transaction.
* @param transaction transaction to be received
*/
public void receiveTransaction(FinancialTransaction transaction) { public void receiveTransaction(FinancialTransaction transaction) {
if (validateSignature(transaction)) transaction.endTransaction(); if (validateSignature(transaction)) transaction.endTransaction();
else refuseTransaction(transaction); else refuseTransaction(transaction);
} }
/**
* Adds transaction to refused transactions.
* @param transaction
*/
public void refuseTransaction(Transaction transaction) { public void refuseTransaction(Transaction transaction) {
transaction.endTransaction(); transaction.endTransaction();
refusedTransactions.add(transaction); refusedTransactions.add(transaction);
} }
/**
* Receives all transactions for this node.
*/
public void receiveTransactions() { public void receiveTransactions() {
subscribedChannels.keySet().forEach(ch -> ch.getTransactions(this).forEach(t -> {receiveTransaction(t); ch.disposeOf(t);})); subscribedChannels.keySet().forEach(ch -> ch.getTransactions(this).forEach(t -> {receiveTransaction(t); ch.disposeOf(t);}));
} }
/**
public void createRequirement(TransactionType tType, ProductType pType, String pName, double price) { * Creates requirement based on data provided.
Requirement req = new Requirement(this, tType, pType, pName, price); * @param tType transaction type
subscribedChannels.keySet().stream() * @param pType product type
.filter(ch -> ch.getProductType().equals(pType)) * @param pName product name
.findAny().ifPresent(channel -> channel.addRequirement(req)); * @param price product price
} * @throws InsufficientResourcesException if product is unavailable
*/
public void createRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) throws InsufficientResourcesException { public void createRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) throws InsufficientResourcesException {
if (price == null) { if (price == null) {
try { try {
@ -139,8 +176,13 @@ public class NodeBase implements ChannelObserver {
.findAny().ifPresent(channel -> channel.addRequirement(req)); .findAny().ifPresent(channel -> channel.addRequirement(req));
} }
/**
* Accepts requirement and creates response.
* @param req requirement to be accepted
* @throws InsufficientResourcesException if product is unavailable
*/
public void acceptRequirement(Requirement req) throws InsufficientResourcesException { public void acceptRequirement(Requirement req) throws InsufficientResourcesException {
System.out.println(this.nodeType.toString() + " accepted " + req.toString()); LOGGER.log(Level.INFO, this.nodeType.toString() + " accepted " + req.toString());
if (req.getTransactionType() == TransactionType.SALE) { if (req.getTransactionType() == TransactionType.SALE) {
createRequirement(TransactionType.PURCHASE, req.getProductType(), req.getProductName(), req.getPrice()); createRequirement(TransactionType.PURCHASE, req.getProductType(), req.getProductName(), req.getPrice());
} }
@ -154,19 +196,28 @@ public class NodeBase implements ChannelObserver {
} }
/**
* Adds channel to subscribed channels with correct type.
* @param channel channel to be subscribed
* @param type type of subscription
*/
public void subscribeToChannel(ChannelBase channel, ChannelSubscriptionType type) { public void subscribeToChannel(ChannelBase channel, ChannelSubscriptionType type) {
subscribedChannels.put(channel, type); subscribedChannels.put(channel, type);
channel.attach(this); channel.attach(this);
} }
/**
* Removes channel from subscribed channels.
* @param channel
*/
public void unsubscribeFromChannel(ChannelBase channel) { public void unsubscribeFromChannel(ChannelBase channel) {
subscribedChannels.remove(channel); subscribedChannels.remove(channel);
} }
/** /**
* Proceed specific type of action on provided product if its possible. (Propagated to its storage) * Proceed specific type of action on provided product if its possible. (Propagated to its storage).
* @param action type of product operation to do * @param action type of product operation to do
* @param product product to proceed * @param product product to proceed
*/ */
@ -176,7 +227,7 @@ public class NodeBase implements ChannelObserver {
} }
/** /**
* Calls specific ProductOperation on each product in stock (Propagated to its storage) * Calls specific ProductOperation on each product in stock (Propagated to its storage).
* @param action ProductOperationType * @param action ProductOperationType
*/ */
public void doAction(ProductOperationType action) public void doAction(ProductOperationType action)
@ -196,6 +247,7 @@ public class NodeBase implements ChannelObserver {
return money; return money;
} }
<<<<<<< HEAD
public Map<ChannelBase, ChannelSubscriptionType> getSubscribedChannels() { public Map<ChannelBase, ChannelSubscriptionType> getSubscribedChannels() {
return subscribedChannels; return subscribedChannels;
} }
@ -212,18 +264,38 @@ public class NodeBase implements ChannelObserver {
return allowedPurchaser; return allowedPurchaser;
} }
=======
/**
* Adds amount to current assets
* @param m amount to be added
*/
>>>>>>> develop
public void addMoney(MonetaryAmount m) { public void addMoney(MonetaryAmount m) {
this.money = this.money.add(m); this.money = this.money.add(m);
} }
/**
* Subtracts amount from current assets.
* @param m amount to be subtracted
*/
public void subtractMoney(MonetaryAmount m) { public void subtractMoney(MonetaryAmount m) {
this.money = this.money.subtract(m); this.money = this.money.subtract(m);
} }
/**
* Validates signature on transaction.
* @param transaction transaction to be validated
* @return signature is valid
*/
public boolean validateSignature(Transaction transaction) { public boolean validateSignature(Transaction transaction) {
return SignatureManager.validateSignature(transaction); return SignatureManager.validateSignature(transaction);
} }
/**
* Checks if requirement creator is an allowed purchaser or allowed seller.
* @param req requirement
* @return creator is valid
*/
boolean senderPurchaserCheck(Requirement req) { boolean senderPurchaserCheck(Requirement req) {
NodeType creatorType = req.getCreator().nodeType; NodeType creatorType = req.getCreator().nodeType;
@ -232,6 +304,12 @@ public class NodeBase implements ChannelObserver {
((allowedPurchaser == creatorType || allowedPurchaser == NodeType.All) && req.getTransactionType() == TransactionType.PURCHASE)); ((allowedPurchaser == creatorType || allowedPurchaser == NodeType.All) && req.getTransactionType() == TransactionType.PURCHASE));
} }
/**
* Checks if requirement type corresponds with channel subscription type.
* @param requirement requirement
* @param channel channel
* @return requirement type corresponds with channel subscription type
*/
boolean transactionSubscriptionCheck(Requirement requirement, ChannelBase channel) { boolean transactionSubscriptionCheck(Requirement requirement, ChannelBase channel) {
switch (subscribedChannels.get(channel)) { switch (subscribedChannels.get(channel)) {
case SALE: case SALE:
@ -245,6 +323,11 @@ public class NodeBase implements ChannelObserver {
return false; return false;
} }
/**
* Chacks if product is available or if node has enough money
* @param req requirement
* @return product is available or node has enough money
*/
boolean requirementCheck(Requirement req) { boolean requirementCheck(Requirement req) {
Product product = storage.getProduct(req.getProductName(), req.getProductType()); Product product = storage.getProduct(req.getProductName(), req.getProductType());
return (req.getTransactionType() == TransactionType.SALE && money.isGreaterThanOrEqualTo(req.getPrice())) || return (req.getTransactionType() == TransactionType.SALE && money.isGreaterThanOrEqualTo(req.getPrice())) ||
@ -252,6 +335,11 @@ public class NodeBase implements ChannelObserver {
((product.getProductState() == ProductState.AVAILABLE) || product.getProductState() == ProductState.IN_REQUIREMENT)); ((product.getProductState() == ProductState.AVAILABLE) || product.getProductState() == ProductState.IN_REQUIREMENT));
} }
/**
* Chacks incomming requirement.
* @param requirement requirement
* @param channel channel
*/
@Override @Override
public void update(Requirement requirement, ChannelBase channel) { public void update(Requirement requirement, ChannelBase channel) {
if (senderPurchaserCheck(requirement) && transactionSubscriptionCheck(requirement, channel) && requirementCheck(requirement)) { if (senderPurchaserCheck(requirement) && transactionSubscriptionCheck(requirement, channel) && requirementCheck(requirement)) {
@ -259,14 +347,16 @@ public class NodeBase implements ChannelObserver {
acceptRequirement(requirement); acceptRequirement(requirement);
channel.disposeOf(requirement); channel.disposeOf(requirement);
} catch (InsufficientResourcesException e) { } catch (InsufficientResourcesException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.WARNING, e.getMessage());
} }
} }
} }
/**
* Receives transactions.
*/
public void tick() { public void tick() {
receiveTransactions(); receiveTransactions();
//System.out.println(this.getClass().getSimpleName() + ": " + money.getNumber());
} }
private static class RefusedRequirement { private static class RefusedRequirement {

View File

@ -4,6 +4,9 @@ import cz.cvut.fel.sit.omo.foodchain.node.interfaces.IBuyerNode;
import cz.cvut.fel.sit.omo.foodchain.node.interfaces.ISellerNode; import cz.cvut.fel.sit.omo.foodchain.node.interfaces.ISellerNode;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Base class for all retailer nodes
*/
public class RetailerNodeBase extends NodeBase implements IBuyerNode, ISellerNode { public class RetailerNodeBase extends NodeBase implements IBuyerNode, ISellerNode {
public RetailerNodeBase(double startMoney) { public RetailerNodeBase(double startMoney) {
super(startMoney); super(startMoney);

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.node.base;
import cz.cvut.fel.sit.omo.foodchain.node.interfaces.ISellerNode; import cz.cvut.fel.sit.omo.foodchain.node.interfaces.ISellerNode;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Base class for all seller nodes
*/
public class SellerNodeBase extends NodeBase implements ISellerNode { public class SellerNodeBase extends NodeBase implements ISellerNode {
public SellerNodeBase(double startMoney) { public SellerNodeBase(double startMoney) {
super(startMoney); super(startMoney);

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.node.enums; package cz.cvut.fel.sit.omo.foodchain.node.enums;
/**
* Enum class for all nodes
*/
public enum NodeType { public enum NodeType {
Farmer, Processor, Distributor, Seller, Customer, None, All Farmer, Processor, Distributor, Seller, Customer, None, All
} }

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.node.interfaces;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Interface for buyer nodes
*/
public interface IBuyerNode { public interface IBuyerNode {
void buyProduct(Product product); void buyProduct(Product product);

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.node.interfaces;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Interface for seller nodes
*/
public interface ISellerNode { public interface ISellerNode {
void sellProduct(Product product); void sellProduct(Product product);

View File

@ -3,8 +3,13 @@ package cz.cvut.fel.sit.omo.foodchain.operation;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
public class Action extends OperationBase { import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Operation for processing products in storage
*/
public class Action extends OperationBase {
private final OperationBase lastOperation; private final OperationBase lastOperation;
private final Product product; private final Product product;
private final ProductOperationType type; private final ProductOperationType type;
@ -18,14 +23,22 @@ public class Action extends OperationBase {
duration = type.getDuration(); duration = type.getDuration();
product.setCurrentOperation(this); product.setCurrentOperation(this);
product.setStateToInAction(); product.setStateToInAction();
System.out.println(toString());
LOGGER.log(Level.INFO, toString());
} }
/**
* Ends this action and changes products type to available.
*/
private void endAction() { private void endAction() {
this.setTimeEnd(); this.setTimeEnd();
product.setStateToAvailable(); product.setStateToAvailable();
} }
/**
* Changes actions duration or ends action.
* @return action is in progress
*/
public boolean tick() { public boolean tick() {
if (duration == 0) { if (duration == 0) {
endAction(); endAction();

View File

@ -5,7 +5,11 @@ import cz.cvut.fel.sit.omo.foodchain.reporting.ReportTextVisitor;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.logging.Level;
/**
* Operation for transporting money
*/
public class FinancialTransaction extends Transaction { public class FinancialTransaction extends Transaction {
private final MonetaryAmount amount; private final MonetaryAmount amount;
@ -17,9 +21,13 @@ public class FinancialTransaction extends Transaction {
this.transactionPaid = transactionPaid; this.transactionPaid = transactionPaid;
if (creator.getMoney().isLessThan(amount)) throw new InsufficientResourcesException("not enough money"); if (creator.getMoney().isLessThan(amount)) throw new InsufficientResourcesException("not enough money");
creator.subtractMoney(amount); creator.subtractMoney(amount);
System.out.println(toString());
LOGGER.log(Level.INFO, toString());
} }
/**
* Ends transaction and adds amount to receiver node.
*/
@Override @Override
public void endTransaction() { public void endTransaction() {
super.endTransaction(); super.endTransaction();

View File

@ -1,11 +1,18 @@
package cz.cvut.fel.sit.omo.foodchain.operation; package cz.cvut.fel.sit.omo.foodchain.operation;
import cz.cvut.fel.sit.omo.foodchain.factory.ScenarioFactory;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.logging.Logger;
/**
* Base class for all operations
*/
public abstract class OperationBase { public abstract class OperationBase {
protected static final Logger LOGGER = Logger.getLogger(OperationBase.class.getName());
private final LocalDateTime timeStart; private final LocalDateTime timeStart;
private LocalDateTime timeEnd; private LocalDateTime timeEnd;

View File

@ -3,6 +3,9 @@ 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.node.enums.NodeType;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Enum class for product operations types with parameters
*/
public enum ProductOperationType public enum ProductOperationType
{ {
STORE_MEAT(NodeType.All, ProductType.MEAT, 20, -8), STORE_MEAT(NodeType.All, ProductType.MEAT, 20, -8),

View File

@ -6,7 +6,11 @@ import cz.cvut.fel.sit.omo.foodchain.product.ProductState;
import cz.cvut.fel.sit.omo.foodchain.reporting.ReportTextVisitor; import cz.cvut.fel.sit.omo.foodchain.reporting.ReportTextVisitor;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.logging.Level;
/**
* Operation for transporting products
*/
public class ProductTransaction extends Transaction { public class ProductTransaction extends Transaction {
private final OperationBase lastOperation; private final OperationBase lastOperation;
@ -22,9 +26,13 @@ public class ProductTransaction extends Transaction {
product.setCurrentOperation(this); product.setCurrentOperation(this);
product.setStateToReadyForDispatch(); product.setStateToReadyForDispatch();
creator.getStorage().removeProduct(product); creator.getStorage().removeProduct(product);
System.out.println(toString());
LOGGER.log(Level.INFO, toString());
} }
/**
* Ends transaction and stores product in receivers storage.
*/
@Override @Override
public void endTransaction() { public void endTransaction() {
super.endTransaction(); super.endTransaction();

View File

@ -5,6 +5,9 @@ import cz.cvut.fel.sit.omo.foodchain.reporting.ReportTextVisitor;
import cz.cvut.fel.sit.omo.foodchain.signature.Signature; 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.signature.SignatureManager;
/**
* Operation for transporting things between nodes
*/
public abstract class Transaction extends OperationBase { public abstract class Transaction extends OperationBase {
private final TransactionType transactionType; private final TransactionType transactionType;
@ -18,6 +21,9 @@ public abstract class Transaction extends OperationBase {
signature = SignatureManager.signTransaction(this); signature = SignatureManager.signTransaction(this);
} }
/**
* Sets time end to current time.
*/
public void endTransaction() { public void endTransaction() {
this.setTimeEnd(); this.setTimeEnd();
} }

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.operation; package cz.cvut.fel.sit.omo.foodchain.operation;
/**
* Enum class for transaction types
*/
public enum TransactionType { public enum TransactionType {
SALE, PURCHASE SALE, PURCHASE

View File

@ -11,10 +11,20 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
/**
* Parser for XML configuration
*/
public class ConfigurationParser { public class ConfigurationParser {
private static Document activeDocument; private static Document activeDocument;
/**
* Parses xml file to document.
* @param name file name
* @throws ParserConfigurationException ParserConfigurationException
* @throws IOException IOException
* @throws SAXException SAXException
*/
public static void parseDocument(String name) throws ParserConfigurationException, IOException, SAXException { public static void parseDocument(String name) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true); factory.setValidating(true);
@ -24,6 +34,11 @@ public class ConfigurationParser {
activeDocument = builder.parse(file); activeDocument = builder.parse(file);
} }
/**
* Returns parsed result with all elements having provided tag.
* @param tag element tag
* @return parsed result element
*/
public static ParserResult getElements(String tag) { public static ParserResult getElements(String tag) {
NodeList elements = activeDocument.getElementsByTagName(tag); NodeList elements = activeDocument.getElementsByTagName(tag);
ParserResult resultList = new ParserResult(); ParserResult resultList = new ParserResult();

View File

@ -1,4 +1,7 @@
package cz.cvut.fel.sit.omo.foodchain.parser; package cz.cvut.fel.sit.omo.foodchain.parser;
/**
* Parser for console input
*/
public class ConsoleParser { public class ConsoleParser {
} }

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.parser;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
/**
* Wrapper class for parser result elements
*/
public class ParserResult { public class ParserResult {
private final List<ParserResultElement> elements; private final List<ParserResultElement> elements;
@ -11,6 +14,10 @@ public class ParserResult {
elements = new LinkedList<>(); elements = new LinkedList<>();
} }
/**
* Adds element to list.
* @param element element
*/
public void addElement(ParserResultElement element) { public void addElement(ParserResultElement element) {
elements.add(element); elements.add(element);
} }

View File

@ -4,6 +4,9 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map; import java.util.Map;
/**
* Class for storing all information given in a xml tag
*/
public class ParserResultElement { public class ParserResultElement {
private String name; private String name;

View File

@ -3,8 +3,16 @@ package cz.cvut.fel.sit.omo.foodchain.pool;
import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase; import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
/**
* Pool for storing all channels
*/
public class ChannelPool extends PoolListBase<ChannelBase> { public class ChannelPool extends PoolListBase<ChannelBase> {
/**
* Finds channel by its type.
* @param type type of channel
* @return channel
*/
public ChannelBase findByType(ProductType type) { public ChannelBase findByType(ProductType type) {
return findAll().stream().filter(ch -> ch.getProductType().equals(type)).findFirst().orElse(null); return findAll().stream().filter(ch -> ch.getProductType().equals(type)).findFirst().orElse(null);
} }

View File

@ -2,5 +2,8 @@ package cz.cvut.fel.sit.omo.foodchain.pool;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
/**
*Pool for storing all nodes
*/
public class NodePool extends PoolListBase<NodeBase> { public class NodePool extends PoolListBase<NodeBase> {
} }

View File

@ -4,6 +4,9 @@ import cz.cvut.fel.sit.omo.foodchain.util.Singleton;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
/**
* Database class for storing all pools
*/
public class PoolDatabase { public class PoolDatabase {
public ChannelPool getChannelPoolInstance() { public ChannelPool getChannelPoolInstance() {

View File

@ -3,6 +3,10 @@ package cz.cvut.fel.sit.omo.foodchain.pool;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
/**
* Base class for all pools
* @param <T> pool type
*/
public abstract class PoolListBase<T> { public abstract class PoolListBase<T> {
List<T> pool; List<T> pool;

View File

@ -2,5 +2,8 @@ package cz.cvut.fel.sit.omo.foodchain.pool;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
/**
* Pool for storing all products
*/
public class ProductPool extends PoolListBase<Product> { public class ProductPool extends PoolListBase<Product> {
} }

View File

@ -2,5 +2,8 @@ package cz.cvut.fel.sit.omo.foodchain.pool;
import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario; import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario;
/**
* Pool for storing all scenarios
*/
public class ScenarioPool extends PoolListBase<Scenario> { public class ScenarioPool extends PoolListBase<Scenario> {
} }

View File

@ -7,6 +7,9 @@ import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
/**
* Product class
*/
public class Product public class Product
{ {
private ProductState productState; private ProductState productState;
@ -16,19 +19,6 @@ public class Product
private String name; private String name;
/**
* Creates Product with default state AVAILABLE
* @param name name of product
* @param productType type of product
*/
public Product(String name, ProductType productType)
{
this.name = name;
this.productType = productType;
this.productState = ProductState.AVAILABLE;
this.price = Money.of(0, "USD");
}
public Product(String name, ProductType productType, double m) public Product(String name, ProductType productType, double m)
{ {
this.name = name; this.name = name;
@ -38,27 +28,9 @@ public class Product
} }
/** /**
* Creates Product * Passes tick onto current operation
* @param name name of product * @return operation is active
* @param productType type of product
* @param productState state of product
*/ */
public Product(String name, ProductType productType, ProductState productState)
{
this.name = name;
this.productType = productType;
this.productState = productState;
this.price = Money.of(0, "USD");
}
public Product(String name, ProductType productType, ProductState productState, double m)
{
this.name = name;
this.productType = productType;
this.productState = productState;
this.price = Money.of(m, "USD");
}
public boolean tick() { public boolean tick() {
try { try {
return ((Action) currentOperation).tick(); return ((Action) currentOperation).tick();
@ -138,13 +110,6 @@ public class Product
throw new IllegalStateException("Cannot set state IN_REQUIREMENT. Product is not AVAILABLE!"); throw new IllegalStateException("Cannot set state IN_REQUIREMENT. Product is not AVAILABLE!");
} }
/*
public void setProductState(ProductState productState)
{
this.productState = productState;
}*/
//Getters & Setters //Getters & Setters
public ProductState getProductState() public ProductState getProductState()

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.product; package cz.cvut.fel.sit.omo.foodchain.product;
/**
* Enum class for product states
*/
public enum ProductState public enum ProductState
{ {
AVAILABLE, READY_FOR_DISPATCH, IN_TRANSIT, READY_FOR_RECEPTION, IN_ACTION, IN_REQUIREMENT AVAILABLE, READY_FOR_DISPATCH, IN_TRANSIT, READY_FOR_RECEPTION, IN_ACTION, IN_REQUIREMENT

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.product; package cz.cvut.fel.sit.omo.foodchain.product;
/**
* Enum class for product types
*/
public enum ProductType public enum ProductType
{ {
MEAT, FRUIT, VEGETABLE, OTHER, ALL // ALL is used only for actions MEAT, FRUIT, VEGETABLE, OTHER, ALL // ALL is used only for actions

View File

@ -4,12 +4,19 @@ import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType; import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType;
import cz.cvut.fel.sit.omo.foodchain.product.ProductState; 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.product.ProductType;
import cz.cvut.fel.sit.omo.foodchain.util.Ticker;
import org.javamoney.moneta.Money; import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Requirement class
*/
public class Requirement { public class Requirement {
private static final Logger LOGGER = Logger.getLogger(Ticker.class.getName());
private final NodeBase creator; private final NodeBase creator;
private final TransactionType transactionType; private final TransactionType transactionType;
@ -20,17 +27,6 @@ public class Requirement {
private static int counter; private static int counter;
private int id; private int id;
public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName, double price) {
this.creator = creator;
this.transactionType = transactionType;
this.productType = productType;
this.productName = productName;
this.price = Money.of(price, "USD");
this.TTL = 3;
this.id = counter++;
System.out.println(toString());
}
public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName, MonetaryAmount price) { public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName, MonetaryAmount price) {
this.creator = creator; this.creator = creator;
this.transactionType = transactionType; this.transactionType = transactionType;
@ -39,9 +35,14 @@ public class Requirement {
this.price = price; this.price = price;
this.TTL = 3; this.TTL = 3;
this.id = counter++; this.id = counter++;
System.out.println(toString());
LOGGER.log(Level.INFO, toString());
} }
/**
* Reduces TTL.
*/
public void tick() { public void tick() {
TTL--; TTL--;
} }

View File

@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.scenario;
import cz.cvut.fel.sit.omo.foodchain.node.Customer; import cz.cvut.fel.sit.omo.foodchain.node.Customer;
/**
* Step for consuming random product from storage
*/
public class ConsumeProductStep extends ScenarioStep { public class ConsumeProductStep extends ScenarioStep {
private final Customer node; private final Customer node;
@ -10,6 +13,9 @@ public class ConsumeProductStep extends ScenarioStep {
this.node = node; this.node = node;
} }
/**
* Consumes random product.
*/
@Override @Override
void execute() { void execute() {
node.consumeProduct(); node.consumeProduct();

View File

@ -4,6 +4,11 @@ import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.operation.ProductOperationType; 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.Product;
import java.util.logging.Level;
/**
* Step for starting action on product(s)
*/
public class DoActionStep extends ScenarioStep { public class DoActionStep extends ScenarioStep {
private final NodeBase nodeBase; private final NodeBase nodeBase;
private final ProductOperationType productOperationType; private final ProductOperationType productOperationType;
@ -20,6 +25,9 @@ public class DoActionStep extends ScenarioStep {
} }
/**
* Starts action.
*/
@Override @Override
void execute() { void execute() {
try { try {
@ -31,7 +39,7 @@ public class DoActionStep extends ScenarioStep {
} }
} }
catch (IllegalCallerException e) { catch (IllegalCallerException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.SEVERE, e.getMessage());
} }
} }
} }

View File

@ -4,6 +4,11 @@ import cz.cvut.fel.sit.omo.foodchain.FoodChain;
import cz.cvut.fel.sit.omo.foodchain.node.Farmer; import cz.cvut.fel.sit.omo.foodchain.node.Farmer;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
import java.util.logging.Level;
/**
* Step for generating product from pool
*/
public class GenerateProductStep extends ScenarioStep { public class GenerateProductStep extends ScenarioStep {
private final Farmer node; private final Farmer node;
@ -18,10 +23,13 @@ public class GenerateProductStep extends ScenarioStep {
} }
else { else {
product = null; product = null;
System.err.println("Insufficient products in pool"); LOGGER.log(Level.SEVERE, "Insufficient products in pool");
} }
} }
/**
* Generates product from pool.
*/
@Override @Override
void execute() { void execute() {
node.generateProduct(product); node.generateProduct(product);

View File

@ -1,7 +1,13 @@
package cz.cvut.fel.sit.omo.foodchain.scenario; package cz.cvut.fel.sit.omo.foodchain.scenario;
/**
* Step for skipping
*/
public class PassStep extends ScenarioStep { public class PassStep extends ScenarioStep {
/**
* Does nothing.
*/
@Override @Override
void execute() {} void execute() {}
} }

View File

@ -3,28 +3,34 @@ package cz.cvut.fel.sit.omo.foodchain.scenario;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
/**
* Scenatio class fpr holding and executing steps
*/
public class Scenario { public class Scenario {
List<ScenarioStep> steps; List<ScenarioStep> steps;
Iterator<ScenarioStep> stepIterator; Iterator<ScenarioStep> stepIterator;
public Scenario() {
stepIterator = steps.listIterator(0);
}
public Scenario(List<ScenarioStep> steps) { public Scenario(List<ScenarioStep> steps) {
this.steps = steps; this.steps = steps;
stepIterator = steps.listIterator(0); stepIterator = steps.listIterator(0);
} }
/**
* Executes next step.
* @return scenario has steps
*/
boolean execute() { boolean execute() {
if (!stepIterator.hasNext()) { if (!stepIterator.hasNext()) {
// stepIterator = steps.listIterator(0);
return false; return false;
} }
stepIterator.next().execute(); stepIterator.next().execute();
return true; return true;
} }
/**
* Executes next step.
* @return scenario has steps
*/
public boolean tick() { public boolean tick() {
return execute(); return execute();
} }

View File

@ -1,5 +1,14 @@
package cz.cvut.fel.sit.omo.foodchain.scenario; package cz.cvut.fel.sit.omo.foodchain.scenario;
import cz.cvut.fel.sit.omo.foodchain.operation.OperationBase;
import java.util.logging.Logger;
/**
* Scenario step class
*/
public abstract class ScenarioStep { public abstract class ScenarioStep {
protected static final Logger LOGGER = Logger.getLogger(ScenarioStep.class.getName());
abstract void execute(); abstract void execute();
} }

View File

@ -7,7 +7,11 @@ import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException; import javax.naming.InsufficientResourcesException;
import java.util.logging.Level;
/**
* Step for sending requirements
*/
public class SendRequirementStep extends ScenarioStep { public class SendRequirementStep extends ScenarioStep {
private final NodeBase node; private final NodeBase node;
private final TransactionType tType; private final TransactionType tType;
@ -33,12 +37,15 @@ public class SendRequirementStep extends ScenarioStep {
this.pPrice = Money.of(price, "USD"); this.pPrice = Money.of(price, "USD");
} }
/**
* Creates requirement.
*/
@Override @Override
void execute() { void execute() {
try { try {
node.createRequirement(tType, pType, pName, pPrice); node.createRequirement(tType, pType, pName, pPrice);
} catch (InsufficientResourcesException e) { } catch (InsufficientResourcesException e) {
System.err.println(e.getMessage()); LOGGER.log(Level.SEVERE, e.getMessage());
} }
} }
} }

View File

@ -5,6 +5,9 @@ import cz.cvut.fel.sit.omo.foodchain.operation.Transaction;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.UUID; import java.util.UUID;
/**
* Signature class validating its transaction
*/
public class Signature { public class Signature {
private final String managerCode; private final String managerCode;

View File

@ -2,14 +2,27 @@ package cz.cvut.fel.sit.omo.foodchain.signature;
import cz.cvut.fel.sit.omo.foodchain.operation.Transaction; import cz.cvut.fel.sit.omo.foodchain.operation.Transaction;
/**
* Manager class for creating and validating signatures
*/
public class SignatureManager { public class SignatureManager {
private static final String MANAGER_CODE = "iW91AJWNOCmX1pbpLlW0"; private static final String MANAGER_CODE = "iW91AJWNOCmX1pbpLlW0";
/**
* Creates signature for transaction.
* @param transaction transaction
* @return signature
*/
public static Signature signTransaction(Transaction transaction) { public static Signature signTransaction(Transaction transaction) {
return new Signature(MANAGER_CODE, transaction); return new Signature(MANAGER_CODE, transaction);
} }
/**
* Check if signature corresponds with its transaction.
* @param transaction transaction
* @return signature corresponds with its transaction
*/
public static boolean validateSignature(Transaction transaction) { public static boolean validateSignature(Transaction transaction) {
return transaction.equals(transaction.getSignature().getTransaction(MANAGER_CODE)) return transaction.equals(transaction.getSignature().getTransaction(MANAGER_CODE))
&& transaction.getSignature().getUuid(MANAGER_CODE).equals(transaction.getSignature().getTransaction(MANAGER_CODE).getSignature().getUuid(MANAGER_CODE)); && transaction.getSignature().getUuid(MANAGER_CODE).equals(transaction.getSignature().getTransaction(MANAGER_CODE).getSignature().getUuid(MANAGER_CODE));

View File

@ -3,6 +3,9 @@ package cz.cvut.fel.sit.omo.foodchain.util;
import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase; import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase;
import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement; import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement;
/**
* Interface for nodes that receives requirements
*/
public interface ChannelObserver { public interface ChannelObserver {
void update(Requirement requirement, ChannelBase channel); void update(Requirement requirement, ChannelBase channel);
} }

View File

@ -1,5 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.util; package cz.cvut.fel.sit.omo.foodchain.util;
/**
* Interface for channels to work with observers
*/
public interface Observable { public interface Observable {
void attach(ChannelObserver channelObserver); void attach(ChannelObserver channelObserver);
void detach(ChannelObserver channelObserver); void detach(ChannelObserver channelObserver);

View File

@ -0,0 +1,37 @@
package cz.cvut.fel.sit.omo.foodchain.util;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
public class ReportLogger extends Handler
{
@Override
public void publish(LogRecord record) {
StringBuilder sb = new StringBuilder();
sb.append(record.getSourceClassName())
.append("#")
.append(record.getSourceMethodName())
.append(" - ")
.append(record.getMessage());
if(record.getLevel().equals(Level.WARNING) || record.getLevel().equals(Level.SEVERE))
{
System.err.println(sb.toString());
//todo add some outprint to report log
}
else
{
System.out.println(sb.toString());
//todo add some outprint to report log
}
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
}

View File

@ -5,6 +5,9 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/**
* Singleton implementation 1 of 3
*/
public class Singleton { public class Singleton {
private static final Singleton instance = new Singleton(); private static final Singleton instance = new Singleton();

View File

@ -2,19 +2,30 @@ package cz.cvut.fel.sit.omo.foodchain.util;
import cz.cvut.fel.sit.omo.foodchain.FoodChain; import cz.cvut.fel.sit.omo.foodchain.FoodChain;
import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase; import cz.cvut.fel.sit.omo.foodchain.channel.ChannelBase;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.pool.PoolDatabase; import cz.cvut.fel.sit.omo.foodchain.pool.PoolDatabase;
import cz.cvut.fel.sit.omo.foodchain.product.Product; import cz.cvut.fel.sit.omo.foodchain.product.Product;
import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario; import cz.cvut.fel.sit.omo.foodchain.scenario.Scenario;
import javax.swing.*; import javax.swing.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Creates artificial time for application
*/
public class Ticker { public class Ticker {
protected static final Logger LOGGER = Logger.getLogger(Ticker.class.getName());
private static Timer timer; private static Timer timer;
/**
* Starts timer.
*/
public static void start() { public static void start() {
timer = new Timer(1000, actionEvent -> { timer = new Timer(1000, actionEvent -> {
System.out.println("-----tick-----"); LOGGER.log(Level.INFO, "-----tick-----");
PoolDatabase db = FoodChain.getFactoryManager().getPoolDatabaseInstance(); PoolDatabase db = FoodChain.getFactoryManager().getPoolDatabaseInstance();
boolean productBool = db.getProductPoolInstance().findAll().stream().filter(Product::tick).count() == 0; // change duration of action boolean productBool = db.getProductPoolInstance().findAll().stream().filter(Product::tick).count() == 0; // change duration of action
boolean channelBool = db.getChannelPoolInstance().findAll().stream().filter(ChannelBase::tick).count() == 0; // change TTL of requirements boolean channelBool = db.getChannelPoolInstance().findAll().stream().filter(ChannelBase::tick).count() == 0; // change TTL of requirements
@ -25,6 +36,9 @@ public class Ticker {
timer.start(); timer.start();
} }
/**
* Stops timer (ends application).
*/
public static void stop() { public static void stop() {
timer.stop(); timer.stop();
} }