package fucoin; import java.util.Collections; import java.util.Vector; import javax.swing.DefaultListModel; import fucoin.actions.FindWalletAction; import fucoin.actions.FindWalletResponseAction; import fucoin.actions.InvalidateAction; import fucoin.actions.InvokeExitAction; import fucoin.actions.InvokeFindWalletAction; import fucoin.actions.InvokePerformTransactionAction; import fucoin.actions.PerformTransactionAction; import fucoin.actions.StoreOrUpdateAction; import fucoin.actions.JoinAction; import fucoin.actions.JoinActionRespond; import fucoin.actions.InvokeStoreOrUpdateAction; import fucoin.actions.TransactionPerformedAction; import fucoin.actions.WaitForAnswersAction; import fucoin.actions.WaitForPerformTransactionAction; import fucoin.gui.IWalletGuiControle; import akka.actor.ActorPath; import akka.actor.ActorRef; import akka.actor.ActorSelection; import akka.actor.ActorSystem; import akka.actor.ActorSystemImpl; import akka.actor.Props; import akka.actor.UntypedActor; import akkateststuff.MyNodeCreator; import akkateststuff.Node; public class Wallet extends UntypedActor implements IWallet{ private ActorRef preknownNeighbour; private String address ; private int moneyAmount ; private Vector<WalletPointer> allKnownNeighbors = new Vector<WalletPointer>(); private Vector<Wallet> synchronizedNeighbors = new Vector<Wallet>(); public Wallet(String preknownNeighbour) { if(preknownNeighbour!=null){ this.preknownNeighbour=stringToActor(preknownNeighbour); } } @Override public Vector<WalletPointer> join() { Vector<WalletPointer> allKnownNeighbors = new Vector<WalletPointer>(); for(WalletPointer neighbors : allKnownNeighbors){ this.allKnownNeighbors.add(neighbors); gui.addKnownAddress(neighbors.address); } return allKnownNeighbors; } @Override public void storeOrUpdate(Wallet w) { if(!synchronizedNeighbors.contains(w)){ synchronizedNeighbors.add(w); }; } @Override public void invalidateWallet(Wallet w) { synchronizedNeighbors.remove(w); } @Override public void receiveTransaction(int moneyAmount) { addMoneyAmount(moneyAmount); } private Vector<WalletPointer> answers = new Vector<WalletPointer>(); @Override public Vector<WalletPointer> searchWallet(String adress) { for(WalletPointer neighbor : allKnownNeighbors){ if(!neighbor.address.equals(adress)){ ActorRef actor = stringToActor(neighbor.address); actor.tell(new FindWalletAction(adress), getSelf()); } } //unschoener workaround getSelf().tell(new WaitForAnswersAction(), getSelf()); return answers; } private boolean isAlive = false; private IWalletGuiControle gui; void performTransaction ( WalletPointer w, int amount ){ ActorRef destActor = stringToActor(w.address); destActor.tell(new PerformTransactionAction(w,amount), getSelf()); getSelf().tell(new WaitForPerformTransactionAction(w,amount), getSelf()); //.tell(new Perform<transaction>, sender); } @Override public void onReceive(Object action) throws Exception { log(""+action); boolean contains = false; String senderName = actorToString(getSender()); String selfName = actorToString(getSelf()); WalletPointer selfWP = null; for(WalletPointer wp : this.allKnownNeighbors){ if(wp.address.equals(senderName)){ contains = true; log("knows allready "+senderName); } if(wp.address.equals(selfName)){ selfWP = wp; } } if(!contains){ this.allKnownNeighbors.add(new WalletPointer(senderName)); gui.addKnownAddress(senderName); } if(selfWP!=null){ this.allKnownNeighbors.remove(selfWP); } if(action instanceof JoinAction){ JoinActionRespond joinaction = new JoinActionRespond(); joinaction.setKnownNeighbors(join()); getSender().tell(joinaction, getSelf()); }else if(action instanceof JoinActionRespond){ JoinActionRespond joinaction = (JoinActionRespond) action; //allKnownNeighbors.addAll(joinaction.getAllKnownNeighbors()); for(WalletPointer neighbor:joinaction.getAllKnownNeighbors()){ gui.addKnownAddress(neighbor.address); allKnownNeighbors.add(neighbor); } log(actorToString(getSelf())+"ah there are new neighbours"+joinaction.getAllKnownNeighbors()); log("now i know these "+allKnownNeighbors); getSelf().tell(new InvokeFindWalletAction(), getSelf()); }else if(action instanceof StoreOrUpdateAction){ StoreOrUpdateAction storeOrUpdateAction = (StoreOrUpdateAction) action; storeOrUpdate(storeOrUpdateAction.getWallet()); }else if(action instanceof InvokeStoreOrUpdateAction){ StoreOrUpdateAction storeOrUpdateAction = new StoreOrUpdateAction(); storeOrUpdateAction.setWallet(this); for(WalletPointer neighbor : allKnownNeighbors){ stringToActor(neighbor.address).tell(storeOrUpdateAction, getSelf()); } }else if(action instanceof InvokeExitAction){ getContext().stop(getSelf()); }else if(action instanceof InvokeFindWalletAction){ InvokeFindWalletAction invokeFindWalletAction = (InvokeFindWalletAction) action; Vector<WalletPointer> wallets = searchWallet(selfName); }else if(action instanceof FindWalletAction){ FindWalletAction findWalletAction = (FindWalletAction) action; for(Wallet s : synchronizedNeighbors){ log(findWalletAction.getSearchedName()); log(s.address); if(s.address.equals(findWalletAction.getSearchedName())){ log(""+s.moneyAmount); getSender().tell(new FindWalletResponseAction(selfName,s.moneyAmount), getSelf()); } } }else if(action instanceof FindWalletResponseAction){ FindWalletResponseAction findWalletResponseAction = (FindWalletResponseAction) action; answers.add(new WalletPointer(findWalletResponseAction.getFoundneighbour())); gui.addKnownAddress(findWalletResponseAction.getFoundneighbour()); moneyAmount=findWalletResponseAction.getMoneyAmount(); gui.setAmount(moneyAmount); }else if(action instanceof WaitForAnswersAction){ log(""+answers); for(WalletPointer answer : answers){ stringToActor(answer.address).tell(new InvalidateAction(actorToString(getSelf())),getSelf()); } }else if(action instanceof InvalidateAction){ InvalidateAction invalidateAction = (InvalidateAction) action; Wallet delWallet = null; for(Wallet w : synchronizedNeighbors){ if(w.address.equals(invalidateAction.getInvalidWallet())){ delWallet=w; } } log(""+synchronizedNeighbors); invalidateWallet(delWallet); log(""+synchronizedNeighbors); }else if(action instanceof InvokePerformTransactionAction){ InvokePerformTransactionAction invokePerformTransactionAction = (InvokePerformTransactionAction) action; performTransaction(invokePerformTransactionAction.getWalletPointer(),invokePerformTransactionAction.getAmount()); addMoneyAmount(-invokePerformTransactionAction.getAmount()); }else if(action instanceof PerformTransactionAction){ PerformTransactionAction performTransactionAction = (PerformTransactionAction) action; if(performTransactionAction.getWalletPointer().address.equals(actorToString(getSelf()))){ getSender().tell(new TransactionPerformedAction(), getSelf()); receiveTransaction(performTransactionAction.getAmount()); }else{ for(Wallet syncwallet : synchronizedNeighbors){ if(syncwallet.address.equals(performTransactionAction.getWalletPointer().address)){ syncwallet.addMoneyAmount(performTransactionAction.getAmount()); } } } }else if(action instanceof WaitForPerformTransactionAction){ WaitForPerformTransactionAction waitForPerformTransactionAction = (WaitForPerformTransactionAction) action; if(!isAlive){ for(Wallet neighbor : synchronizedNeighbors){ if(neighbor.address.equals(waitForPerformTransactionAction.getWalletPointer().address)){ neighbor.addMoneyAmount(waitForPerformTransactionAction.getAmount()); log("have to update "+neighbor.address+"amount because he is offline"); } } } }else if(action instanceof TransactionPerformedAction){ isAlive=true; } } @Override public void preStart() throws Exception { super.preStart(); log("prestart"+preknownNeighbour); this.address=actorToString(getSelf()); gui.setAddress(address); addMoneyAmount(100); if(preknownNeighbour!=null){ String p = actorToString(preknownNeighbour); allKnownNeighbors.add(new WalletPointer(p)); gui.addKnownAddress(p); preknownNeighbour.tell(new JoinAction(), getSelf()); } } private void log(String string) { String logMsg = actorToString(getSender()).replace("akka://MySystem/user/", "")+" said "+ string+" to me("+actorToString(getSelf()).replace("akka://MySystem/user/", "")+")"; System.out.println(logMsg); gui.addLogMsg(string); } public static Props props(String preknownNeighbour, String walletCounter) { return Props.create(new WalletCreator(preknownNeighbour,walletCounter)); } public static String actorToString(ActorRef actor){ return actor.path().toStringWithAddress(actor.path().address()); } public static ActorRef stringToActor(String path){ return Main.getSingleton().getSystem().actorFor(path); } public void addMoneyAmount(int moneyAmount) { this.moneyAmount += moneyAmount; this.gui.setAmount(this.moneyAmount); } @Override public String toString() { return address+"'s wallet"; } public void invokePerformTransaction(WalletPointer walletPointer, int i) { getSelf().tell(new InvokePerformTransactionAction(walletPointer, i),getSelf()); } @Override public void send(String address, int amount) { invokePerformTransaction(new WalletPointer(address), amount); } public void store() { getSelf().tell(new InvokeStoreOrUpdateAction(), getSelf()); } public void leave() { store(); getSelf().tell(new InvokeExitAction(), getSelf()); } public void setGui(IWalletGuiControle gui) { this.gui=gui; } }