Flow computation using Titan utilities for BFS
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
index a516108..9d65c91 100644
--- a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -1,17 +1,43 @@
 package net.onrc.onos.flow;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Vertex;
 
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.util.DataPath;
+import net.floodlightcontroller.util.Dpid;
 import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowEntryAction;
+import net.floodlightcontroller.util.FlowEntryMatch;
 import net.floodlightcontroller.util.FlowPath;
+import net.floodlightcontroller.util.Port;
+import net.floodlightcontroller.util.SwitchPort;
+import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.util.LocalTopologyEventListener;
+import net.onrc.onos.util.GraphDBConnection.Transaction;
 
 public class FlowManagerImpl implements IFlowManager {
+	
+	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
+	protected static GraphDBConnection conn;
 
 	@Override
 	public void createFlow(IPortObject src_port, IPortObject dest_port) {
@@ -44,6 +70,7 @@
 	public void reconcileFlows(IPortObject src_port) {
 		// TODO Auto-generated method stub
 
+		log.debug("Reconcile Flows for Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
 		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
 
 		for(IFlowEntry fe: flowEntries) {
@@ -54,6 +81,29 @@
 
 	private void reconcileFlow(IFlowPath flow) {
 		// TODO Auto-generated method stub
+		String src_dpid = flow.getSrcSwitch();
+		String dst_dpid = flow.getDstSwitch();
+		Short src_port = flow.getSrcPort();
+		Short dst_port = flow.getDstPort();
+		IPortObject src = null;
+		IPortObject dst = null;
+		src = conn.utils().searchPort(conn, src_dpid, src_port);
+		dst = conn.utils().searchPort(conn, dst_dpid, dst_port);
+		if (src != null && dst != null) {
+			FlowPath newFlow = this.computeFlowPath(src,dst);
+			installFlow(newFlow);
+			removeFlow(flow);
+		}
+		
+	}
+
+	private void removeFlow(IFlowPath flow) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	private void installFlow(FlowPath newFlow) {
+		// TODO Auto-generated method stub
 		
 	}
 
@@ -66,7 +116,188 @@
 	@Override
 	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
 		// TODO Auto-generated method stub
-		return null;
+		DataPath dataPath = new DataPath(); 
+		
+		// FIXME: Bad idea to use FloodLight data structures (SwitchPort)
+		
+		dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
+						new Port(src_port.getNumber())));
+		dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
+				new Port(src_port.getNumber())));
+		
+		if (src_port.getSwitch().equals(dest_port.getSwitch())) {
+			// on same switch create quick path
+			FlowEntry flowEntry = new FlowEntry();
+		    flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
+		    flowEntry.setInPort(new Port(src_port.getNumber()));
+		    flowEntry.setOutPort(new Port(src_port.getNumber()));
+		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+		    
+		    FlowPath flowPath = new FlowPath();
+			flowPath.setDataPath(dataPath);
+
+			return flowPath;
+		}
+		Vertex v_src = src_port.getSwitch().asVertex();	
+		Vertex v_dest = dest_port.getSwitch().asVertex();
+
+		//
+		// Implement the Shortest Path computation by using Breath First Search
+		//
+		Set<Vertex> visitedSet = new HashSet<Vertex>();
+		Queue<Vertex> processingList = new LinkedList<Vertex>();
+		Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
+
+		processingList.add(v_src);
+		visitedSet.add(v_src);
+		Boolean path_found = false;
+		while (! processingList.isEmpty()) {
+		    Vertex nextVertex = processingList.poll();
+		    if (v_dest.equals(nextVertex)) {
+			path_found = true;
+			break;
+		    }
+		    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
+			for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
+			    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
+				// Ignore inactive switches
+				String state = child.getProperty("state").toString();
+				if (! state.equals(SwitchState.ACTIVE.toString()))
+				    continue;
+
+				if (! visitedSet.contains(child)) {
+				    previousVertexMap.put(parentPort, nextVertex);
+				    previousVertexMap.put(childPort, parentPort);
+				    previousVertexMap.put(child, childPort);
+				    visitedSet.add(child);
+				    processingList.add(child);
+				}
+			    }
+			}
+		    }
+		}
+		if (! path_found) {
+		    return null;		// No path found
+		}
+
+		List<Vertex> resultPath = new LinkedList<Vertex>();
+		Vertex previousVertex = v_dest;
+		resultPath.add(v_dest);
+		while (! v_src.equals(previousVertex)) {
+		    Vertex currentVertex = previousVertexMap.get(previousVertex);
+		    resultPath.add(currentVertex);
+		    previousVertex = currentVertex;
+		}
+		Collections.reverse(resultPath);
+		
+		// Loop through the result and prepare the return result
+		// as a list of Flow Entries.
+		//
+		long nodeId = 0;
+		short portId = 0;
+		Port inPort = new Port(src_port.getNumber());
+		Port outPort = new Port();
+		int idx = 0;
+		for (Vertex v: resultPath) {
+		    String type = v.getProperty("type").toString();
+		    // System.out.println("type: " + type);
+		    if (type.equals("port")) {
+			String number = v.getProperty("number").toString();
+			// System.out.println("number: " + number);
+
+			Object obj = v.getProperty("number");
+			// String class_str = obj.getClass().toString();
+			if (obj instanceof Short) {
+			    portId = (Short)obj;
+			} else if (obj instanceof Integer) {
+			    Integer int_nodeId = (Integer)obj;
+			    portId = int_nodeId.shortValue();
+			    // int int_nodeId = (Integer)obj;
+			    // portId = (short)int_nodeId.;
+			}
+		    } else if (type.equals("switch")) {
+			String dpid = v.getProperty("dpid").toString();
+			nodeId = HexString.toLong(dpid);
+
+			// System.out.println("dpid: " + dpid);
+		    }
+		    idx++;
+		    if (idx == 1) {
+			continue;
+		    }
+		    int mod = idx % 3;
+		    if (mod == 0) {
+			// Setup the incoming port
+			inPort = new Port(portId);
+			continue;
+		    }
+		    if (mod == 2) {
+			// Setup the outgoing port, and add the Flow Entry
+			outPort = new Port(portId);
+
+			FlowEntry flowEntry = new FlowEntry();
+			flowEntry.setDpid(new Dpid(nodeId));
+			flowEntry.setInPort(inPort);
+			flowEntry.setOutPort(outPort);
+			flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+			continue;
+		    }
+		}
+		if (idx > 0) {
+		    // Add the last Flow Entry
+		    FlowEntry flowEntry = new FlowEntry();
+		    flowEntry.setDpid(new Dpid(nodeId));
+		    flowEntry.setInPort(inPort);
+		    flowEntry.setOutPort(new Port(dest_port.getNumber()));
+		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
+		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
+		    
+		    // Set the outgoing port output action
+		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
+		    if (flowEntryActions == null) {
+			flowEntryActions = new ArrayList<FlowEntryAction>();
+			flowEntry.setFlowEntryActions(flowEntryActions);
+		    }
+		    FlowEntryAction flowEntryAction = new FlowEntryAction();
+		    flowEntryAction.setActionOutput(flowEntry.outPort());
+		    flowEntryActions.add(flowEntryAction);
+		    dataPath.flowEntries().add(flowEntry);
+		    dataPath.flowEntries().add(flowEntry);
+		}
+
+	
+		if (dataPath.flowEntries().size() > 0) {
+		    FlowPath flowPath = new FlowPath();
+			flowPath.setDataPath(dataPath);
+
+			return flowPath;
+		}
+		return null;		
+		
 	}
 
 	@Override
@@ -100,5 +331,6 @@
 		// TODO Auto-generated method stub
 		return false;
 	}
+	
 
 }