package net.onrc.onos.ofcontroller.core.internal;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.easymock.EasyMock;
import org.openflow.util.HexString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.Property;
import com.tinkerpop.frames.annotations.gremlin.GremlinParam;

import net.onrc.onos.graph.GraphDBConnection;
import net.onrc.onos.graph.GraphDBOperation;
import net.onrc.onos.graph.IDBConnection;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
import net.onrc.onos.ofcontroller.util.FlowEntryId;
import net.onrc.onos.ofcontroller.util.FlowId;

/**
 * Mock class of GraphDBOperation which provides additional setter to construct a graph for test.
 * This object simply caches parameters set up by override interfaces and reflect them when commit().
 * *ForTest() methods are exempt from cache, parameters through those methods are reflected soon.
 * @author Naoki Shiota
 *
 */
public class TestableGraphDBOperation extends GraphDBOperation {
	protected static Logger log = LoggerFactory.getLogger(TestableGraphDBOperation.class);

	protected List<TestSwitchObject> switches;
	protected List<TestPortObject> ports;
	protected List<TestDeviceObject> devices;
	protected List<TestFlowPath> paths;
	protected List<TestFlowEntry> entries;

	protected List<TestSwitchObject> switchesToAdd;
	protected List<TestPortObject> portsToAdd;
	protected List<TestDeviceObject> devicesToAdd;
	protected List<TestFlowPath> pathsToAdd;
	protected List<TestFlowEntry> entriesToAdd;

	protected List<TestSwitchObject> switchesToRemove;
	protected List<TestPortObject> portsToRemove;
	protected List<TestDeviceObject> devicesToRemove;
	protected List<TestFlowPath> pathsToRemove;
	protected List<TestFlowEntry> entriesToRemove;

	// Testable implementations of INetMapTopologyObject interfaces

	public static class TestSwitchObject implements ISwitchObject {
		private String state,type,dpid;
		private List<IPortObject> ports;
		private List<IDeviceObject> devices;
		private List<IFlowEntry> entries;

		private String stateToUpdate, typeToUpdate, dpidToUpdate;
		private List<IPortObject> portsToAdd;
		private List<IPortObject> portsToRemove;

		public TestSwitchObject() {
			type = "switch";
			
			ports = new ArrayList<IPortObject>();
			portsToAdd = new ArrayList<IPortObject>();
			portsToRemove = new ArrayList<IPortObject>();
			devices = new ArrayList<IDeviceObject>();
			entries = new ArrayList<IFlowEntry>();
			
			clearUncommitedData();
		}
		
		public void commit() {
			for(IPortObject port : portsToAdd) {
				ports.add(port);
			}
			for(IPortObject port : portsToRemove) {
				ports.remove(port);
			}
			if(stateToUpdate != null) { state = stateToUpdate; }
			if(typeToUpdate != null) { type = typeToUpdate; }
			if(dpidToUpdate != null) { dpid = dpidToUpdate; }

			clearUncommitedData();
		}
		
		public void rollback() {
			clearUncommitedData();
		}
		
		public void clearUncommitedData() {
			portsToAdd.clear();
			portsToRemove.clear();
			stateToUpdate = typeToUpdate = dpidToUpdate = null;
		}
		
		public void setStateForTest(String state) { this.state = state; }
		public void setTypeForTest(String type) { this.type = type; }
		public void setDpidForTest(String dpid) { this.dpid = dpid; }
		public void addPortForTest(TestPortObject port) { ports.add(port);  }
		public void addDeviceForTest(TestDeviceObject dev) { devices.add(dev); }
		public void addEntryForTest(TestFlowEntry entry) { entries.add(entry); }
		
		@Override
		public String getState() { return state; }
	
		@Override
		public void setState(String state) { this.stateToUpdate = state; }
	
		@Override
		public String getType() { return type ; }
	
		@Override
		public void setType(String type) { this.typeToUpdate = type; }
	
		// Not support for test
		@Override
		public Vertex asVertex() { return null; }
	
		@Override
		public String getDPID() { return dpid; }
	
		@Override
		public void setDPID(String dpid) { this.dpidToUpdate = dpid; }
	
		@Override
		public Iterable<IPortObject> getPorts() { return ports; }
	
		@Override
		public IPortObject getPort(@GremlinParam("port_num") short port_num) {
			for(IPortObject port : ports) {
				if(port.getNumber() == port_num) {
					return port;
				}
			}
			return null;
		}
	
		@Override
		public void addPort(IPortObject port) { portsToAdd.add(port); }
	
		@Override
		public void removePort(IPortObject port) { portsToRemove.add(port); }
	
		@Override
		public Iterable<IDeviceObject> getDevices() { return devices; }
	
		@Override
		public Iterable<IFlowEntry> getFlowEntries() { return entries; }
	}
	
	public static class TestPortObject implements IPortObject {
		private String state,type,desc;
		private Short number;
		private Integer port_state;
		private ISwitchObject sw;
		
		private List<IPortObject> linkedPorts;
		private List<IDeviceObject> devices;
		private List<IFlowEntry> inflows,outflows;
		
		private String stateToUpdate,typeToUpdate,descToUpdate;
		private Short numberToUpdate;
		private Integer port_stateToUpdate;
		
		private List<IPortObject> linkedPortsToAdd;
		private List<IPortObject> linkedPortsToRemove;
		private List<IDeviceObject> devicesToAdd;
		private List<IDeviceObject> devicesToRemove;
		

