Change calcPathIntent method to accept IntentOperationList

PathCalcRuntime.calcPathIntent()
 - accepts app-level IntentOperationList
 - returns PathIntents' IntentOperationList

PathCalcRuntimeModule class
 - retains app-level intents and path-level intents
 - publishes PathIntents' IntentOperationList

Change-Id: I70576390437f36d8b88849c0098966994b29900d
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 d22d516..32fe746 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -1,11 +1,10 @@
 package net.onrc.onos.intent.runtime;
 
-import java.util.Collection;
+import java.util.HashMap;
 
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.onrc.onos.intent.ConstrainedBFSTree;
 import net.onrc.onos.intent.ConstrainedShortestPathIntent;
-import net.onrc.onos.intent.Intent;
 import net.onrc.onos.intent.IntentOperation;
 import net.onrc.onos.intent.IntentOperationList;
 import net.onrc.onos.intent.PathIntent;
@@ -24,45 +23,61 @@
 		this.graph = g;
 	}
 
-	public PathIntentMap calcPathIntents(Collection<Intent> highLevelIntents, PathIntentMap pathIntents) {
-		IntentOperationList intentOpList = new IntentOperationList();
+	/**
+	 * calculate shortest-path and constrained-shortest-path intents into low-level path intents
+	 * @param intentOpList IntentOperationList having instances of ShortestPathIntent/ConstrainedShortestPathIntent
+	 * @param pathIntents a set of current low-level intents
+	 * @return IntentOperationList for PathIntent instances
+	 */
+	public IntentOperationList calcPathIntents(IntentOperationList intentOpList, PathIntentMap pathIntents) {
+		IntentOperationList pathIntentOpList = new IntentOperationList();
+		HashMap<Switch, ConstrainedBFSTree> spfTrees = new HashMap<>();
 
-		for (Intent intent: highLevelIntents) {
-			if (!(intent instanceof ShortestPathIntent)) {
-				// unsupported intent type.
-				// TODO should push back the intent to caller
-				continue;
-			}
+		for (IntentOperation intentOp: intentOpList) {
+			switch (intentOp.operator) {
+			case ADD:
+				if (!(intentOp.intent instanceof ShortestPathIntent)) {
+					// unsupported intent type.
+					// TODO should push back the intent to caller
+					continue;
+				}
 
-			ShortestPathIntent spIntent = (ShortestPathIntent) intent;
-			Switch srcSwitch = graph.getSwitch(spIntent.getSrcSwitchDpid());
-			Switch dstSwitch = graph.getSwitch(spIntent.getDstSwitchDpid());
-			if (srcSwitch == null || dstSwitch == null) {
-				// incomplete intent.
-				// TODO should push back the intent to caller
-				continue;
-			}
+				ShortestPathIntent spIntent = (ShortestPathIntent) intentOp.intent;
+				Switch srcSwitch = graph.getSwitch(spIntent.getSrcSwitchDpid());
+				Switch dstSwitch = graph.getSwitch(spIntent.getDstSwitchDpid());
+				if (srcSwitch == null || dstSwitch == null) {
+					// incomplete intent.
+					// TODO should push back the intent to caller
+					continue;
+				}
 
-			double bandwidth = 0.0;
-			ConstrainedBFSTree tree = null;
-			if (intent instanceof ConstrainedShortestPathIntent) {
-				bandwidth = ((ConstrainedShortestPathIntent) intent).getBandwidth();
-				tree = new ConstrainedBFSTree(srcSwitch, pathIntents, bandwidth);
+				double bandwidth = 0.0;
+				ConstrainedBFSTree tree = null;
+				if (intentOp.intent instanceof ConstrainedShortestPathIntent) {
+					bandwidth = ((ConstrainedShortestPathIntent) intentOp.intent).getBandwidth();
+					tree = new ConstrainedBFSTree(srcSwitch, pathIntents, bandwidth);
+				}
+				else {
+					tree = spfTrees.get(srcSwitch);
+					if (tree == null) {
+						tree = new ConstrainedBFSTree(srcSwitch);
+						spfTrees.put(srcSwitch, tree);
+					}
+				}
+				Path path = tree.getPath(dstSwitch);
+				if (path == null) {
+					// path not found.
+					// TODO should push back the intent to caller
+					continue;
+				}
+				PathIntent pathIntent = new PathIntent("pi" + intentOp.intent.getId(), path, bandwidth, intentOp.intent);
+				pathIntentOpList.add(new IntentOperation(IntentOperation.Operator.ADD, pathIntent));
+				break;
+			case REMOVE:
+				pathIntentOpList.add(intentOp);
+				break;
 			}
-			else {
-				tree = new ConstrainedBFSTree(srcSwitch);
-			}
-			Path path = tree.getPath(dstSwitch);
-			if (path == null) {
-				// path not found.
-				// TODO should push back the intent to caller
-				continue;
-			}
-
-			PathIntent pathIntent = new PathIntent("pi" + intent.getId(), path, bandwidth, intent);
-			pathIntents.addIntent(pathIntent);
-			intentOpList.add(new IntentOperation(IntentOperation.Operator.ADD, pathIntent));
 		}
-		return pathIntents;
+		return pathIntentOpList;
 	}
 }
\ No newline at end of file