Merge branch 'master' of github.com:OPENNETWORKINGLAB/ONOS
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 2b23e18..25cf367 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -1323,7 +1323,7 @@
      * @return the list of flows that are going out from the port.
      */
     @Override
-    public Iterable<FlowPath> getFlows(IPortObject port) {
+    public Iterable<FlowPath> getOutFlows(IPortObject port) {
 	// TODO: We need it now: Pankaj
 	return null;
     }
@@ -1384,7 +1384,13 @@
 	    //
 	    for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
 		flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
-		installFlowEntry(mySwitches, flowEntry);
+		IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
+		if (mySwitch == null) {
+		    // Not my switch
+		    installRemoteFlowEntry(flowEntry);
+		} else {
+		    installFlowEntry(mySwitch, flowEntry);
+		}
 	    }
 
 	    //
@@ -1393,7 +1399,7 @@
 	    //
 	    FlowPath addedFlowPath = addAndMaintainShortestPathFlow(flowPath);
 	    if (addedFlowPath == null) {
-		log.error("Cannot add Shortest Path Flow from {} to {}",
+		log.error("Cannot add Shortest Path Flow from {} to {}: path not found?",
 			  flowPath.dataPath().srcPort().toString(),
 			  flowPath.dataPath().dstPort().toString());
 		continue;
@@ -1404,7 +1410,33 @@
 	    //
 	    for (FlowEntry flowEntry : addedFlowPath.dataPath().flowEntries()) {
 		flowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_ADD);
-		installFlowEntry(mySwitches, flowEntry);
+		IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
+		if (mySwitch == null) {
+		    // Not my switch
+		    installRemoteFlowEntry(flowEntry);
+		    continue;
+		}
+
+		IFlowEntry flowEntryObj =
+		    conn.utils().searchFlowEntry(conn, flowEntry.flowEntryId());
+		if (flowEntryObj == null) {
+		    //
+		    // TODO: Remove the "new Object[] wrapper in the statement
+		    // below after the SLF4J logger is upgraded to
+		    // Version 1.7.5
+		    //
+		    log.error("Cannot add Flow Entry to switch {} for Path Flow from {} to {} : Flow Entry not in the Network MAP",
+			      new Object[] {
+				  flowEntry.dpid(),
+				  flowPath.dataPath().srcPort(),
+				  flowPath.dataPath().dstPort()
+			      });
+		    continue;
+		}
+		// Update the Flow Entry Switch State in the Network MAP
+		if (installFlowEntry(mySwitch, flowEntry)) {
+		    flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
+		}
 	    }
 	}
     }
@@ -1505,20 +1537,12 @@
     /**
      * Install a Flow Entry on a switch.
      *
-     * @param mySwitches the DPID-to-Switch mapping for the switches
-     * controlled by this controller.
+     * @param mySwitch the switch to install the Flow Entry into.
      * @param flowEntry the flow entry to install.
      * @return true on success, otherwise false.
      */
     @Override