		public TestPortObject() {
			type = "port";

			linkedPorts = new ArrayList<IPortObject>();
			linkedPortsToAdd = new ArrayList<IPortObject>();
			linkedPortsToRemove = new ArrayList<IPortObject>();
			devices = new ArrayList<IDeviceObject>();
			devicesToAdd = new ArrayList<IDeviceObject>();
			devicesToRemove = new ArrayList<IDeviceObject>();
			inflows = new ArrayList<IFlowEntry>();
			outflows = new ArrayList<IFlowEntry>();
			
			clearUncommitedData();
		}
		
		public void commit() {
			for(IPortObject port : linkedPortsToAdd) { linkedPorts.add(port); }
			for(IPortObject port : linkedPortsToRemove) { linkedPorts.remove(port); }
			for(IDeviceObject dev : devicesToAdd) { devices.add(dev); }
			for(IDeviceObject dev : devicesToRemove) { devices.remove(dev); }
			
			if(stateToUpdate != null) { state = stateToUpdate; }
			if(typeToUpdate != null) { type = typeToUpdate; }
			if(descToUpdate != null) { desc = descToUpdate; }
			if(numberToUpdate != null) { number = numberToUpdate; }
			if(port_stateToUpdate != null) { port_state = port_stateToUpdate; }
			
			clearUncommitedData();
		}
		
		public void rollback() {
			clearUncommitedData();
		}
		
		public void clearUncommitedData() {
			linkedPortsToAdd.clear();
			linkedPortsToRemove.clear();
			devicesToAdd.clear();
			devicesToRemove.clear();
			stateToUpdate = typeToUpdate = descToUpdate = null;
			port_stateToUpdate = null;
			numberToUpdate = null;
		}
		
		// Setter methods for test
		public void setStateForTest(String state) { this.state = state; }
		public void setTypeForTest(String type) { this.type = type; }
		public void setDescForTest(String desc) { this.desc = desc; }
		public void setNumberForTest(Short number) { this.number = number; }
		public void setPortStateForTest(Integer state) { this.port_state = state; }
		public void setSwitchForTest(ISwitchObject sw) { this.sw = sw; }
		public void addLinkedPortForTest(TestPortObject port) { this.linkedPorts.add(port); }
		public void addInflowForTest(TestFlowEntry entry) { inflows.add(entry); }
		public void addOutflowForTest(TestFlowEntry entry) { outflows.add(entry); }
		
		// Override methods for mock IPortObject
		@Override
		public String getState() { return state; }

		@Override
		public void setState(String state) { this.stateToUpdate = state; }

		@Override
		public String getType() { return type; }

		@Override
		public void setType(String type) { this.typeToUpdate = type; }

		// not support for test
		@Override
		public Vertex asVertex() {
			return null;
		}

		@Override
		public Short getNumber() { return number; }

		@Override
		public void setNumber(Short n) { this.numberToUpdate = n; }

		@Override
		public String getDesc() { return desc; }

		@Override
		public void setDesc(String s) { this.descToUpdate = s; }

		@Override
		public Integer getPortState() { return port_state; }

		@Override
		public void setPortState(Integer s) { this.port_stateToUpdate = s; }

		@Override
		public ISwitchObject getSwitch() { return sw; }

		@Override
		public Iterable<IDeviceObject> getDevices() { return devices; }

		@Override
		public void setDevice(IDeviceObject device) { devicesToAdd.add(device); }

		@Override
		public void removeDevice(IDeviceObject device) { devicesToRemove.add(device); }

		@Override
		public Iterable<IFlowEntry> getInFlowEntries() { return inflows; }

		@Override
		public Iterable<IFlowEntry> getOutFlowEntries() { return outflows; }

		@Override
		public Iterable<IPortObject> getLinkedPorts() { return linkedPorts; }

		@Override
		public void removeLink(IPortObject dest_port) { linkedPortsToRemove.add(dest_port); }

		@Override
		public void setLinkPort(IPortObject dest_port) { linkedPortsToAdd.add(dest_port); }

		@Override
		@JsonIgnore
		@Property("port_id")
		public void setPortId(String id) {
			// TODO Auto-generated method stub
			
		}

		@Override
		@JsonIgnore
		@Property("port_id")
		public String getPortId() {
			// TODO Auto-generated method stub
			return null;
		}
	}
		
	public static class TestDeviceObject implements IDeviceObject {
		private String state,type,mac,ipaddr;
		private List<IPortObject> ports;
		private List<ISwitchObject> switches;
		
		private String stateToUpdate,typeToUpdate,macToUpdate,ipaddrToUpdate;
		private List<IPortObject> portsToAdd;
		private List<IPortObject> portsToRemove;
	
		public TestDeviceObject() {
			type = "device";
			
			ports = new ArrayList<IPortObject>();
			portsToAdd = new ArrayList<IPortObject>();
			portsToRemove = new ArrayList<IPortObject>();
			switches = new ArrayList<ISwitchObject>();
			
			clearUncommitedData();
		}
		
		public void commit() {
			for(IPortObject port : portsToAdd) {
				ports.add(port);
			}
			for(IPortObject port : portsToRemove) {
				ports.remove(port);
			}
			
			if(stateToUpdate != null) { state = stateToUpdate; }
			if(typeToUpdate != null) { type = typeToUpdate; }
			if(macToUpdate != null) { mac = macToUpdate; }
			if(ipaddrToUpdate != null) { ipaddr = ipaddrToUpdate; }
			
			clearUncommitedData();
		}
		
