-
Luca Keidel authoredLuca Keidel authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
WalletImpl.java 7.28 KiB
package fucoin.wallet;
import akka.actor.ActorRef;
import akka.actor.Props;
import fucoin.actions.ClientAction;
import fucoin.actions.join.ActionJoin;
import fucoin.actions.join.ActionJoinAnswer;
import fucoin.actions.join.ActionTellSupervisor;
import fucoin.actions.join.ServerActionJoin;
import fucoin.actions.persist.ActionInvokeLeave;
import fucoin.actions.persist.ActionInvokeRevive;
import fucoin.actions.transaction.ActionGetAmountAnswer;
import fucoin.actions.transaction.ActionInvokeSentMoney;
import fucoin.gui.WalletGuiControl;
import scala.concurrent.Future;
import static akka.dispatch.Futures.future;
import java.util.concurrent.ConcurrentLinkedQueue;
public class WalletImpl extends AbstractWallet {
private ActorRef preKnownNeighbour;
private ActorRef remoteSuperVisorActor;
private transient WalletGuiControl gui;
private String preKnownNeighbourName;
private boolean isActive;
private ConcurrentLinkedQueue<ActorRef> deferedSupervisorReceivers = new ConcurrentLinkedQueue<>();
public WalletImpl(String name) {
super(name);
}
public WalletImpl(ActorRef preKnownNeighbour, String walletName) {
super(walletName);
if (preKnownNeighbour != null) {
this.preKnownNeighbourName = preKnownNeighbour.path().name();
this.preKnownNeighbour = preKnownNeighbour;
}
}
public static Props props(ActorRef preKnownNeighbour, String walletName, boolean createGUI) {
return Props.create(new WalletCreator(preKnownNeighbour, walletName, createGUI));
}
/**
* Adds amount to the current amount of FUCs in the wallet.
*
* @param amount value to add to current account.
*/
public void addAmount(int amount) {
setAmount(this.getAmount() + amount);
addLogMsg(" My amount is now " + this.getAmount());
}
@Override
public void leave() {
getSelf().tell(new ActionInvokeLeave(), getSelf());
}
@Override
public void onReceive(Object message) {
addLogMsg(getSender().path().name() + " invokes " + getSelf().path().name() + " to do " + message.getClass().getSimpleName());
if (message instanceof ActionInvokeRevive) {
((ActionInvokeRevive) message).doAction(this);
}
if (!isActive && !(message instanceof ActionInvokeRevive)) return;
if (message instanceof ClientAction) {
((ClientAction) message).doAction(this);
}
}
@Override
public void preStart() throws Exception {
isActive = true;
if (gui != null) {
String address = getAddress();
gui.setAddress(address);
if (address.contains("Remote@")) {
gui.setRemote();
}
}
if (preKnownNeighbour != null) {
addKnownNeighbor(preKnownNeighbourName, preKnownNeighbour);
preKnownNeighbour.tell(new ActionJoin(), getSelf());
ActionJoinAnswer aja = new ActionJoinAnswer();
aja.someNeighbors.putAll(getKnownNeighbors());
aja.someNeighbors.put(name, getSelf());
preKnownNeighbour.tell(aja, getSelf());
if (this.getRemoteSuperVisorActor() != null) {
preKnownNeighbour.tell(new ActionTellSupervisor(this.getRemoteSuperVisorActor()), self());
}
}
}
@Override
public void postStop() throws Exception {
leave();
super.postStop();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof WalletImpl) {
WalletImpl wobj = (WalletImpl) obj;
return amount == wobj.getAmount() && name.equals(wobj.getName());
}
return false;
}
/**
* Returns the amount of FUCs currently in the wallet.
*
* @return
*/
public int getAmount() {
return amount;
}
/**
* Sets the amount of FUCs in the wallet to amount.
*
* @param amount New amount of the wallet
*/
public void setAmount(int amount) {
this.amount = amount;
if (remoteSuperVisorActor != null) {
remoteSuperVisorActor.tell(new ActionGetAmountAnswer(getAddress(), getName(), amount), getSelf());
}
if (gui != null) {
gui.setAmount(this.amount);
}
}
@Override
public ActorRef getPreKnownNeighbour() {
return preKnownNeighbour;
}
public void setPreKnownNeighbour(ActorRef preKnownNeighbour) {
this.preKnownNeighbour = preKnownNeighbour;
}
@Override
public ActorRef getRemoteSuperVisorActor() {
return remoteSuperVisorActor;
}
public Future<ActorRef> resolveSuperVisorActor() {
// TODO: this should return only, if getRemoteSuperVisorActor() != null
return future(() -> getRemoteSuperVisorActor(), context().system().dispatcher());
}
@Override
public void setRemoteSuperVisorActor(ActorRef remoteSuperVisorActor) {
if (this.remoteSuperVisorActor == null) {
this.remoteSuperVisorActor = remoteSuperVisorActor;
this.remoteSuperVisorActor.tell(new ServerActionJoin(getName()), getSelf());
this.tellDeferedSuperVisorReceivers(remoteSuperVisorActor);
}
}
@Override
public void deferSendOfSuperVisorActor(ActorRef destinationWallet) {
deferedSupervisorReceivers.add(destinationWallet);
}
protected void tellDeferedSuperVisorReceivers(ActorRef supervisor) {
while (deferedSupervisorReceivers.size() > 0) {
ActorRef receiver = deferedSupervisorReceivers.poll();
if (receiver != null) {
receiver.tell(new ActionTellSupervisor(supervisor), self());
}
}
}
public WalletGuiControl getGui() {
return gui;
}
public void setGui(WalletGuiControl gui) {
this.gui = gui;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}
@Override
public boolean addKnownNeighbor(String key, ActorRef value) {
addLogMsg(key + " is newNeighbor of " + name + "?" + !getKnownNeighbors().containsKey(key));
if (getKnownNeighbors().containsKey(key) || key.equals(name)) {
return false;
}
boolean newNeighbor = super.addKnownNeighbor(key, value);
if (gui != null && newNeighbor) {
gui.addKnownAddress(key);
}
return newNeighbor;
}
public void send(String address, int amount) {
send(address, amount, null);
}
@Override
public void send(String address, int amount, ActorRef observer) {
getSelf().tell(new ActionInvokeSentMoney(address, amount, observer), getSelf());
}
@Override
public void addLogMsg(String message) {
if (gui != null) {
gui.addLogMsg(message);
} else {
System.out.println(message);
}
}
@Override
public void addTransactionLogMessageSuccess(String message) {
if (gui != null) {
gui.addTransactionLogMessageSuccess(message);
} else {
System.out.println(message);
}
}
@Override
public void addTransactionLogMessageFail(String message) {
if (gui != null) {
gui.addTransactionLogMessageFail(message);
} else {
System.out.println(message);
}
}
}