-    public boolean installFlowEntry(Map<Long, IOFSwitch> mySwitches,
-				    FlowEntry flowEntry) {
-	IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-	if (mySwitch == null) {
-	    // Not my switch
-	    return (installRemoteFlowEntry(flowEntry));
-	}
-
+    public boolean installFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
 	//
 	// Create the OpenFlow Flow Modification Entry to push
 	//
@@ -1634,19 +1658,17 @@
     /**
      * Remove a Flow Entry from a switch.
      *
-     * @param mySwitches the DPID-to-Switch mapping for the switches
-     * controlled by this controller.
+     * @param mySwitch the switch to remove the Flow Entry from.
      * @param flowEntry the flow entry to remove.
      * @return true on success, otherwise false.
      */
     @Override
-    public boolean removeFlowEntry(Map<Long, IOFSwitch> mySwitches,
-				    FlowEntry flowEntry) {
+    public boolean removeFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
 	//
 	// The installFlowEntry() method implements both installation
 	// and removal of flow entries.
 	//
-	return (installFlowEntry(mySwitches, flowEntry));
+	return (installFlowEntry(mySwitch, flowEntry));
     }
 
     /**
diff --git a/src/main/java/net/floodlightcontroller/util/FlowPath.java b/src/main/java/net/floodlightcontroller/util/FlowPath.java
index 7fcb2e6..f4c25c2 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowPath.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowPath.java
@@ -1,5 +1,9 @@
 package net.floodlightcontroller.util;
 
+import java.util.ArrayList;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.util.CallerId;
 import net.floodlightcontroller.util.DataPath;
 import net.floodlightcontroller.util.FlowId;
@@ -20,6 +24,75 @@
     public FlowPath() {
 	dataPath = new DataPath();
     }
+    
+    /**
+     * Constructor to instantiate from object in Network Map
+     */
+    public FlowPath(IFlowPath flowObj) {
+    	dataPath = new DataPath();
+    	this.setFlowId(new FlowId(flowObj.getFlowId()));
+    	this.setInstallerId(new CallerId(flowObj.getInstallerId()));
+    	this.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
+    	this.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
+    	this.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
+    	this.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
+
+    	//
+    	// Extract all Flow Entries
+    	//
+    	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+    	for (IFlowEntry flowEntryObj : flowEntries) {
+    	    FlowEntry flowEntry = new FlowEntry();
+    	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
+    	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
+
+    	    //
+    	    // Extract the match conditions
+    	    //
+    	    FlowEntryMatch match = new FlowEntryMatch();
+    	    Short matchInPort = flowEntryObj.getMatchInPort();
+    	    if (matchInPort != null)
+    		match.enableInPort(new Port(matchInPort));
+    	    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+    	    if (matchEthernetFrameType != null)
+    		match.enableEthernetFrameType(matchEthernetFrameType);
+    	    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+    	    if (matchSrcIPv4Net != null)
+    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+    	    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+    	    if (matchDstIPv4Net != null)
+    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+    	    String matchSrcMac = flowEntryObj.getMatchSrcMac();
+    	    if (matchSrcMac != null)
+    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+    	    String matchDstMac = flowEntryObj.getMatchDstMac();
+    	    if (matchDstMac != null)
+    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+    	    flowEntry.setFlowEntryMatch(match);
+
+    	    //
+    	    // Extract the actions
+    	    //
+    	    ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
+    	    Short actionOutputPort = flowEntryObj.getActionOutput();
+    	    if (actionOutputPort != null) {
+    		FlowEntryAction action = new FlowEntryAction();
+    		action.setActionOutput(new Port(actionOutputPort));
+    		actions.add(action);
+    	    }
+    	    flowEntry.setFlowEntryActions(actions);
+
+    	    String userState = flowEntryObj.getUserState();
+    	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
+    	    String switchState = flowEntryObj.getSwitchState();
+    	    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
+    	    //
+    	    // TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
+    	    // and FlowEntryErrorState.
+    	    //
+    	    this.dataPath().flowEntries().add(flowEntry);
+    	}
+    }
 
     /**
      * Get the flow path Flow ID.
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
new file mode 100644
index 0000000..a516108
--- /dev/null
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -0,0 +1,104 @@
+package net.onrc.onos.flow;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowPath;
+
+public class FlowManagerImpl implements IFlowManager {
+
+	@Override
+	public void createFlow(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public Iterable<FlowPath> getFlows(IPortObject src_port,
+			IPortObject dest_port) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Iterable<FlowPath> getOutFlows(IPortObject port) {
+		// TODO Auto-generated method stub
+		List<FlowPath> flowPaths = new ArrayList<FlowPath> ();
+		Iterable<IFlowEntry> flowEntries = port.getOutFlowEntries();
+
+		for(IFlowEntry fe: flowEntries) {
+			IFlowPath flow = fe.getFlow();
+			FlowPath flowPath = new FlowPath(flow);
+			flowPaths.add(flowPath);
+		}
+		return flowPaths;
+	}
+
+	@Override
+	public void reconcileFlows(IPortObject src_port) {
+		// TODO Auto-generated method stub
+
+		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
+
+		for(IFlowEntry fe: flowEntries) {
+			IFlowPath flow = fe.getFlow();
+			reconcileFlow(flow);
+		}
+	}
+
+	private void reconcileFlow(IFlowPath flow) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+
+	@Override
+	public boolean installRemoteFlowEntry(FlowEntry entry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean removeRemoteFlowEntry(FlowEntry entry) {
+		return false;
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public boolean installFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean removeFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/flow/IFlowManager.java b/src/main/java/net/onrc/onos/flow/IFlowManager.java
index 8394046..d163760 100644
--- a/src/main/java/net/onrc/onos/flow/IFlowManager.java
+++ b/src/main/java/net/onrc/onos/flow/IFlowManager.java
@@ -38,7 +38,7 @@
      * @param port the port to match.
      * @return the list of flows that are going out from the port.
      */
-    public Iterable<FlowPath> getFlows(IPortObject port);
+    public Iterable<FlowPath> getOutFlows(IPortObject port);
 
     /**
      * Reconcile all flows on inactive switch port.
@@ -83,24 +83,20 @@
     /**
      * Install a Flow Entry on a switch.
      *
-     * @param mySwitches the DPID-to-Switch mapping for the switches
-     * controlled by this controller.
+     * @param mySwitch the switch to install the Flow Entry into.
      * @param flowEntry the flow entry to install.
      * @return true on success, otherwise false.
      */
-    public boolean installFlowEntry(Map<Long, IOFSwitch> mySwitches,
-				    FlowEntry flowEntry);
+    public boolean installFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry);
 
     /**
      * Remove a Flow Entry from a switch.
      *
-     * @param mySwitches the DPID-to-Switch mapping for the switches
-     * controlled by this controller.
+     * @param mySwitch the switch to remove the Flow Entry from.
      * @param flowEntry the flow entry to remove.
      * @return true on success, otherwise false.
      */