		public void rollback() {
			clearUncommitedData();
		}
		
		public void clearUncommitedData() {
			ports.clear();
			portsToAdd.clear();
			portsToRemove.clear();
			
			stateToUpdate = typeToUpdate = macToUpdate = ipaddrToUpdate = null;
		}
		
		// Setter methods for test
		public void setStateForTest(String state) { this.state = state; }
		public void setTypeForTest(String type) { this.type = type; }
		public void setMacForTest(String mac) { this.mac = mac; }
		public void setIpaddrForTest(String ipaddr) { this.ipaddr = ipaddr; }
		public void addSwitchForTest(ISwitchObject sw) { switches.add(sw); }
		public void addPortForTest(IPortObject port) { ports.add(port); }
		
		
		// Override methods
		@Override
		public String getState() { return state; }
	
		@Override
		public void setState(String state) { stateToUpdate = state; }
	
		@Override
		public String getType() { return type; }
	
		@Override
		public void setType(String type) { typeToUpdate = type; }
	
		@Override
		public Vertex asVertex() {
			// TODO Auto-generated method stub
			return null;
		}
	
		@Override
		public String getMACAddress() { return mac; }
	
		@Override
		public void setMACAddress(String macaddr) { macToUpdate = macaddr; }
	
		@Override
		public String getIPAddress() { return ipaddr; }
	
		@Override
		public void setIPAddress(String ipaddr) { ipaddrToUpdate = ipaddr; }
	
		@Override
		public Iterable<IPortObject> getAttachedPorts() {
			return ports; }
	
		@Override
		public void setHostPort(IPortObject port) { portsToAdd.add(port); }
	
		@Override
		public void removeHostPort(IPortObject port) { portsToRemove.add(port); }
	
		@Override
		public Iterable<ISwitchObject> getSwitch() { return switches; }
	}
	
	public static class TestFlowPath implements IFlowPath {
		private String state,type,flowId,installerId,srcSw,dstSw;
		private String dataPathSummary,userState;
		private String matchSrcMac,matchDstMac,matchSrcIpaddr,matchDstIpaddr;
		private Short srcPort,dstPort,matchEthernetFrameType;
		
		private List<IFlowEntry> entries;
		private List<ISwitchObject> switches;

		private String stateToUpdate,typeToUpdate,flowIdToUpdate,installerIdToUpdate,srcSwToUpdate,dstSwToUpdate;
		private String dataPathSummaryToUpdate,userStateToUpdate;
		private String matchSrcMacToUpdate,matchDstMacToUpdate,matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
		private Short srcPortToUpdate,dstPortToUpdate,matchEthernetFrameTypeToUpdate;

		private List<IFlowEntry> flowsToAdd;
		private List<IFlowEntry> flowsToRemove;

		public TestFlowPath() {
			type = "flow";
			
			entries = new ArrayList<IFlowEntry>();
			flowsToAdd = new ArrayList<IFlowEntry>();
			flowsToRemove = new ArrayList<IFlowEntry>();
			
			switches = new ArrayList<ISwitchObject>();
			
			clear();
		}
		
		public void commit() {
			for(IFlowEntry flow : flowsToAdd) {
				entries.add(flow);
			}
			for(IFlowEntry flow : flowsToRemove) {
				entries.remove(flow);
			}
			if(stateToUpdate != null) { state = stateToUpdate; }
			if(typeToUpdate != null) { type = typeToUpdate; }
			if(flowIdToUpdate != null) { flowId = flowIdToUpdate; }
			if(installerIdToUpdate != null) { installerId = installerIdToUpdate; }
			if(srcSwToUpdate != null) { srcSw = srcSwToUpdate; }
			if(dstSwToUpdate != null) { dstSw = dstSwToUpdate; }
			if(dataPathSummaryToUpdate != null) { dataPathSummary = dataPathSummaryToUpdate; }
			if(userStateToUpdate != null) { userState = userStateToUpdate; }
			if(matchSrcMacToUpdate != null) { matchSrcMac = matchSrcMacToUpdate; }
			if(matchDstMacToUpdate != null) { matchDstMac = matchDstMacToUpdate; }
			if(matchSrcIpaddrToUpdate != null) { matchSrcIpaddr = matchSrcIpaddrToUpdate; }
			if(matchDstIpaddrToUpdate != null) { matchDstIpaddr = matchDstIpaddrToUpdate; }
			if(srcPortToUpdate != null) { srcPort = srcPortToUpdate; }
			if(dstPortToUpdate != null) { dstPort = dstPortToUpdate; }
			if(matchEthernetFrameTypeToUpdate != null) { matchEthernetFrameType = matchEthernetFrameTypeToUpdate; }
		}
		
		public void rollback() {
			clear();
		}
		
		public void clear() {
			flowsToAdd.clear();
			flowsToRemove.clear();
			
			stateToUpdate = typeToUpdate = flowIdToUpdate = installerIdToUpdate = null;
			srcSwToUpdate = dstSwToUpdate = dataPathSummaryToUpdate = userStateToUpdate = null;
			matchSrcMacToUpdate = matchDstMacToUpdate = matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
			srcPortToUpdate = dstPortToUpdate = matchEthernetFrameTypeToUpdate = null;
		}
		
