Implemented requirement acceptance

This commit is contained in:
Tomáš Musil 2020-12-26 16:59:00 +01:00
parent 853bf05ee5
commit 12fc7a1309
14 changed files with 102 additions and 33 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>0</money> <money>5</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

@ -20,10 +20,4 @@
generate generate
</steps> </steps>
</scenario> </scenario>
<scenario type="Customer">
<steps>
pass
sendreq PURCHASE FRUIT jablko
</steps>
</scenario>
</scenarios> </scenarios>

View File

@ -17,8 +17,8 @@
</dependencies> </dependencies>
<properties> <properties>
<maven.compiler.target>14</maven.compiler.target> <maven.compiler.target>12</maven.compiler.target>
<maven.compiler.source>14</maven.compiler.source> <maven.compiler.source>12</maven.compiler.source>
</properties> </properties>
</project> </project>

View File

@ -60,7 +60,7 @@ public abstract class ChannelBase implements Observable {
@Override @Override
public void notifyAllObservers(){ public void notifyAllObservers(){
subscribers.forEach(subscriber -> requirements.forEach(subscriber::update)); subscribers.forEach(subscriber -> new LinkedList<>(requirements).forEach(r -> subscriber.update(r, this)));
} }
@Override @Override
@ -82,6 +82,10 @@ public abstract class ChannelBase implements Observable {
this.transactions.add(transaction); this.transactions.add(transaction);
} }
public void disposeOf(Requirement requirement) { this.requirements.remove(requirement); }
public void disposeOf(Transaction transaction) { this.transactions.remove(transaction); }
/** /**
* Clears all requirements from this channel * Clears all requirements from this channel
*/ */

View File

@ -61,7 +61,7 @@ public class ScenarioFactory
} }
break; break;
case "sendreq": case "sendreq":
scenarioStep = new SendRequirementStep(node, TransactionType.valueOf(parts[1]), ProductType.valueOf(parts[2]), parts[3]); scenarioStep = new SendRequirementStep(node, TransactionType.valueOf(parts[1]), ProductType.valueOf(parts[2]), parts[3], Double.parseDouble(parts[4]));
break; break;
case "pass": case "pass":
scenarioStep = new PassStep(); scenarioStep = new PassStep();

View File

@ -15,6 +15,6 @@ public class Farmer extends SellerNodeBase {
public void generateProduct(Product product) { public void generateProduct(Product product) {
storeProduct(product); storeProduct(product);
createRequirement(TransactionType.SALE, product.getProductType(), product.getName()); createRequirement(TransactionType.SALE, product.getProductType(), product.getName(), product.getPrice());
} }
} }

View File

