[Draft] Implemented receiveTransaction

This commit is contained in:
Tomáš Musil 2020-12-26 20:05:33 +01:00
parent c81e2b0332
commit c0fc73218e
10 changed files with 107 additions and 44 deletions

View File

@ -13,7 +13,7 @@
<channels>MEAT PURCHASE;VEGETABLE PURCHASE;FRUIT PURCHASE</channels> <channels>MEAT PURCHASE;VEGETABLE PURCHASE;FRUIT PURCHASE</channels>
</node> </node>
<node type = "Processor"> <node type = "Processor">
<money>5</money> <money>10</money>
<channels>MEAT SALE_AND_PURCHASE;VEGETABLE SALE_AND_PURCHASE;FRUIT SALE_AND_PURCHASE</channels> <channels>MEAT SALE_AND_PURCHASE;VEGETABLE SALE_AND_PURCHASE;FRUIT SALE_AND_PURCHASE</channels>
</node> </node>
<node type = "Distributor"> <node type = "Distributor">

View File

@ -6,18 +6,19 @@
type CDATA #REQUIRED> type CDATA #REQUIRED>
<!ELEMENT steps (#PCDATA)> <!ELEMENT steps (#PCDATA)>
]> ]>
<!--
generate
consume
doaction <product-operation-type>
doaction <product-operation-type> <product-name>
sendreq <transaction-type> <product-type> <product-name>
pass
-->
<scenarios> <scenarios>
<scenario type="Farmer"> <scenario type="Farmer">
<steps> <steps>
generate generate
generate sendreq SALE FRUIT jablko
generate
generate
generate
generate
generate
generate
generate
</steps> </steps>
</scenario> </scenario>
</scenarios> </scenarios>

View File

@ -1,5 +1,6 @@
package cz.cvut.fel.sit.omo.foodchain.channel; package cz.cvut.fel.sit.omo.foodchain.channel;
import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase;
import cz.cvut.fel.sit.omo.foodchain.operation.Transaction; import cz.cvut.fel.sit.omo.foodchain.operation.Transaction;
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.requirement.Requirement; import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement;
@ -32,9 +33,9 @@ public abstract class ChannelBase implements Observable {
this.productType = ProductType.OTHER; this.productType = ProductType.OTHER;
} }
public Queue<Transaction> getTransactions() public Queue<Transaction> getTransactions(NodeBase node)
{ {
return this.transactions; return this.transactions.stream().filter(t -> t.getNodeReceiver().equals(node)).collect(Collectors.toCollection(LinkedList::new));
} }
public Queue<Requirement> getCurrentRequirements() public Queue<Requirement> getCurrentRequirements()

View File

@ -60,8 +60,11 @@ public class ScenarioFactory
scenarioStep = new DoActionStep(node, ProductOperationType.valueOf(parts[1]), p); scenarioStep = new DoActionStep(node, ProductOperationType.valueOf(parts[1]), p);
} }
break; break;
case "sendreq": case "sell":
scenarioStep = new SendRequirementStep(node, TransactionType.valueOf(parts[1]), ProductType.valueOf(parts[2]), parts[3], Double.parseDouble(parts[4])); scenarioStep = new SendRequirementStep(node, TransactionType.SALE, ProductType.valueOf(parts[1]), parts[2], Double.parseDouble(parts[3]));
break;
case "buy":
scenarioStep = new SendRequirementStep(node, TransactionType.PURCHASE, ProductType.valueOf(parts[1]), parts[2]);
break; break;
case "pass": case "pass":
scenarioStep = new PassStep(); scenarioStep = new PassStep();
@ -75,10 +78,6 @@ public class ScenarioFactory
{ {
System.err.println("! Wrong type of enum in ScenarioFactory: " + e); System.err.println("! Wrong type of enum in ScenarioFactory: " + e);
} }
catch (Exception e)
{
System.err.println("! Fatal error in ScenarioFactory: " + e);
}
return s; return s;
} }

View File