		// Setter methods for test
		public void setStateForTest(String state) { this.state = state; }
		public void setTypeForTest(String type) { this.type = type; }
		public void setFlowIdForTest(String flowId) { this.flowId = flowId; }
		public void setInstallerIdForTest(String installerId) { this.installerId = installerId; }
		public void setSrcSwForTest(String srcSw) { this.srcSw = srcSw; }
		public void setDstSwForTest(String dstSw) { this.dstSw = dstSw; }
		public void setDataPathSummaryForTest(String dataPathSummary) { this.dataPathSummary = dataPathSummary; }
		public void setUserStateForTest(String userState) { this.userState = userState; }
		public void setMatchSrcMacForTest(String matchSrcMac) { this.matchSrcMac = matchSrcMac; }
		public void setMatchDstMacForTest(String matchDstMac) { this.matchDstMac = matchDstMac; }
		public void setMatchSrcIpaddrForTest(String matchSrcIpaddr) { this.matchSrcIpaddr = matchSrcIpaddr; }
		public void setMatchDstIpaddrForTest(String matchDstIpaddr) { this.matchDstIpaddr = matchDstIpaddr; }
		public void setSrcPortForTest(Short srcPort) { this.srcPort = srcPort; }
		public void setDstPortForTest(Short dstPort) { this.dstPort = dstPort; }
		public void setMatchEthernetFrameTypeForTest(Short matchEthernetFrameType) { this.matchEthernetFrameType = matchEthernetFrameType; }
		public void addFlowEntryForTest(IFlowEntry entry) { entries.add(entry); }
		public void addSwitchForTest(ISwitchObject sw) { switches.add(sw); }

		@Override
		public String getState() { return state; }

		@Override
		public void setState(String state) { stateToUpdate = state; }

		@Override
		public String getType() { return type; }

		@Override
		public void setType(String type) { typeToUpdate = type; }

		@Override
		public Vertex asVertex() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public String getFlowId() { return flowId; }

		@Override
		public void setFlowId(String flowId) { flowIdToUpdate = flowId; }

		@Override
		public String getInstallerId() { return installerId; }

		@Override
		public void setInstallerId(String installerId) { installerIdToUpdate = installerId; }

		@Override
		public String getSrcSwitch() { return srcSw; }

		@Override
		public void setSrcSwitch(String srcSwitch) { srcSwToUpdate = srcSwitch; }

		@Override
		public Short getSrcPort() { return srcPort; }

		@Override
		public void setSrcPort(Short srcPort) { srcPortToUpdate = srcPort; }

		@Override
		public String getDstSwitch() { return dstSw; }

		@Override
		public void setDstSwitch(String dstSwitch) { dstSwToUpdate = dstSwitch; }

		@Override
		public Short getDstPort() { return dstPort; }

		@Override
		public void setDstPort(Short dstPort) { dstPortToUpdate = dstPort; }

		@Override
		public String getDataPathSummary() { return dataPathSummary; }

		@Override
		public void setDataPathSummary(String dataPathSummary) { dataPathSummaryToUpdate = dataPathSummary; }

		@Override
		public Iterable<IFlowEntry> getFlowEntries() { return entries; }

		@Override
		public void addFlowEntry(IFlowEntry flowEntry) {
			if(! entries.contains(flowEntry)) {
				flowsToAdd.add(flowEntry);
			}
		}

		@Override
		public void removeFlowEntry(IFlowEntry flowEntry) {
			if(entries.contains(flowEntry)) {
				flowsToAdd.add(flowEntry);
			}
		}

		@Override
		public Short getMatchEthernetFrameType() { return matchEthernetFrameType; }

		@Override
		public void setMatchEthernetFrameType(Short matchEthernetFrameType) {
			matchEthernetFrameTypeToUpdate = matchEthernetFrameType; }

		@Override
		public String getMatchSrcMac() { return matchSrcMac; }

		@Override
		public void setMatchSrcMac(String matchSrcMac) { matchSrcMacToUpdate = matchSrcMac; }

		@Override
		public String getMatchDstMac() { return matchDstMac; }

		@Override
		public void setMatchDstMac(String matchDstMac) { matchDstMacToUpdate = matchDstMac; }

		@Override
		public String getMatchSrcIPv4Net() { return matchSrcIpaddr; }

		@Override
		public void setMatchSrcIPv4Net(String matchSrcIPv4Net) {
			matchSrcIpaddrToUpdate = matchSrcIPv4Net; }

		@Override
		public String getMatchDstIPv4Net() { return matchDstIpaddr; }

		@Override
		public void setMatchDstIPv4Net(String matchDstIPv4Net) {
			matchDstIpaddrToUpdate = matchDstIPv4Net; }

		@Override
		public Iterable<ISwitchObject> getSwitches() { return switches; }

		@Override
		public String getUserState() { return userState; }

		@Override
		public void setUserState(String userState) { userStateToUpdate = userState; }
	}

	public static class TestFlowEntry implements IFlowEntry {
		private String state,type,entryId,dpid,userState,switchState,errorStateType,errorStateCode;
		private String matchSrcMac,matchDstMac,matchSrcIpaddr,matchDstIpaddr;
		private Short matchInPort,matchEtherFrameType,actionOutput;
		
		private IFlowPath flowPath;
		private ISwitchObject sw;
		private IPortObject inport,outport;
	
		private String stateToUpdate,typeToUpdate,entryIdToUpdate,dpidToUpdate,
			userStateToUpdate,switchStateToUpdate,errorStateTypeToUpdate,errorStateCodeToUpdate;
		private String matchSrcMacToUpdate,matchDstMacToUpdate,matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
	
		private Short matchInPortToUpdate,matchEtherFrameTypeToUpdate,actionOutputToUpdate;
	