@ -5,6 +5,7 @@ import cz.cvut.fel.sit.omo.foodchain.channel.ChannelSubscriptionType;
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.operation.*; 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.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.product.ProductType;
import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement; 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.Signature;
@ -83,15 +84,28 @@ public class NodeBase implements ChannelObserver {
} }
public void createRequirement(TransactionType tType, ProductType pType, String pName) { public void createRequirement(TransactionType tType, ProductType pType, String pName, double price) {
Requirement req = new Requirement(this, tType, pType, pName); Requirement req = new Requirement(this, tType, pType, pName, price);
subscribedChannels.keySet().stream() subscribedChannels.keySet().stream()
.filter(ch -> ch.getProductType().equals(pType)) .filter(ch -> ch.getProductType().equals(pType))
.findAny().ifPresent(channel -> channel.addRequirement(req)); .findAny().ifPresent(channel -> channel.addRequirement(req));
} }
public void acceptRequirement(Requirement requirement) { public void createRequirement(TransactionType tType, ProductType pType, String pName, MonetaryAmount price) {
System.out.println(this.getClass().getSimpleName() + " accepted " + requirement.toString()); Requirement req = new Requirement(this, tType, pType, pName, price);
subscribedChannels.keySet().stream()
.filter(ch -> ch.getProductType().equals(pType))
.findAny().ifPresent(channel -> channel.addRequirement(req));
}
public void acceptRequirement(Requirement req) {
System.out.println(this.getClass().getSimpleName() + " accepted " + req.toString());
if (req.getTransactionType() == TransactionType.SALE) {
createRequirement(TransactionType.PURCHASE, req.getProductType(), req.getProductName(), req.getPrice());
}
else {
sendTransaction(getProductFromStorage(req.getProductName(), req.getProductType()), req.getCreator());
}
} }
@ -134,10 +148,13 @@ public class NodeBase implements ChannelObserver {
return products; return products;
} }
public Signature generateSignature(Transaction transaction) { public MonetaryAmount getMoney() {
return SignatureManager.signTransaction(transaction); return money;
} }
public void addMoney(MonetaryAmount m) {
this.money.add(m);
}
public boolean validateSignature(Transaction transaction) { public boolean validateSignature(Transaction transaction) {
return SignatureManager.validateSignature(transaction); return SignatureManager.validateSignature(transaction);
@ -151,9 +168,30 @@ public class NodeBase implements ChannelObserver {
((allowedPurchaser == NodeType.valueOf(simpleName) || allowedPurchaser == NodeType.All) && req.getTransactionType() == TransactionType.PURCHASE)); ((allowedPurchaser == NodeType.valueOf(simpleName) || allowedPurchaser == NodeType.All) && req.getTransactionType() == TransactionType.PURCHASE));
} }
boolean transactionSubscriptionCheck(Requirement requirement, ChannelBase channel) {
switch (subscribedChannels.get(channel)) {
case SALE:
return requirement.getTransactionType() == TransactionType.SALE;
case PURCHASE:
return requirement.getTransactionType() == TransactionType.PURCHASE;
case SALE_AND_PURCHASE:
return true;
}
return false;
}
boolean requirementCheck(Requirement req) {
return (req.getTransactionType() == TransactionType.SALE && money.isGreaterThanOrEqualTo(req.getPrice())) ||
(req.getTransactionType() == TransactionType.PURCHASE && getProductFromStorage(req.getProductName(), req.getProductType()) != null &&
getProductFromStorage(req.getProductName(), req.getProductType()).getProductState() == ProductState.AVAILABLE);
}
@Override @Override
public void update(Requirement requirement) { public void update(Requirement requirement, ChannelBase channel) {
if (senderPurchaserCheck(requirement)) if (senderPurchaserCheck(requirement) && transactionSubscriptionCheck(requirement, channel) && requirementCheck(requirement)) {
channel.disposeOf(requirement);
acceptRequirement(requirement); acceptRequirement(requirement);
} }
}
} }

View File

@ -13,6 +13,13 @@ public class FinancialTransaction extends Transaction {
super(creator, receiver, type); super(creator, receiver, type);
this.amount = amount; this.amount = amount;
this.transactionPaid = transactionPaid; this.transactionPaid = transactionPaid;
creator.addMoney(amount.negate());
}
@Override
public void endTransaction() {
super.endTransaction();
getNodeReceiver().addMoney(amount);
} }
public MonetaryAmount getAmount() { public MonetaryAmount getAmount() {

View File

@ -16,6 +16,7 @@ public class ProductTransaction extends Transaction {
lastOperation = product.getCurrentOperation(); lastOperation = product.getCurrentOperation();
product.setCurrentOperation(this); product.setCurrentOperation(this);
product.setStateToReadyForDispatch(); product.setStateToReadyForDispatch();
System.out.println(toString());
} }
@Override @Override
@ -35,4 +36,11 @@ public class ProductTransaction extends Transaction {
public ProductOperationType getType() { public ProductOperationType getType() {
return type; return type;
} }
@Override
public String toString() {
return "ProductTransaction{" +
"product=" + product.getName() +
'}';
}
} }

View File

