implement shortest path app and fix typos

Change-Id: I2bf63b092eefd8bcd4dc757446181d64638d127d
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java b/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java
index 7b18c34..d754fa1 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ConstrainedFlow.java
@@ -71,7 +71,8 @@
 					path.add(0, upstreamLink);
 					sw = upstreamLink.getSrcPort().getSwitch();
 				}
-				return super.calcPath();
+				state = FlowState.PathCalculated;
+				return true;
 			}
 			for (Link link: sw.getAdjLinks()) {
 				Switch reachedSwitch = link.getDstPort().getSwitch();
@@ -82,7 +83,13 @@
 				upstreamLinks.put(reachedSwitch, link);
 			}
 		}
-		state = FlowState.PathCalcurationFailed;
+		state = FlowState.PathCalculationFailed;
 		return false;
 	}
+
+	@Override
+	void calcFlowEntries() {
+		// TODO Auto-generated method stub
+		// not implemented yet
+	}
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java b/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java
index 071d89f..826447a 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/Flow.java
@@ -1,6 +1,5 @@
 package net.onrc.onos.ofcontroller.app;
 
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -8,19 +7,19 @@
  * This code is valid for the architectural study purpose only.
  * @author Toshio Koide (t-koide@onlab.us)
  */
-public class Flow extends NetworkGraphEntity {
+public abstract class Flow extends NetworkGraphEntity {
 	public enum FlowState {
 		Created,
 		Configuring,
 		Configured,
-		PathCalcurating,
-		PathCalcurated,
-		PathCalcurationFailed,
+		PathCalculating,
+		PathCalculated,
+		PathCalculationFailed,
 		PathInstalled,
-		PathInstlationFailed,
-		FlowEntriesCalcurating,
-		FlowEntriesCalcurated,
-		FlowEntriesCalcuratinFailed,
+		PathInstallationFailed,
+		FlowEntriesCalculating,
+		FlowEntriesCalculated,
+		FlowEntriesCalculationFailed,
 		FlowEntriesInstalling,
 		FlowEntriesInstalled,
 		FlowEntriesInstallationFailed,
@@ -43,6 +42,11 @@
 	// flow entries
 	protected Map<SwitchPort, FlowEntry> flowEntries = null;
 
+	// abstract methods
+	abstract boolean calcPath();
+	abstract void calcFlowEntries();
+	
+
 	public Flow(NetworkGraph graph, String name, SwitchPort srcPort, SwitchPort dstPort) {
 		super(graph);
 		this.srcPort = srcPort;
@@ -57,12 +61,7 @@
 	boolean isState(FlowState state) {
 		return this.state == state;
 	}
-	
-	boolean calcPath() {
-		state = FlowState.PathCalcurated;
-		return true;
-	}
-	
+		
 	public Path getPath() {
 		return path;
 	}
@@ -83,15 +82,16 @@
 		return true;
 	}
 
-	public void calcFlowEntries() {
-		flowEntries = new HashMap<SwitchPort, FlowEntry>();
-		state = FlowState.FlowEntriesCalcurated;
-	}
-	
+	/**
+	 * not implemented yet
+	 */
 	public void installFlowEntries() {
 		state = FlowState.FlowEntriesInstalled;
 	}
 	
+	/**
+	 * not implemented yet
+	 */
 	public void uninstallFlowEntries() {
 		state = FlowState.FlowEntriesRemoved;
 	}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java b/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java
deleted file mode 100644
index c900d53..0000000
--- a/src/test/java/net/onrc/onos/ofcontroller/app/NamedNode.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.onrc.onos.ofcontroller.app;
-
-public class NamedNode {
-	protected String name;
-	protected NetworkGraph graph;
-
-	public NamedNode(NetworkGraph graph, String name) {
-		this.graph = graph;
-		this.name = name;
-	}
-
-	public String getName() {
-		return name;
-	}
-	
-	public NetworkGraph getNetworkGraph() {
-		return graph;
-	}
-}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java
index 4789c6e..d8723d2 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPath.java
@@ -1,9 +1,77 @@
 package net.onrc.onos.ofcontroller.app;
 
 /**
- * @author Toshio Koide (t-koide@onlab.us)
  * This code is valid for the architectural study purpose only.
+ * @author Toshio Koide (t-koide@onlab.us)
  */
 public class ShortestPath implements BaseApplication {
+	NetworkGraph graph;
+	
+	/**
+	 * Instantiate SimpleTrafficEngineering application
+	 * 
+	 * 1. store NetworkGraph as a cache
+	 * 
+	 * @param graph
+	 */
+	public ShortestPath(NetworkGraph graph) {
+		this.graph = graph;
+	}
 
+	/**
+	 * Allocate specified bandwidth between specified switch ports
+	 * 
+	 * @param srcPort
+	 * @param dstPort
+	 * @param bandWidth
+	 * @return
+	 */
+	public ShortestPathFlow install(SwitchPort srcPort, SwitchPort dstPort) {
+		ShortestPathFlow flow = new ShortestPathFlow(this.graph, null, srcPort, dstPort);
+
+		// 1. store Flow object to NetworkGraph
+		if (!graph.addFlow(flow)) {
+			return flow;
+		}
+
+		// 2. calculate path from srcPort to dstPort under condition of bandWidth
+		if (!flow.calcPath()) {
+			return flow;
+		}
+		
+		// debug (show path)
+		System.out.println("path was calculated:");
+		System.out.println("[Flow] " + flow.toString());
+
+		// 3. install path in NetworkGraph
+		if (!flow.installPath()) {
+			return flow;
+		}
+
+		// debug (show path)
+		System.out.println("path was installed.");
+		System.out.println("[Flow] " + flow.toString());
+
+		// (then, flow entries are created and installed from stored path information in the Flow object by another processes)
+		return flow;
+	}
+
+	/**
+	 * Release specified Flow object
+	 * 
+	 * @param flow
+	 */
+	public void release(ShortestPathFlow flow) {
+		// 1. release bandwidth (remove property of links) in NetworkGraph
+		flow.uninstallPath();
+
+		// debug (show path)
+		System.out.println("path was released.");
+		System.out.println("[Flow] " + flow.toString());
+		
+		// 2. deactivate Flow object
+
+		// (then, flow entries are removed by another processes)
+		// (retain flow object in NetworkGraph as a removed flow object)
+	}
 }
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathFlow.java b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathFlow.java
new file mode 100644
index 0000000..6a179a1
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathFlow.java
@@ -0,0 +1,58 @@
+package net.onrc.onos.ofcontroller.app;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+public class ShortestPathFlow extends Flow {
+
+	public ShortestPathFlow(NetworkGraph graph, String name, SwitchPort srcPort, SwitchPort dstPort) {
+		super(graph, name, srcPort, dstPort);
+		// TODO Auto-generated constructor stub
+	}
+
+	@Override
+	boolean calcPath() {
+		LinkedList<Switch> switchQueue = new LinkedList<Switch>();
+		HashSet<Switch> switchSearched = new HashSet<Switch>();
+		HashMap<Switch, Link> upstreamLinks = new HashMap<Switch, Link>();
+		
+		Switch srcSwitch = srcPort.getSwitch();
+		Switch dstSwitch = dstPort.getSwitch();
+		
+		switchQueue.add(srcSwitch);
+		switchSearched.add(srcSwitch);
+
+		while (!switchQueue.isEmpty()) {
+			Switch sw = switchQueue.poll();
+			if (sw == dstSwitch) {
+				// path has been searched.
+				// store path into itself
+				path.clear();
+				while (sw != srcSwitch) {
+					Link upstreamLink = upstreamLinks.get(sw);
+					path.add(0, upstreamLink);
+					sw = upstreamLink.getSrcPort().getSwitch();
+				}
+				state = FlowState.PathCalculated;
+				return true;
+			}
+			for (Link link: sw.getAdjLinks()) {
+				Switch reachedSwitch = link.getDstPort().getSwitch();
+				if (switchSearched.contains(reachedSwitch)) continue;
+				switchQueue.add(reachedSwitch);
+				switchSearched.add(reachedSwitch);
+				upstreamLinks.put(reachedSwitch, link);
+			}
+		}
+		state = FlowState.PathCalculationFailed;
+		return false;
+	}
+
+	@Override
+	void calcFlowEntries() {
+		// TODO Auto-generated method stub
+		// not implemented yet
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java
index 4bf1d4c..011a49f 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/app/ShortestPathTest.java
@@ -1,7 +1,10 @@
 package net.onrc.onos.ofcontroller.app;
 
 import static org.junit.Assert.*;
+import net.onrc.onos.ofcontroller.app.Flow.FlowState;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 /**
@@ -9,10 +12,65 @@
  * @author Toshio Koide (t-koide@onlab.us)
  */
 public class ShortestPathTest {
+	NetworkGraph g;
 
-	@Test
-	public void test() {
-		fail("Not yet implemented");
+	@Before
+	public void setUp() {
+		g = new NetworkGraph();
+
+		// add 10 switches (24 ports switch)
+		for (Integer i=1; i<10; i++) {
+			Switch sw = g.addSwitch("v" + i.toString());
+			for (Integer j=1; j<=24; j++) {
+				sw.addPort(j);
+			}
+		}
+
+		// add loop path
+		g.addBidirectionalLinks("v1", 1, "v2", 2);
+		g.addBidirectionalLinks("v2", 1, "v3", 2);
+		g.addBidirectionalLinks("v3", 1, "v4", 2);
+		g.addBidirectionalLinks("v4", 1, "v5", 2);
+		g.addBidirectionalLinks("v5", 1, "v6", 2);
+		g.addBidirectionalLinks("v6", 1, "v7", 2);
+		g.addBidirectionalLinks("v7", 1, "v8", 2);
+		g.addBidirectionalLinks("v8", 1, "v9", 2);
+		g.addBidirectionalLinks("v9", 1, "v1", 2);
+
+		// add other links
+		g.addBidirectionalLinks("v1", 3, "v2", 3);
+		g.addBidirectionalLinks("v2", 4, "v3", 4);
+		g.addBidirectionalLinks("v4", 5, "v3", 5);
+		g.addBidirectionalLinks("v5", 6, "v6", 6);
+		g.addBidirectionalLinks("v7", 7, "v6", 7);
+		g.addBidirectionalLinks("v8", 8, "v1", 8);
+		g.addBidirectionalLinks("v9", 9, "v1", 9);
+		
+		// set capacity of all links to 1000Mbps
+		for (Link link: g.getLinks()) {
+			link.setCapacity(1000.0);
+		}
 	}
 
+	@After
+	public void tearDown() {
+	}
+
+	@Test
+	public void useCase1() {
+		// load TE algorithm
+		ShortestPath spf = new ShortestPath(g);
+
+		// get edge ports
+		SwitchPort srcPort = g.getSwitch("v1").getPort(20);
+		SwitchPort dstPort = g.getSwitch("v6").getPort(20);
+		
+		// setup path
+		ShortestPathFlow flow = spf.install(srcPort, dstPort);
+		assertTrue(flow.isState(FlowState.PathInstalled));
+
+		// release flow
+		spf.release(flow);
+		assertTrue(flow.isState(FlowState.PathRemoved));
+	}
 }