		private IFlowPath flowPathToUpdate;
		private ISwitchObject swToUpdate;
		private IPortObject inportToUpdate,outportToUpdate;
	
		public TestFlowEntry() {
			type = "flow_entry";
			
			clearUncommitedData();
		}
		
		public void commit() {
			if(stateToUpdate != null) { state = stateToUpdate; }
			if(typeToUpdate != null) { type = typeToUpdate; }
			if(entryIdToUpdate != null) { entryId = entryIdToUpdate; }
			if(dpidToUpdate != null) { dpid = dpidToUpdate; }
			if(userStateToUpdate != null) { userState = userStateToUpdate; }
			if(switchStateToUpdate != null) { switchState = switchStateToUpdate; }
			if(errorStateTypeToUpdate != null) { errorStateType = errorStateTypeToUpdate; }
			if(errorStateCodeToUpdate != null) { errorStateCode = errorStateCodeToUpdate; }
			if(matchSrcMacToUpdate != null) { matchSrcMac = matchSrcMacToUpdate; }
			if(matchDstMacToUpdate != null) { matchDstMac = matchDstMacToUpdate; }
			if(matchSrcIpaddrToUpdate != null) { matchSrcIpaddr = matchSrcIpaddrToUpdate; }
			if(matchDstIpaddrToUpdate != null) { matchDstIpaddr = matchDstIpaddrToUpdate; }
			if(matchInPortToUpdate != null) { matchInPort = matchInPortToUpdate; }
			if(matchEtherFrameTypeToUpdate != null) { matchEtherFrameType = matchEtherFrameTypeToUpdate; }
			if(actionOutputToUpdate != null) { actionOutput = actionOutputToUpdate; }
			
			if(flowPathToUpdate != null) { flowPath = flowPathToUpdate; }
			if(swToUpdate != null) { sw = swToUpdate; }
			if(inportToUpdate != null) { inport = inportToUpdate; }
			if(outportToUpdate != null) { outport = outportToUpdate; }
	
			clearUncommitedData();
		}
		
		public void rollback() {
			clearUncommitedData();
		}
		
		public void clearUncommitedData() {
			stateToUpdate = typeToUpdate = entryIdToUpdate = dpidToUpdate = null;
			userStateToUpdate = switchStateToUpdate = errorStateTypeToUpdate = errorStateCodeToUpdate = null;
			matchSrcMacToUpdate = matchDstMacToUpdate = matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
			matchInPortToUpdate = matchEtherFrameTypeToUpdate = actionOutputToUpdate = null;
			flowPathToUpdate = null;
			swToUpdate = null;
			inportToUpdate = outportToUpdate = null;
		}
		
		// Setter methods for test
		public void setStateForTest(String state) { this.state = state; }
		public void setTypeForTest(String type) { this.type = type; }
		public void setEntryIdForTest(String entryId) { this.entryId = entryId; }
		public void setDpidForTest(String dpid) { this.dpid = dpid; }
		public void setUserStateForTest(String userState) { this.userState = userState; }
		public void setSwitchStateForTest(String switchState) { this.switchState = switchState; }
		public void setErrorStateTypeForTest(String errorStateType) { this.errorStateType = errorStateType; }
		public void setErrorStateCodeForTest(String errorStateCode) { this.errorStateCode = errorStateCode; }
		public void setMatchSrcMacForTest(String matchSrcMac) { this.matchSrcMac = matchSrcMac; }
		public void setMatchDstMacForTest(String matchDstMac) { this.matchDstMac = matchDstMac; }
		public void setMatchSrcIpaddrForTest(String matchSrcIpaddr) { this.matchSrcIpaddr = matchSrcIpaddr; }
		public void setMatchDstIpaddrForTest(String matchDstIpaddr) { this.matchDstIpaddr = matchDstIpaddr; }
		public void setMatchInPortForTest(Short matchInPort) { this.matchInPort = matchInPort; }
		public void setMatchEtherFrameTypeForTest(Short matchEtherFrameType) { this.matchEtherFrameType = matchEtherFrameType; }
		public void setActionOutputForTest(Short actionOutput) { this.actionOutput = actionOutput; }
		public void setFlowPathForTest(IFlowPath flowPath) { this.flowPath = flowPath; }
		public void setSwitchForTest(ISwitchObject sw) { this.sw = sw; }
		public void setInportForTest(IPortObject inport) { this.inport = inport; }
		public void setOutportForTest(IPortObject outport) { this.outport = outport; }
		
		@Override
		public String getState() { return state; }
	
		@Override
		public void setState(String state) { stateToUpdate = state; }
	
		@Override
		public String getType() { return type; }
	
		@Override
		public void setType(String type) { typeToUpdate = type; }
	
		@Override
		public Vertex asVertex() {
			// TODO Auto-generated method stub
			return null;
		}
	
		@Override
		public String getFlowEntryId() { return entryId; }
	
		@Override
		public void setFlowEntryId(String flowEntryId) { entryIdToUpdate = flowEntryId; }
	
		@Override
		public String getSwitchDpid() { return dpid; }
	
		@Override
		public void setSwitchDpid(String switchDpid) { dpidToUpdate = switchDpid; }
	
		@Override
		public String getUserState() { return userState; }
	
		@Override
		public void setUserState(String userState) { userStateToUpdate = userState; }
	
		@Override
		public String getSwitchState() { return switchState; }
	