@ -15,7 +15,6 @@ public abstract class Transaction extends OperationBase {
transactionType = type; transactionType = type;
nodeReceiver = receiver; nodeReceiver = receiver;
signature = SignatureManager.signTransaction(this); signature = SignatureManager.signTransaction(this);
System.out.println(toString());
} }
public void endTransaction() { public void endTransaction() {

View File

@ -12,7 +12,7 @@ public class Product
private ProductState productState; private ProductState productState;
private ProductType productType; private ProductType productType;
private OperationBase currentOperation; private OperationBase currentOperation;
private MonetaryAmount money; private MonetaryAmount price;
private String name; private String name;
@ -26,7 +26,7 @@ public class Product
this.name = name; this.name = name;
this.productType = productType; this.productType = productType;
this.productState = ProductState.AVAILABLE; this.productState = ProductState.AVAILABLE;
this.money = Money.of(0, "USD"); this.price = Money.of(0, "USD");
} }
public Product(String name, ProductType productType, double m) public Product(String name, ProductType productType, double m)
@ -34,7 +34,7 @@ public class Product
this.name = name; this.name = name;
this.productType = productType; this.productType = productType;
this.productState = ProductState.AVAILABLE; this.productState = ProductState.AVAILABLE;
this.money = Money.of(m, "USD"); this.price = Money.of(m, "USD");
} }
/** /**
@ -48,7 +48,7 @@ public class Product
this.name = name; this.name = name;
this.productType = productType; this.productType = productType;
this.productState = productState; this.productState = productState;
this.money = Money.of(0, "USD"); this.price = Money.of(0, "USD");
} }
public Product(String name, ProductType productType, ProductState productState, double m) public Product(String name, ProductType productType, ProductState productState, double m)
@ -56,7 +56,7 @@ public class Product
this.name = name; this.name = name;
this.productType = productType; this.productType = productType;
this.productState = productState; this.productState = productState;
this.money = Money.of(m, "USD"); this.price = Money.of(m, "USD");
} }
public boolean tick() { public boolean tick() {
@ -155,7 +155,7 @@ public class Product
this.currentOperation = currentOperation; this.currentOperation = currentOperation;
} }
public MonetaryAmount getMoney() { return money; } public MonetaryAmount getPrice() { return price; }
public void setMoney(MonetaryAmount money) { this.money = money; } public void setPrice(MonetaryAmount price) { this.price = price; }
} }

View File

@ -3,6 +3,9 @@ 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.ProductType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType;
import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount;
public class Requirement { public class Requirement {
@ -10,13 +13,25 @@ public class Requirement {
private final TransactionType transactionType; private final TransactionType transactionType;
private final ProductType productType; private final ProductType productType;
private final String productName; private final String productName;
private final MonetaryAmount price;
private int TTL; private int TTL;
public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName) { public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName, double price) {
this.creator = creator; this.creator = creator;
this.transactionType = transactionType; this.transactionType = transactionType;
this.productType = productType; this.productType = productType;
this.productName = productName; this.productName = productName;
this.price = Money.of(price, "USD");
TTL = 3;
System.out.println(toString());
}
public Requirement(NodeBase creator, TransactionType transactionType, ProductType productType, String productName, MonetaryAmount price) {
this.creator = creator;
this.transactionType = transactionType;
this.productType = productType;
this.productName = productName;
this.price = price;
TTL = 3; TTL = 3;
System.out.println(toString()); System.out.println(toString());
} }
@ -41,6 +56,8 @@ public class Requirement {
return productName; return productName;
} }
public MonetaryAmount getPrice() { return price; }
public int getTTL() { public int getTTL() {
return TTL; return TTL;
} }
@ -50,7 +67,6 @@ public class Requirement {
return "Requirement{" + return "Requirement{" +
"creator=" + creator.getClass().getSimpleName() + "creator=" + creator.getClass().getSimpleName() +
", transactionType=" + transactionType + ", transactionType=" + transactionType +
", productType=" + productType +
", productName='" + productName + '\'' + ", productName='" + productName + '\'' +
", TTL=" + TTL + ", TTL=" + TTL +
'}'; '}';

View File

@ -9,16 +9,18 @@ public class SendRequirementStep extends ScenarioStep {
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;
public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName) { public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName, double pPrice) {
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;
} }
@Override @Override
void execute() { void execute() {
node.createRequirement(tType, pType, pName); node.createRequirement(tType, pType, pName, pPrice);
} }
} }

View File

@ -1,7 +1,8 @@
package cz.cvut.fel.sit.omo.foodchain.util; package cz.cvut.fel.sit.omo.foodchain.util;
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;
public interface ChannelObserver { public interface ChannelObserver {
void update(Requirement requirement); void update(Requirement requirement, ChannelBase channel);
} }