@ -14,6 +14,7 @@ import cz.cvut.fel.sit.omo.foodchain.util.ChannelObserver;
import org.javamoney.moneta.Money; import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -25,7 +26,7 @@ public class NodeBase implements ChannelObserver {
private final List<Product> products; private final List<Product> products;
private final List<Transaction> refusedTransactions; private final List<Transaction> refusedTransactions;
private final MonetaryAmount money; private MonetaryAmount money;
protected NodeType allowedSeller; protected NodeType allowedSeller;
protected NodeType allowedPurchaser; protected NodeType allowedPurchaser;
@ -45,42 +46,64 @@ public class NodeBase implements ChannelObserver {
public void sendTransaction(Product product, NodeBase node) { public void sendTransaction(Product product, NodeBase node) {
Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product); try {
Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product);
subscribedChannels.keySet().stream() subscribedChannels.keySet().stream()
.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) {
e.printStackTrace();
}
} }
public void sendTransaction(MonetaryAmount amount, NodeBase node, ProductTransaction prevTransaction) { public void sendTransaction(MonetaryAmount amount, NodeBase node, ProductTransaction prevTransaction) {
Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction); try {
Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction);
subscribedChannels.keySet().stream() subscribedChannels.keySet().stream()
.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) {
e.printStackTrace();
}
} }
public void receiveTransaction(Transaction transaction) {
try {
receiveTransaction((ProductTransaction) transaction);
}
catch (Exception e) {
try {
receiveTransaction((FinancialTransaction) transaction);
}
catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
public void receiveTransaction(ProductTransaction transaction) { public void receiveTransaction(ProductTransaction transaction) {
if (validateSignature(transaction)) {
transaction.endTransaction();
sendTransaction(transaction.getProduct().getPrice(), transaction.getNodeCreator(), transaction);
}
else refuseTransaction(transaction);
} }
public void receiveTransaction(FinancialTransaction transaction) { public void receiveTransaction(FinancialTransaction transaction) {
if (validateSignature(transaction)) transaction.endTransaction();
else refuseTransaction(transaction);
} }
public void refuseTransaction(Transaction transaction) { public void refuseTransaction(Transaction transaction) {
transaction.endTransaction(); transaction.endTransaction();
refusedTransactions.add(transaction); //TODO maybe need more work on it refusedTransactions.add(transaction);
} }
public Transaction readNextTransaction(ChannelBase channel) { public void receiveTransactions() {
//TODO subscribedChannels.keySet().forEach(ch -> ch.getTransactions(this).forEach(t -> {receiveTransaction(t); ch.disposeOf(t);}));
return null;
// return channel.getNextTransaction();
} }
@ -153,7 +176,11 @@ public class NodeBase implements ChannelObserver {
} }
public void addMoney(MonetaryAmount m) { public void addMoney(MonetaryAmount m) {
this.money.add(m); this.money = this.money.add(m);
}
public void subtractMoney(MonetaryAmount m) {
this.money = this.money.subtract(m);
} }
public boolean validateSignature(Transaction transaction) { public boolean validateSignature(Transaction transaction) {
@ -194,4 +221,9 @@ public class NodeBase implements ChannelObserver {
acceptRequirement(requirement); acceptRequirement(requirement);
} }
} }
public void tick() {
receiveTransactions();
System.out.println(this.getClass().getSimpleName() + ": " + money.getNumber());
}
} }

View File