		@Override
		public void setSwitchState(String switchState) { switchStateToUpdate = switchState; }
	
		@Override
		public String getErrorStateType() { return errorStateType; }
	
		@Override
		public void setErrorStateType(String errorStateType) { errorStateTypeToUpdate = errorStateType; }
	
		@Override
		public String getErrorStateCode() { return errorStateCode; }
	
		@Override
		public void setErrorStateCode(String errorStateCode) { errorStateCodeToUpdate = errorStateCode; }
	
		@Override
		public Short getMatchInPort() { return matchInPort; }
	
		@Override
		public void setMatchInPort(Short matchInPort) { matchInPortToUpdate = matchInPort; }
	
		@Override
		public Short getMatchEthernetFrameType() {return matchEtherFrameType; }
	
		@Override
		public void setMatchEthernetFrameType(Short matchEthernetFrameType) { matchEtherFrameTypeToUpdate = matchEthernetFrameType; }
		
		@Override
		public String getMatchSrcMac() { return matchSrcMac; }
	
		@Override
		public void setMatchSrcMac(String matchSrcMac) { matchSrcMacToUpdate = matchSrcMac; }
	
		@Override
		public String getMatchDstMac() { return matchDstMac; }
	
		@Override
		public void setMatchDstMac(String matchDstMac) { matchDstMacToUpdate = matchDstMac; }
	
		@Override
		public String getMatchSrcIPv4Net() { return matchSrcIpaddr; }
	
		@Override
		public void setMatchSrcIPv4Net(String matchSrcIPv4Net) { matchSrcIpaddrToUpdate = matchSrcIPv4Net; }
	
		@Override
		public String getMatchDstIPv4Net() { return matchDstIpaddr; }
	
		@Override
		public void setMatchDstIPv4Net(String matchDstIPv4Net) { matchDstIpaddrToUpdate = matchDstIPv4Net; }
	
		@Override
		public Short getActionOutput() { return actionOutput; }
	
		@Override
		public void setActionOutput(Short actionOutput) { actionOutputToUpdate = actionOutput; }
	
		@Override
		public IFlowPath getFlow() { return flowPath; }
	
		@Override
		public void setFlow(IFlowPath flow) { flowPathToUpdate = flow; }
	
		@Override
		public ISwitchObject getSwitch() { return sw; }
	
		@Override
		public void setSwitch(ISwitchObject sw) { swToUpdate = sw; }
	
		@Override
		public IPortObject getInPort() { return inport; }
	
		@Override
		public void setInPort(IPortObject port) { inportToUpdate = port; }
	
		@Override
		public IPortObject getOutPort() { return outport; }
	
		@Override
		public void setOutPort(IPortObject port) { outportToUpdate = port; }
	}


	public TestableGraphDBOperation() {
		super(EasyMock.createNiceMock(GraphDBConnection.class));
		
		switches = new ArrayList<TestSwitchObject>();
		ports = new ArrayList<TestPortObject>();
		devices = new ArrayList<TestDeviceObject>();
		paths = new ArrayList<TestFlowPath>();
		entries = new ArrayList<TestFlowEntry>();
		
		switchesToAdd = new ArrayList<TestSwitchObject>();
		portsToAdd = new ArrayList<TestPortObject>();
		devicesToAdd = new ArrayList<TestDeviceObject>();
		pathsToAdd = new ArrayList<TestFlowPath>();
		entriesToAdd = new ArrayList<TestFlowEntry>();

		switchesToRemove = new ArrayList<TestSwitchObject>();
		portsToRemove = new ArrayList<TestPortObject>();
		devicesToRemove = new ArrayList<TestDeviceObject>();
		pathsToRemove = new ArrayList<TestFlowPath>();
		entriesToRemove = new ArrayList<TestFlowEntry>();
		
		clearUncommitedData();
	}
	
	private void clearUncommitedData() {
		for(TestFlowEntry flow : entries) {
			flow.clearUncommitedData();
		}
		for(TestFlowEntry flow : entriesToAdd) {
			flow.clearUncommitedData();
		}
		
		for(TestDeviceObject dev : devices) {
			dev.clearUncommitedData();
		}
		for(TestDeviceObject dev : devicesToAdd) {
			dev.clearUncommitedData();
		}
		
		for(TestSwitchObject sw : switches) {
			sw.clearUncommitedData();
		}
		for(TestSwitchObject sw : switchesToAdd) {
			sw.clearUncommitedData();
		}
		
		for(TestPortObject port : ports) {
			port.clearUncommitedData();
		}
		for(TestPortObject port : portsToAdd) {
			port.clearUncommitedData();
		}
		
		entriesToAdd.clear();
		entriesToRemove.clear();
		devicesToAdd.clear();
		devicesToRemove.clear();
		switchesToAdd.clear();
		switchesToRemove.clear();
		portsToAdd.clear();
		portsToRemove.clear();
	}
	
	
	// this.*ForTest() methods below are supposed to be used for creation of test topology.
	/**
	 * Create new empty TestSwitchObject.
	 * @return New TestSwitchObject
	 */
	public TestSwitchObject createNewSwitchForTest() {
		TestSwitchObject sw = new TestSwitchObject();
		switches.add(sw);
		return sw;
	}
	
