Implement Floodlight module for PathCalcRuntime class and refactor

Change-Id: I57ff45cd11c84db1b30b40fbb5fbc01f657388bf
diff --git a/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java b/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
index 0f552d3..ead5a1f 100755
--- a/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
+++ b/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
@@ -128,9 +128,8 @@
 	    }
 	}
         IntentMap intents = new IntentMap();
-        intents.executeOperations(operations);
+//        intents.executeOperations(operations); // TODO use PathCalcRuntimeModule
         return mapper.writeValueAsString(arrayNode);
-        
     }
 
     private void appendIntentStatus(String status, final String applnIntentId, 
diff --git a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
index 2fd5013..30bdb01 100644
--- a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
+++ b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
@@ -22,7 +22,7 @@
 	HashMap<Switch, Link> upstreamLinks = new HashMap<Switch, Link>();
 	HashMap<Switch, Path> paths = new HashMap<Switch, Path>();
 	Switch rootSwitch;
-	PathIntents intents = null;
+	PathIntentMap intents = null;
 	double bandwidth = 0.0; // 0.0 means no limit for bandwidth (normal BFS tree)
 
 	public ConstrainedBFSTree(Switch rootSwitch) {
@@ -30,7 +30,7 @@
 		calcTree();
 	}
 
-	public ConstrainedBFSTree(Switch rootSwitch, PathIntents intents, double bandwidth) {
+	public ConstrainedBFSTree(Switch rootSwitch, PathIntentMap intents, double bandwidth) {
 		this.rootSwitch = rootSwitch;
 		this.intents = intents;
 		this.bandwidth = bandwidth;
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index 3429d1f..8e20bb7 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -45,7 +45,7 @@
 		state = newState;
 		return oldState;
 	}
-	
+
 	@Override
 	public int hashCode() {
 		return id.hashCode();
diff --git a/src/main/java/net/onrc/onos/intent/IntentMap.java b/src/main/java/net/onrc/onos/intent/IntentMap.java
index f9d8b9f..57ce5e0 100644
--- a/src/main/java/net/onrc/onos/intent/IntentMap.java
+++ b/src/main/java/net/onrc/onos/intent/IntentMap.java
@@ -6,7 +6,6 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.Map.Entry;
 
 import net.onrc.onos.intent.Intent.IntentState;
@@ -52,7 +51,7 @@
 	private HashSet<ChangedListener> listeners = new HashSet<>();
 	protected HashMap<String, Intent> intents = new HashMap<>();
 
-	public void executeOperations(List<IntentOperation> operations) {
+	public void executeOperations(IntentOperationList operations) {
 		LinkedList<ChangedEvent> events = new LinkedList<>();
 		for (IntentOperation operation: operations) {
 			switch (operation.operator) {
@@ -98,7 +97,6 @@
 		return intents.get(key);
 	}
 
-
 	public void addChangeListener(ChangedListener listener) {
 		listeners.add(listener);
 	}
diff --git a/src/main/java/net/onrc/onos/intent/IntentOperationList.java b/src/main/java/net/onrc/onos/intent/IntentOperationList.java
new file mode 100644
index 0000000..1c916db
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/IntentOperationList.java
@@ -0,0 +1,7 @@
+package net.onrc.onos.intent;
+
+import java.util.ArrayList;
+
+public class IntentOperationList extends ArrayList<IntentOperation> {
+	private static final long serialVersionUID = -3894081461861052610L;
+}
diff --git a/src/main/java/net/onrc/onos/intent/PathIntents.java b/src/main/java/net/onrc/onos/intent/PathIntentMap.java
similarity index 74%
rename from src/main/java/net/onrc/onos/intent/PathIntents.java
rename to src/main/java/net/onrc/onos/intent/PathIntentMap.java
index 8d712e3..02444ff 100644
--- a/src/main/java/net/onrc/onos/intent/PathIntents.java
+++ b/src/main/java/net/onrc/onos/intent/PathIntentMap.java
@@ -4,7 +4,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedList;
 
 import net.onrc.onos.ofcontroller.networkgraph.Link;
 import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
@@ -12,17 +11,18 @@
 /**
  * @author Toshio Koide (t-koide@onlab.us)
  */
-public class PathIntents {
-	protected LinkedList<PathIntent> intents = new LinkedList<PathIntent>();
+public class PathIntentMap extends IntentMap {
 	protected HashMap<Link, HashSet<PathIntent>> linkToIntents = new HashMap<Link, HashSet<PathIntent>>();
 	protected NetworkGraph graph;
 
-	public PathIntents(NetworkGraph graph) {
+	public PathIntentMap(NetworkGraph graph) {
 		this.graph = graph;
 	}
 
 	public void addIntent(PathIntent intent) {
-		intents.add(intent);
+		if (intents.containsKey(intent.getId()))
+			removeIntent((PathIntent)intents.get(intent.getId()));
+		intents.put(intent.getId(), intent);
 		for (Link link: intent.getPath(graph)) {
 			HashSet<PathIntent> value = linkToIntents.get(link);
 			if (value == null) {
@@ -41,26 +41,10 @@
 		}
 	}
 
-	public void addIntents(PathIntents intents) {
-		for(PathIntent intent: intents.getIntents()) {
-			addIntent(intent);
-		}
-	}
-
-	public void removeIntents(PathIntents intents) {
-		for(PathIntent intent: intents.getIntents()) {
-			removeIntent(intent);
-		}
-	}
-
 	public Collection<PathIntent> getIntentByLink(Link link) {
 		return Collections.unmodifiableCollection(linkToIntents.get(link));
 	}
 
-	public Collection<PathIntent> getIntents() {
-		return Collections.unmodifiableCollection(intents);
-	}
-
 	/**
 	 * calculate available bandwidth of specified link
 	 * @param link
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 0a171b3..d22d516 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -1,13 +1,15 @@
 package net.onrc.onos.intent.runtime;
 
 import java.util.Collection;
-import java.util.HashSet;
 
+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;
-import net.onrc.onos.intent.PathIntents;
+import net.onrc.onos.intent.PathIntentMap;
 import net.onrc.onos.intent.ShortestPathIntent;
 import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
 import net.onrc.onos.ofcontroller.networkgraph.Path;
@@ -16,33 +18,16 @@
 /**
  * @author Toshio Koide (t-koide@onlab.us)
  */
-public class PathCalcRuntime {
-	NetworkGraph graph;
-	HashSet<Intent> inputIntents = new HashSet<Intent>();
-	PathIntents outputIntents = null;
-
+public class PathCalcRuntime implements IFloodlightService {
+	private NetworkGraph graph;
 	public PathCalcRuntime(NetworkGraph g) {
 		this.graph = g;
-		outputIntents = new PathIntents(g);
 	}
 
-	public Collection<Intent> getInputIntents() {
-		return inputIntents;
-	}
+	public PathIntentMap calcPathIntents(Collection<Intent> highLevelIntents, PathIntentMap pathIntents) {
+		IntentOperationList intentOpList = new IntentOperationList();
 
-	public PathIntents getOutputIntents() {
-		return outputIntents;
-	}
-
-	public void addInputIntents(Collection<Intent> inputIntents) {
-		this.inputIntents.addAll(inputIntents);
-		this.outputIntents = calcPathIntents(inputIntents);
-	}
-
-	protected PathIntents calcPathIntents(Collection<Intent> originalIntents) {
-		PathIntents pathIntents = new PathIntents(graph);
-
-		for (Intent intent: originalIntents) {
+		for (Intent intent: highLevelIntents) {
 			if (!(intent instanceof ShortestPathIntent)) {
 				// unsupported intent type.
 				// TODO should push back the intent to caller
@@ -73,8 +58,10 @@
 				// TODO should push back the intent to caller
 				continue;
 			}
-			
-			pathIntents.addIntent(new PathIntent("pi" + intent.getId(), path, bandwidth, intent));
+
+			PathIntent pathIntent = new PathIntent("pi" + intent.getId(), path, bandwidth, intent);
+			pathIntents.addIntent(pathIntent);
+			intentOpList.add(new IntentOperation(IntentOperation.Operator.ADD, pathIntent));
 		}
 		return pathIntents;
 	}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
new file mode 100644
index 0000000..c32b4a7
--- /dev/null
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
@@ -0,0 +1,88 @@
+package net.onrc.onos.intent.runtime;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.onrc.onos.datagrid.IDatagridService;
+import net.onrc.onos.datagrid.IEventChannel;
+import net.onrc.onos.intent.IntentMap;
+import net.onrc.onos.intent.IntentOperationList;
+import net.onrc.onos.intent.PathIntentMap;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+
+public class PathCalcRuntimeModule implements IFloodlightModule {
+	private PathCalcRuntime runtime;
+	private IDatagridService datagridService;
+	private NetworkGraph networkGraph;
+	private IntentMap highLevelIntents;
+	private PathIntentMap lowLevelIntents;
+	
+	private IEventChannel<byte[], IntentOperationList> eventChannel;
+	private static final String EVENT_CHANNEL_NAME = "onos.pathintent";
+
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l = new ArrayList<>(1);
+		l.add(PathCalcRuntime.class);
+		return l;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+		Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<>(1);
+		m.put(PathCalcRuntime.class, runtime);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l = new ArrayList<>();
+		l.add(IDatagridService.class);
+		return l;
+	}
+
+	@Override
+	public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+		datagridService = context.getServiceImpl(IDatagridService.class);
+		//networkGraph = new MockNetworkGraph(); // TODO give pointer to the correct NetworkGraph
+		runtime = new PathCalcRuntime(networkGraph);
+		highLevelIntents = new IntentMap();
+		lowLevelIntents = new PathIntentMap(networkGraph);
+	}
+
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		eventChannel = datagridService.createChannel(
+				EVENT_CHANNEL_NAME,
+				byte[].class,
+				IntentOperationList.class);
+	}
+	
+	public void executeIntentOperations(IntentOperationList list) {
+		highLevelIntents.executeOperations(list);
+		lowLevelIntents = runtime.calcPathIntents(
+				highLevelIntents.getAllIntents(),
+				new PathIntentMap(networkGraph));
+		// TODO publishPathIntentOperationList(IntentOperationList list)
+	}
+	
+	protected void publishPathIntentOperationList(IntentOperationList list) {
+		eventChannel.addEntry(new byte[1], list); // TODO make key bytes		
+	}
+	
+	public IntentMap getIntents() {
+		return highLevelIntents;
+	}
+	
+	public void purgeIntents() {
+		highLevelIntents.purge();
+		lowLevelIntents.purge();
+	}
+}
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
index 9a46530..b01bfbc 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
@@ -13,7 +13,7 @@
 import net.onrc.onos.intent.FlowEntry;
 import net.onrc.onos.intent.Intent;
 import net.onrc.onos.intent.PathIntent;
-import net.onrc.onos.intent.PathIntents;
+import net.onrc.onos.intent.PathIntentMap;
 import net.onrc.onos.intent.ShortestPathIntent;
 import net.onrc.onos.ofcontroller.networkgraph.Link;
 import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
@@ -28,7 +28,7 @@
 
 public class PlanCalcRuntime {
 	NetworkGraph graph;
-	protected PathIntents intents;
+	protected PathIntentMap intents;
 	protected Set<Collection<FlowEntry>> flowEntries;
 	protected List<Set<FlowEntry>> plan;
 	
@@ -38,7 +38,7 @@
 		this.plan = new ArrayList<>();
 	}
 	
-	public void addIntents(PathIntents intents) {
+	public void addIntents(PathIntentMap intents) {
 		this.intents = intents;
 		computeFlowEntries();
 		constructPlan();
@@ -49,7 +49,8 @@
 	}
 
 	public void computeFlowEntries() {
-		for(PathIntent intent : intents.getIntents()) {
+		for(Intent i : intents.getAllIntents()) {
+			PathIntent intent = (PathIntent)i;
 			Intent parent = intent.getParentIntent();
 			Port srcPort, dstPort, lastDstPort = null;
 			MACAddress srcMac, dstMac;