Skip to content
Snippets Groups Projects
Wallet.java 9.45 KiB
Newer Older
Michael Kmoch's avatar
Michael Kmoch committed
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 : this.allKnownNeighbors){
			allKnownNeighbors.add(neighbors);
Michael Kmoch's avatar
Michael Kmoch committed
		}
		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);
		String senderName = actorToString(getSender());
		String selfName = actorToString(getSelf());		
		
Michael Kmoch's avatar
Michael Kmoch committed
		if(action instanceof JoinAction){
			JoinAction joinAction = (JoinAction) action;
			JoinActionRespond joinactionrespond = new JoinActionRespond();
			joinactionrespond.setKnownNeighbors(join());
			addKnownaddress(joinAction.getNewMember());
			
			getSender().tell(joinactionrespond, getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(action instanceof JoinActionRespond){
			JoinActionRespond joinaction = (JoinActionRespond) action;
Michael Kmoch's avatar
Michael Kmoch committed
			//allKnownNeighbors.addAll(joinaction.getAllKnownNeighbors());
			for(WalletPointer neighbor:joinaction.getAllKnownNeighbors()){
Michael Kmoch's avatar
Michael Kmoch committed
			}
			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());
				}
			}
Michael Kmoch's avatar
Michael Kmoch committed
		}else if(action instanceof FindWalletResponseAction){
			FindWalletResponseAction findWalletResponseAction = (FindWalletResponseAction) action;
			answers.add(new WalletPointer(findWalletResponseAction.getFoundneighbour()));
Michael Kmoch's avatar
Michael Kmoch committed
			moneyAmount=findWalletResponseAction.getMoneyAmount();
			gui.setAmount(moneyAmount);
		}else if(action instanceof WaitForAnswersAction){
			log(""+answers);
			for(WalletPointer answer : answers){
Michael Kmoch's avatar
Michael Kmoch committed
				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;
		}
	}

	private void addKnownaddress(WalletPointer senderPointer) {
		if(!allKnownNeighbors.contains(senderPointer)
				&&getSender().compareTo(getSelf())!=0){
			
		
			this.allKnownNeighbors.add(senderPointer);
			gui.addKnownAddress(senderPointer.address);
		}
	}
Michael Kmoch's avatar
Michael Kmoch committed
	
	@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);
			addKnownaddress(new WalletPointer(p));
			preknownNeighbour.tell(new JoinAction(new WalletPointer(address)), getSelf());
Michael Kmoch's avatar
Michael Kmoch committed
		}
	}
	
	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;
	}

}