	/**
	 * Create new TestSwitchObject with specific DPID.
	 * @param dpid DPID to be set
	 * @return New TestSwitchObject
	 */
	public TestSwitchObject createNewSwitchForTest(String dpid) {
		for(TestSwitchObject sw_loop : switches) {
			if(sw_loop.getDPID().equals(dpid)) {
				// Already created
				log.error("switch already exists : " + dpid);
				return sw_loop;
			}
		}

		TestSwitchObject sw = new TestSwitchObject();
		
		sw.setDpidForTest(dpid);
		switches.add(sw);
		
		return sw;
	}
	
	/**
	 * Create new empty TestPortObject.
	 * @return New TestPortObject
	 */
	public TestPortObject createNewPortForTest() {
		TestPortObject port = new TestPortObject();
		ports.add(port);
		return port;
	}
	
	/**
	 * Create new TestPortObject with specific DPID and port number.
	 * @param dpid DPID to be set
	 * @param number Port number to be set
	 * @return New TestPortObject
	 */
	public TestPortObject createNewPortForTest(String dpid, Short number) {
		TestSwitchObject sw = null;
		
		for(TestSwitchObject sw_loop : switches) {
			if(sw_loop.getDPID().equals(dpid)) {
				sw = sw_loop;
			}
		}
		
		if(sw != null) {
			TestPortObject port = new TestPortObject();
			port.setNumberForTest(number);
			port.setSwitchForTest(sw);
			sw.addPortForTest(port);
			
			ports.add(port);

			return port;
		} else {
			return  null;
		}
	}
	
	/**
	 * Link a TestPortObject to other TestPortObject.
	 * @param src TestPortObjecgt of source port.
	 * @param dst TestPortObjecgt of destination port.
	 */
	public void setLinkBetweenPortsForTest(TestPortObject src, TestPortObject dst) {
		src.addLinkedPortForTest(dst);
	}
	
	/**
	 * Create new empty TestDeviceObject.
	 * @return New TestDeviceObject
	 */
	public TestDeviceObject createNewDeviceForTest() {
		TestDeviceObject dev = new TestDeviceObject();
		
		return dev;
	}
	
	/**
	 * Create new empty TestFlowPathObject.
	 * @return New TestFlowPathObject
	 */
	public TestFlowPath createNewFlowPathForTest() {
		TestFlowPath path = new TestFlowPath();
		paths.add(path);
		return path;
	}

	/**
	 * Create new empty TestFlowEntryObject.
	 * @return New TestFlowEntryObject
	 */
	public TestFlowEntry createNewFlowEntryForTest() {
		TestFlowEntry entry = new TestFlowEntry();
		entries.add(entry);
		return entry;
	}

	
	public boolean hasLinkBetween(String srcSw_str, Short srcNumber, String dstSw_str, Short dstNumber) {
		IPortObject srcPort = null, dstPort = null;
		long srcSw = HexString.toLong(srcSw_str);
		long dstSw = HexString.toLong(dstSw_str);
		
		for(TestSwitchObject sw : switches) {
			long swLong = HexString.toLong(sw.getDPID());
			if(swLong == srcSw) {
				for(IPortObject port : sw.getPorts()) {
					if(port.getNumber().equals(srcNumber)) {
						srcPort = port;
					}
				}
			} else if(swLong == dstSw) {
				for(IPortObject port : sw.getPorts()) {
					if(port.getNumber().equals(dstNumber)) {
						dstPort = port;
					}
				}
			}
		}
		
		if(srcPort != null && dstPort != null) {
			for(IPortObject port : srcPort.getLinkedPorts()) {
				if(port.equals(dstPort)) {
					return true;
				}
			}
		}
		
		return false;
	}

	// Overriding methods below are to mock GraphDBOperation class.
	@Override
	public ISwitchObject newSwitch(String dpid) {
		TestSwitchObject sw = new TestSwitchObject();
		sw.setDPID(dpid);
		switchesToAdd.add(sw);
		
		return sw;
	}

	@Override
	public ISwitchObject searchSwitch(String dpid_str) {
		Long dpid = HexString.toLong(dpid_str);
		
		for(ISwitchObject sw : switches) {
			if(HexString.toLong(sw.getDPID()) == dpid) {
				return sw;
			}
		}
		return null;
	}

	@Override
	public ISwitchObject searchActiveSwitch(String dpid_str) {
		Long dpid = HexString.toLong(dpid_str);

		for(ISwitchObject sw : switches) {
			if(HexString.toLong(sw.getDPID()) == dpid && sw.getState().equals("ACTIVE")) {
				return sw;
			}
		}
		return null;
	}

	@Override
	public Iterable<ISwitchObject> getActiveSwitches() {
		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
		
		for(ISwitchObject sw : switches) {
			if(sw.getState() != null && sw.getState().equals("ACTIVE")) {
				list.add(sw);
			}
		}
		return list.isEmpty() ? null : list;
	}

	@Override
	public Iterable<ISwitchObject> getAllSwitches() {
		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
		
		for(ISwitchObject sw : switches) {
			list.add(sw);
		}
		
		return list.isEmpty() ? null : list;
	}

	@Override
	public Iterable<ISwitchObject> getInactiveSwitches() {
		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
		
		for(ISwitchObject sw : switches) {
			if(! sw.getState().equals("ACTIVE")) {
				list.add(sw);
			}
		}
		return list.isEmpty() ? null : list;
	}

	@Override
	public Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries() {
		List<IFlowEntry> list = new ArrayList<IFlowEntry>();
		
		for(TestFlowEntry entry : entries) {
			if(entry.getSwitchState().equals("FE_SWITCH_NOT_UPDATED")) {
				list.add(entry);
			}
		}
		return list;
	}

