splitting roles from IO loop and providing a abstract of switch
diff --git a/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
new file mode 100644
index 0000000..976e347
--- /dev/null
+++ b/of/ctl/src/main/java/org/onlab/onos/of/controller/impl/internal/OpenFlowControllerImpl.java
@@ -0,0 +1,263 @@
+package org.onlab.onos.of.controller.impl.internal;
+
+import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.of.controller.Dpid;
+import org.onlab.onos.of.controller.OpenFlowController;
+import org.onlab.onos.of.controller.OpenFlowSwitch;
+import org.onlab.onos.of.controller.OpenFlowSwitchListener;
+import org.onlab.onos.of.controller.PacketListener;
+import org.onlab.onos.of.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+@Service
+public class OpenFlowControllerImpl implements OpenFlowController {
+
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> connectedSwitches;
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeMasterSwitches;
+    protected ConcurrentHashMap<Long, OpenFlowSwitch> activeEqualSwitches;
+
+    protected OpenFlowSwitchAgent agent = new OpenFlowSwitchAgent();
+    protected ArrayList<OpenFlowSwitchListener> ofEventListener;
+
+    private final Controller ctrl = new Controller();
+
+    @Activate
+    public void activate() {
+        ctrl.start(agent);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        ctrl.stop();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getSwitches() {
+        return connectedSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getMasterSwitches() {
+        return activeMasterSwitches.values();
+    }
+
+    @Override
+    public Iterable<OpenFlowSwitch> getEqualSwitches() {
+        return activeEqualSwitches.values();
+    }
+
+    @Override
+    public OpenFlowSwitch getSwitch(Dpid dpid) {
+        return connectedSwitches.get(dpid.value());
+    }
+
+    @Override
+    public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
+        return activeMasterSwitches.get(dpid.value());
+    }
+
+    @Override
+    public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
+        return activeEqualSwitches.get(dpid.value());    }
+
+    @Override
+    public void addListener(OpenFlowSwitchListener listener) {
+        if (!ofEventListener.contains(listener)) {
+            this.ofEventListener.add(listener);
+        }
+    }
+
+    @Override
+    public void removeListener(OpenFlowSwitchListener listener) {
+        this.ofEventListener.remove(listener);
+    }
+
+    @Override
+    public void addPacketListener(int priority, PacketListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void removePacketListener(PacketListener listener) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void write(Dpid dpid, OFMessage msg) {
+        this.getSwitch(dpid).write(msg);
+    }
+
+    @Override
+    public void processPacket(OFMessage msg) {
+    }
+
+    @Override
+    public void setRole(Dpid dpid, RoleState role) {
+        switch (role) {
+        case MASTER:
+            agent.transitionToMasterSwitch(dpid.value());
+            break;
+        case EQUAL:
+            agent.transitionToEqualSwitch(dpid.value());
+            break;
+        case SLAVE:
+            //agent.transitionToSlaveSwitch(dpid.value());
+            break;
+        default:
+            //WTF role is this?
+        }
+
+    }
+
+    public class OpenFlowSwitchAgent {
+
+        private final Logger log = LoggerFactory.getLogger(OpenFlowSwitchAgent.class);
+        private Lock switchLock = new ReentrantLock();
+
+        public boolean addConnectedSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            if (connectedSwitches.get(dpid) != null) {
+                log.error("Trying to add connectedSwitch but found a previous "
+                        + "value for dpid: {}", dpid);
+                return false;
+            } else {
+                log.error("Added switch {}", dpid);
+                connectedSwitches.put(dpid, sw);
+                for (OpenFlowSwitchListener l : ofEventListener) {
+                    l.switchAdded(new Dpid(dpid));
+                }
+                return true;
+            }
+        }
+
+        private boolean validActivation(long dpid) {
+            if (connectedSwitches.get(dpid) == null) {
+                log.error("Trying to activate switch but is not in "
+                        + "connected switches: dpid {}. Aborting ..",
+                        HexString.toHexString(dpid));
+                return false;
+            }
+            if (activeMasterSwitches.get(dpid) != null ||
+                    activeEqualSwitches.get(dpid) != null) {
+                log.error("Trying to activate switch but it is already "
+                        + "activated: dpid {}. Found in activeMaster: {} "
+                        + "Found in activeEqual: {}. Aborting ..", new Object[] {
+                                HexString.toHexString(dpid),
+                                (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
+                                (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
+                return false;
+            }
+            return true;
+        }
+
+        /**
+         * Called when a switch is activated, with this controller's role as MASTER.
+         */
+        protected boolean addActivatedMasterSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                if (!validActivation(dpid)) {
+                    return false;
+                }
+                activeMasterSwitches.put(dpid, sw);
+                return true;
+            } finally {
+                switchLock.unlock();
+            }
+    }
+
+        /**
+         * Called when a switch is activated, with this controller's role as EQUAL.
+         */
+        protected boolean addActivatedEqualSwitch(long dpid, AbstractOpenFlowSwitch sw) {
+            switchLock.lock();
+            try {
+                    if (!validActivation(dpid)) {
+                        return false;
+                    }
+                    activeEqualSwitches.put(dpid, sw);
+                    return true;
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+        /**
+         * Called when this controller's role for a switch transitions from equal
+         * to master. For 1.0 switches, we internally refer to the role 'slave' as
+         * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
+         */
+        protected void transitionToMasterSwitch(long dpid) {
+            switchLock.lock();
+            try {
+                OpenFlowSwitch sw = activeEqualSwitches.remove(dpid);
+                if (sw == null) {
+                    log.error("Transition to master called on sw {}, but switch "
+                            + "was not found in controller-cache", dpid);
+                    return;
+                }
+                activeMasterSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
+        }
+
+
+        /**
+         * Called when this controller's role for a switch transitions to equal.
+         * For 1.0 switches, we internally refer to the role 'slave' as
+         * 'equal'.
+         */
+        protected void transitionToEqualSwitch(long dpid) {
+            switchLock.lock();
+            try {
+                OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+                if (sw == null) {
+                    log.error("Transition to equal called on sw {}, but switch "
+                            + "was not found in controller-cache", dpid);
+                    return;
+                }
+                activeEqualSwitches.put(dpid, sw);
+            } finally {
+                switchLock.unlock();
+            }
+
+        }
+
+        /**
+         * Clear all state in controller switch maps for a switch that has
+         * disconnected from the local controller. Also release control for
+         * that switch from the global repository. Notify switch listeners.
+         */
+        public void removeConnectedSwitch(long dpid) {
+            connectedSwitches.remove(dpid);
+            OpenFlowSwitch sw = activeMasterSwitches.remove(dpid);
+            if (sw == null) {
+                sw = activeEqualSwitches.remove(dpid);
+            }
+            for (OpenFlowSwitchListener l : ofEventListener) {
+                l.switchRemoved(new Dpid(dpid));
+            }
+        }
+
+        public void processMessage(OFMessage m) {
+            processPacket(m);
+        }
+    }
+
+
+
+}