-    public boolean removeFlowEntry(Map<Long, IOFSwitch> mySwitches,
-				   FlowEntry flowEntry);
+    public boolean removeFlowEntry(IOFSwitch mySwitch, FlowEntry flowEntry);
 
     /**
      * Install a Flow Entry on a remote controller.
diff --git a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
new file mode 100644
index 0000000..186ba58
--- /dev/null
+++ b/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
@@ -0,0 +1,92 @@
+package net.onrc.onos.util;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.linkdiscovery.internal.TopoLinkServiceImpl;
+import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.flow.FlowManagerImpl;
+import net.onrc.onos.flow.IFlowManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanEdge;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
+
+public class LocalTopologyEventListener implements GraphChangedListener {
+	
+	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
+	protected static GraphDBConnection conn = GraphDBConnection.getInstance("");
+
+	@Override
+	public void edgeAdded(Edge arg0) {
+		// TODO Auto-generated method stub
+		// Convert this Event into NetMapEvent (LinkAdded, FlowEntryEnabled, HostAttached, PortEnabled)
+	}
+
+	@Override
+	public void edgePropertyChanged(Edge arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+        // Generate State change events on edges too
+	}
+
+	@Override
+	public void edgePropertyRemoved(Edge arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		// Currently not needed
+
+	}
+
+	@Override
+	public void edgeRemoved(Edge e) {
+		// TODO Auto-generated method stub
+		// Fire NetMapEvents (LinkRemoved, FlowEntryRemoved, HostRemoved, PortRemoved)
+		TitanEdge edge = (TitanEdge) e;
+		log.debug("TopologyEvents: Received edge removed event: {}",edge.toString());
+		String label = edge.getLabel();
+		if (label.equals("link")) {
+			Vertex v = edge.getVertex(Direction.IN);
+			IPortObject src_port = conn.getFramedGraph().frame(v, IPortObject.class);
+			v = edge.getVertex(Direction.OUT);
+			IPortObject dest_port = conn.getFramedGraph().frame(v, IPortObject.class);
+
+			log.debug("TopologyEvents: link broken {}", new Object []{src_port.getSwitch().getDPID(),
+																src_port.getNumber(),
+																dest_port.getSwitch().getDPID(),
+																dest_port.getNumber()});
+			IFlowManager manager = new FlowManagerImpl();
+			// TODO: Find the flows and add to reconcile queue
+			manager.reconcileFlows(src_port);
+		}
+	}
+
+	@Override
+	public void vertexAdded(Vertex arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void vertexPropertyChanged(Vertex arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+		
+
+	}
+
+	@Override
+	public void vertexPropertyRemoved(Vertex arg0, String arg1, Object arg2) {
+		// TODO Auto-generated method stub
+
+	}
+
+	@Override
+	public void vertexRemoved(Vertex arg0) {
+		// TODO Auto-generated method stub
+
+	}
+
+}