	@Override
	public void removeSwitch(ISwitchObject sw) {
		if(switches.contains(sw)) {
			switchesToRemove.add((TestSwitchObject)sw);
		}
	}

	@Override
	public IPortObject newPort(Short portNumber) {
		TestPortObject port = new TestPortObject();
		port.setNumber(portNumber);
		
		return port;
	}

	public IPortObject newPort(Long dpid, Short portNumber) {
		TestPortObject port = null;
		TestSwitchObject sw = (TestSwitchObject)searchSwitch(HexString.toHexString(dpid));
		
		if(sw != null) {
			port = (TestPortObject)newPort(portNumber);
			portsToAdd.add(port);
			sw.addPort(port);
		}
		
		return port;
	}
	
	@Override
	public IPortObject searchPort(String dpid_str, Short number) {
		long dpid = HexString.toLong(dpid_str);
		
		for(TestSwitchObject sw : switches) {
			if(HexString.toLong(sw.getDPID()) == dpid) {
				for(IPortObject port : sw.getPorts()) {
					if(port.getNumber().equals(number)) {
						return port;
					}
				}
			}
		}
		return null;
	}

	@Override
	public void removePort(IPortObject port) {
		for(TestSwitchObject sw : switches) {
			for(IPortObject pt : sw.getPorts()) {
				if(pt.equals(port)) {
					sw.removePort(port);
				}
			}
		}
		portsToRemove.add((TestPortObject)port);
	}

	@Override
	public IDeviceObject newDevice() {
		TestDeviceObject dev = new TestDeviceObject();
		devicesToAdd.add(dev);
		
		return dev;
	}

	@Override
	public IDeviceObject searchDevice(String macAddr) {
		for(IDeviceObject dev : devices) {
			if(dev.getMACAddress().equals(macAddr)) {
				return dev;
			}
		}
		return null;
	}

	@Override
	public Iterable<IDeviceObject> getDevices() {
		List<IDeviceObject> list = new ArrayList<IDeviceObject>();
		
		for(TestDeviceObject dev : devices) {
			list.add(dev);
		}
		
		return list;
	}

	@Override
	public void removeDevice(IDeviceObject dev) {
		if(devices.contains((TestDeviceObject)dev)) {
			devicesToRemove.add((TestDeviceObject)dev);
		}
	}

	@Override
	public IFlowPath newFlowPath() {
		TestFlowPath path = new TestFlowPath();
		pathsToAdd.add(path);
		
		return path;
	}

	@Override
	public IFlowPath searchFlowPath(FlowId flowId) {
		for(IFlowPath path : paths) {
			if(path.getFlowId().equals(flowId)) {
				return path;
			}
		}
		return null;
	}

	@Override
	public IFlowPath getFlowPathByFlowEntry(IFlowEntry flowEntry) {
		for(IFlowPath path : paths) {
			for(IFlowEntry entry : path.getFlowEntries()) {
				if(entry.equals(flowEntry)) {
					return path;
				}
			}

		}
		return null;
	}

	@Override
	public Iterable<IFlowPath> getAllFlowPaths() {
		List<IFlowPath> list = new ArrayList<IFlowPath>();
		
		for(IFlowPath path : paths) {
			list.add(path);
		}
		
		return list;
	}

	@Override
	public void removeFlowPath(IFlowPath flowPath) {
		if(paths.contains((TestFlowPath)flowPath)) {
			pathsToRemove.add((TestFlowPath)flowPath);
		}
	}

	@Override
	public IFlowEntry newFlowEntry() {
		TestFlowEntry entry = new TestFlowEntry();
		entriesToAdd.add(entry);
		return entry;
	}

	@Override
	public IFlowEntry searchFlowEntry(FlowEntryId flowEntryId) {
		for(TestFlowEntry entry : entries) {
			// TODO check if this matching works
			if(entry.getFlowEntryId().equals(flowEntryId)) {
				return entry;
			}
		}
		return null;
	}

	@Override
	public Iterable<IFlowEntry> getAllFlowEntries() {
		List<IFlowEntry> list = new ArrayList<IFlowEntry>();
		
		for(TestFlowEntry entry : entries) {
			list.add(entry);
		}
		
		return list;
	}

	@Override
	public void removeFlowEntry(IFlowEntry flowEntry) {
		if(entries.contains((TestFlowEntry)flowEntry)) {
			entriesToRemove.add((TestFlowEntry)flowEntry);
		}
	}

	@Override
	public IDBConnection getDBConnection() {
		return super.getDBConnection();
	}

	@Override
	public void commit() {
		for(TestSwitchObject sw : switchesToAdd) {
			switches.add(sw);
		}
		for(TestSwitchObject sw : switchesToRemove) {
			sw.commit();
			switches.remove(sw);
		}
		for(TestSwitchObject sw : switches) {
			sw.commit();
		}
		
		for(TestPortObject port : portsToAdd) {
			ports.add(port);
		}
		for(TestPortObject port : portsToRemove) {
			port.commit();
			ports.remove(port);
		}
		for(TestPortObject port : ports) {
			port.commit();
		}
		
		for(TestDeviceObject dev : devicesToAdd) {
			devices.add(dev);
		}
		for(TestDeviceObject dev : devicesToRemove) {
			dev.commit();
			devices.remove(dev);
		}
		for(TestDeviceObject dev : devices) {
			dev.commit();
		}
		
		clearUncommitedData();
	}

	@Override
	public void rollback() {
		clearUncommitedData();
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub

	}
}
