import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Graph implements DirectedGraph{
  private HashMap nodeMap = new HashMap();
  
  public void addEdge(Object fromNode, Object toNode, double weight) {
  	Node f = (Node) nodeMap.get(fromNode);
  	Node t = (Node) nodeMap.get(toNode);
  	f.succs.put(toNode, new Double(weight));
  	t.preds.put(fromNode, new Double(weight));
  }
  
  
  public void addNode(Object n) {
  	nodeMap.put(n, new Node(n));
  }
  
  
  public double getEdgeWeight(Object fromNode, Object toNode){
  	Node f = (Node) nodeMap.get(fromNode);
  	Double weight = (Double) f.succs.get(toNode);
  	return weight.doubleValue();
  }
  
  
  public Set getNodes() {
  	return new HashSet(nodeMap.keySet());
  }
  
  
  public Set getPredNodes(Object node) {
  	return new HashSet(((Node) nodeMap.get(node)).preds.keySet());
  }
  
  
  public Set getSuccNodes(Object node) {
  	return new HashSet(((Node) nodeMap.get(node)).succs.keySet());
  }
  
  
  public void removeEdge(Object fromNode, Object toNode) {
  	Node f = (Node) nodeMap.get(fromNode);
  	Node t = (Node) nodeMap.get(toNode);
  	f.succs.remove(toNode);
  	t.preds.remove(fromNode);
  }
  
  
  public void removeNode(Object node) {
  	Node n = (Node) nodeMap.get(node);
  	Iterator succIt = n.succs.keySet().iterator();
  	while (succIt.hasNext()) removeEdge(node, succIt.next());
  	nodeMap.remove(node);
  }
  
  //private classes
  private static class Node{
  	Object content;
  	HashMap preds = new HashMap(), succs=new HashMap();
  	
  	//constructor
  	Node(Object o) {
  		content = o;
  	}
  }// end of class Node
  
}// end of class Graph