Change PathIntent class to be self-contained class

Change-Id: I67e768bd6be8430bb83b48963cf3c7cc4c592790
diff --git a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
index 758494f..2fd5013 100644
--- a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
+++ b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
@@ -27,7 +27,6 @@
 
 	public ConstrainedBFSTree(Switch rootSwitch) {
 		this.rootSwitch = rootSwitch;
-		this.intents = new PathIntents();
 		calcTree();
 	}
 
@@ -46,7 +45,7 @@
 			for (Link link: sw.getOutgoingLinks()) {
 				Switch reachedSwitch = link.getDestinationPort().getSwitch();
 				if (switchSearched.contains(reachedSwitch)) continue;
-				if (bandwidth > 0.0 && intents.getAvailableBandwidth(link) < bandwidth) continue;
+				if (intents != null && intents.getAvailableBandwidth(link) < bandwidth) continue;
 				switchQueue.add(reachedSwitch);
 				switchSearched.add(reachedSwitch);
 				upstreamLinks.put(reachedSwitch, link);
diff --git a/src/main/java/net/onrc/onos/intent/ConstrainedShortestPathIntent.java b/src/main/java/net/onrc/onos/intent/ConstrainedShortestPathIntent.java
index 879d92f..6a6aab0 100644
--- a/src/main/java/net/onrc/onos/intent/ConstrainedShortestPathIntent.java
+++ b/src/main/java/net/onrc/onos/intent/ConstrainedShortestPathIntent.java
@@ -9,10 +9,9 @@
 	/**
 	 * Default constructor for Kryo deserialization
 	 */
-	@Deprecated
-	public ConstrainedShortestPathIntent() {
+	protected ConstrainedShortestPathIntent() {
 	}
-	
+
 	public ConstrainedShortestPathIntent(String id,
 			long srcSwitch, long srcPort, long srcMac,
 			long dstSwitch, long dstPort, long dstMac,
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index 921d430..a31cbde 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -13,8 +13,7 @@
 	/**
 	 * Default constructor for Kryo deserialization
 	 */
-	@Deprecated
-	public Intent() {
+	protected Intent() {
 	}
 
 	public Intent(String id) {
diff --git a/src/main/java/net/onrc/onos/intent/PathIntent.java b/src/main/java/net/onrc/onos/intent/PathIntent.java
index 4d1e71e..4ef4cf0 100644
--- a/src/main/java/net/onrc/onos/intent/PathIntent.java
+++ b/src/main/java/net/onrc/onos/intent/PathIntent.java
@@ -1,15 +1,24 @@
 package net.onrc.onos.intent;
 
+import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
 import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.networkgraph.Port;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
 
 /**
  * @author Toshio Koide (t-koide@onlab.us)
  */
 public class PathIntent extends Intent {
-	protected Path path;
+	protected long pathData[];
 	protected double bandwidth;
 	protected Intent parentIntent;
-	protected int id;
+
+	/**
+	 * Default constructor for Kryo deserialization
+	 */
+	protected PathIntent() {
+	}
 
 	/**
 	 * 
@@ -22,16 +31,44 @@
 	 */
 	public PathIntent(String id, Path path, double bandwidth, Intent parentIntent) {
 		super(id);
-		this.path = path;
+		pathData = new long[path.size() * 4];
+		for (int i=0; i<path.size(); i++) {
+			Link link = path.get(i);
+			this.pathData[i*4] = link.getSourceSwitch().getDpid();
+			this.pathData[i*4+1] = link.getSourcePort().getNumber();
+			this.pathData[i*4+2] = link.getDestinationSwitch().getDpid();
+			this.pathData[i*4+3] = link.getDestinationPort().getNumber();
+		}
 		this.bandwidth = bandwidth;
 		this.parentIntent = parentIntent;
 	}
 
-	public Double getBandwidth() {
+	public double getBandwidth() {
 		return bandwidth;
 	}
 
-	public Path getPath() {
+	public long[] getPathData() {
+		return pathData;
+	}
+
+	/**
+	 * Get Path object.
+	 * @param graph
+	 * @return path object. If there is no path in the specified graph, returns null.
+	 */
+	public Path getPath(NetworkGraph graph) {
+		Path path = new Path();
+		Switch srcSwitch;
+		Port srcPort;
+		Link link;
+		for (int i=0; i<pathData.length; i+=4) {
+			if ((srcSwitch = graph.getSwitch(pathData[i])) == null) return null;
+			if ((srcPort = srcSwitch.getPort(pathData[i+1])) == null) return null;
+			if ((link = srcPort.getOutgoingLink()) == null) return null;
+			if (link.getDestinationSwitch().getDpid() != pathData[i+2]) return null;
+			if (link.getDestinationPort().getNumber() != pathData[i+3]) return null;
+			path.add(link);
+		}
 		return path;
 	}
 
diff --git a/src/main/java/net/onrc/onos/intent/PathIntents.java b/src/main/java/net/onrc/onos/intent/PathIntents.java
index 9371fd5..8d712e3 100644
--- a/src/main/java/net/onrc/onos/intent/PathIntents.java
+++ b/src/main/java/net/onrc/onos/intent/PathIntents.java
@@ -7,6 +7,7 @@
 import java.util.LinkedList;
 
 import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
 
 /**
  * @author Toshio Koide (t-koide@onlab.us)
@@ -14,10 +15,15 @@
 public class PathIntents {
 	protected LinkedList<PathIntent> intents = new LinkedList<PathIntent>();
 	protected HashMap<Link, HashSet<PathIntent>> linkToIntents = new HashMap<Link, HashSet<PathIntent>>();
+	protected NetworkGraph graph;
+
+	public PathIntents(NetworkGraph graph) {
+		this.graph = graph;
+	}
 
 	public void addIntent(PathIntent intent) {
 		intents.add(intent);
-		for (Link link: intent.getPath()) {
+		for (Link link: intent.getPath(graph)) {
 			HashSet<PathIntent> value = linkToIntents.get(link);
 			if (value == null) {
 				value = new HashSet<PathIntent>();
@@ -26,10 +32,10 @@
 			value.add(intent);
 		}
 	}
-	
+
 	public void removeIntent(PathIntent intent) {
 		intents.remove(intent);
-		for (Link link: intent.getPath()) {
+		for (Link link: intent.getPath(graph)) {
 			HashSet<PathIntent> value = linkToIntents.get(link);
 			value.remove(intent);
 		}
diff --git a/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java b/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
index 2677942..4b324df 100644
--- a/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
+++ b/src/main/java/net/onrc/onos/intent/ShortestPathIntent.java
@@ -17,8 +17,7 @@
 	/**
 	 * Default constructor for Kryo deserialization
 	 */
-	@Deprecated
-	public ShortestPathIntent() {
+	protected ShortestPathIntent() {
 	}
 
 	public ShortestPathIntent(String id,
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
index 8d9cc87..0a171b3 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -19,10 +19,11 @@
 public class PathCalcRuntime {
 	NetworkGraph graph;
 	HashSet<Intent> inputIntents = new HashSet<Intent>();
-	PathIntents outputIntents = new PathIntents();
+	PathIntents outputIntents = null;
 
 	public PathCalcRuntime(NetworkGraph g) {
 		this.graph = g;
+		outputIntents = new PathIntents(g);
 	}
 
 	public Collection<Intent> getInputIntents() {
@@ -39,7 +40,7 @@
 	}
 
 	protected PathIntents calcPathIntents(Collection<Intent> originalIntents) {
-		PathIntents pathIntents = new PathIntents();
+		PathIntents pathIntents = new PathIntents(graph);
 
 		for (Intent intent: originalIntents) {
 			if (!(intent instanceof ShortestPathIntent)) {
diff --git a/src/test/java/net/onrc/onos/intent/PathIntentTest.java b/src/test/java/net/onrc/onos/intent/PathIntentTest.java
new file mode 100644
index 0000000..3161cca
--- /dev/null
+++ b/src/test/java/net/onrc/onos/intent/PathIntentTest.java
@@ -0,0 +1,89 @@
+package net.onrc.onos.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+public class PathIntentTest {
+	NetworkGraph g;
+
+	@Before
+	public void setUp() throws Exception {
+		MockNetworkGraph graph = new MockNetworkGraph();
+		graph.createSampleTopology();
+		g = graph;
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	@Test
+	public void test() {
+		Kryo kryo = new Kryo();
+		Output output = new Output(1024);
+
+		ConstrainedShortestPathIntent cspIntent1 =
+				new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+
+		Path path = new Path();
+		path.add(g.getSwitch(1L).getPort(1L).getOutgoingLink());
+		path.add(g.getSwitch(2L).getPort(1L).getOutgoingLink());
+		path.add(g.getSwitch(3L).getPort(1L).getOutgoingLink());
+
+		PathIntent pathIntent1 = new PathIntent("11", path, 123.45, cspIntent1);
+
+		kryo.writeObject(output, pathIntent1);
+		output.close();
+
+		Input input = new Input(output.toBytes());
+
+		// create pathIntent from bytes
+
+		PathIntent pathIntent2 =
+				kryo.readObject(input, PathIntent.class);
+		input.close();
+
+		// check
+		
+		assertEquals("11", pathIntent2.getId());
+		Path path2 = pathIntent2.getPath(g);
+
+		assertEquals(Long.valueOf(1L), path2.get(0).getSourceSwitch().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(0).getSourcePort().getNumber());
+		assertEquals(Long.valueOf(2L), path2.get(0).getDestinationSwitch().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(0).getDestinationPort().getNumber());
+
+		assertEquals(Long.valueOf(2L), path2.get(1).getSourceSwitch().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(1).getSourcePort().getNumber());
+		assertEquals(Long.valueOf(3L), path2.get(1).getDestinationSwitch().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(1).getDestinationPort().getNumber());
+
+		assertEquals(Long.valueOf(3L), path2.get(2).getSourceSwitch().getDpid());
+		assertEquals(Long.valueOf(1L), path2.get(2).getSourcePort().getNumber());
+		assertEquals(Long.valueOf(4L), path2.get(2).getDestinationSwitch().getDpid());
+		assertEquals(Long.valueOf(2L), path2.get(2).getDestinationPort().getNumber());
+
+		assertEquals(123.45, pathIntent2.getBandwidth(), 0.0);
+
+		ConstrainedShortestPathIntent cspIntent2 = 
+				(ConstrainedShortestPathIntent) pathIntent2.getParentIntent();
+		
+		assertEquals("1", cspIntent2.getId());
+		assertEquals(2L, cspIntent2.getSrcSwitchDpid());
+		assertEquals(3L, cspIntent2.getSrcPortNumber());
+		assertEquals(4L, cspIntent2.getSrcMac());
+		assertEquals(5L, cspIntent2.getDstSwitchDpid());
+		assertEquals(6L, cspIntent2.getDstPortNumber());
+		assertEquals(7L, cspIntent2.getDstMac());
+		assertEquals(1000.0, cspIntent2.getBandwidth(), 0.0);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
index 554aece..e2a9a64 100644
--- a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
+++ b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
@@ -35,7 +35,7 @@
 		for (PathIntent pathIntent: intents.getIntents()) {
 			System.out.println("Parent intent: " + pathIntent.getParentIntent().toString());
 			System.out.println("Path:");
-			for (Link link: pathIntent.getPath()) {
+			for (Link link: pathIntent.getPath(g)) {
 				System.out.printf("%s --(%f/%f)--> %s\n",
 						link.getSourcePort(),
 						link.getCapacity() - intents.getAvailableBandwidth(link),