@ -3,17 +3,20 @@ 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 javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException;
public class FinancialTransaction extends Transaction { public class FinancialTransaction extends Transaction {
private final MonetaryAmount amount; private final MonetaryAmount amount;
private final ProductTransaction transactionPaid; private final ProductTransaction transactionPaid;
public FinancialTransaction(NodeBase creator, NodeBase receiver, TransactionType type, MonetaryAmount amount, ProductTransaction transactionPaid) { public FinancialTransaction(NodeBase creator, NodeBase receiver, TransactionType type, MonetaryAmount amount, ProductTransaction transactionPaid) throws InsufficientResourcesException {
super(creator, receiver, type); super(creator, receiver, type);
this.amount = amount; this.amount = amount;
this.transactionPaid = transactionPaid; this.transactionPaid = transactionPaid;
creator.addMoney(amount.negate()); if (creator.getMoney().isLessThan(amount)) throw new InsufficientResourcesException("not enough money");
creator.subtractMoney(amount);
System.out.println(toString());
} }
@Override @Override
@ -29,4 +32,12 @@ public class FinancialTransaction extends Transaction {
public ProductTransaction getTransactionPaid() { public ProductTransaction getTransactionPaid() {
return transactionPaid; return transactionPaid;
} }
@Override
public String toString() {
return "FinancialTransaction{" +
"amount=" + amount.getNumber() +
", transactionPaid=" + transactionPaid +
'}';
}
} }

View File

@ -2,6 +2,9 @@ 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;
import cz.cvut.fel.sit.omo.foodchain.product.ProductState;
import javax.naming.InsufficientResourcesException;
public class ProductTransaction extends Transaction { public class ProductTransaction extends Transaction {
@ -9,19 +12,22 @@ public class ProductTransaction extends Transaction {
private final Product product; private final Product product;
private final ProductOperationType type; private final ProductOperationType type;
public ProductTransaction(NodeBase creator, NodeBase receiver, TransactionType transactionType, Product product) { public ProductTransaction(NodeBase creator, NodeBase receiver, TransactionType transactionType, Product product) throws InsufficientResourcesException {
super(creator, receiver, transactionType); super(creator, receiver, transactionType);
this.product = product; this.product = product;
type = null; type = null;
lastOperation = product.getCurrentOperation(); lastOperation = product.getCurrentOperation();
if (product == null || product.getProductState() != ProductState.AVAILABLE) throw new InsufficientResourcesException("product not available");
product.setCurrentOperation(this); product.setCurrentOperation(this);
product.setStateToReadyForDispatch(); product.setStateToReadyForDispatch();
creator.getStorage().remove(product);
System.out.println(toString()); System.out.println(toString());
} }
@Override @Override
public void endTransaction() { public void endTransaction() {
super.endTransaction(); super.endTransaction();
getNodeReceiver().storeProduct(product);
product.setStateToAvailable(); product.setStateToAvailable();
} }

View File

@ -2,10 +2,12 @@ package cz.cvut.fel.sit.omo.foodchain.requirement;
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.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.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import org.javamoney.moneta.Money; import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import javax.naming.InsufficientResourcesException;
public class Requirement { public class Requirement {

View File

@ -3,20 +3,31 @@ package cz.cvut.fel.sit.omo.foodchain.scenario;
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.operation.TransactionType; import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType;
import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount;
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;
private final ProductType pType; private final ProductType pType;
private final String pName; private final String pName;
private final double pPrice; private final MonetaryAmount pPrice;
public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName, double pPrice) { public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName) {
this.node = node; this.node = node;
this.tType = tType; this.tType = tType;
this.pType = pType; this.pType = pType;
this.pName = pName; this.pName = pName;
this.pPrice = pPrice; this.pPrice = Money.of(0, "USD");
}
public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName, Double price) {
this.node = node;
this.tType = tType;
this.pType = pType;
this.pName = pName;
this.pPrice = Money.of(price, "USD");
} }
@Override @Override

View File

@ -14,12 +14,12 @@ public class Ticker {
public static void start() { public static void start() {
timer = new Timer(500, actionEvent -> { timer = new Timer(500, actionEvent -> {
System.out.println("tick"); System.out.println("-----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 scenarioBool = db.getScenarioPoolInstance().findAll().stream().filter(Scenario::tick).count() == 0; // do next step in scenario boolean scenarioBool = db.getScenarioPoolInstance().findAll().stream().filter(Scenario::tick).count() == 0; // do next step in scenario
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
// db.getNodePoolInstance().findAll().forEach(n -> n.tick()); // maybe unnecessary db.getNodePoolInstance().findAll().forEach(n -> n.tick()); // receive transactions
if (channelBool && productBool && scenarioBool) stop(); if (channelBool && productBool && scenarioBool) stop();
}); });
timer.start(); timer.start();