Renamed SDN-IP packages and classes.

The code use to use the name 'BgpRoute' in a number of places, which is not
descriptive and doesn't map to how we talk about SDN-IP (we always call it
SDN-IP in all other documents/presentations).

Details of changes are as follows:

net.onrc.onos.apps.bgproute -> net.onrc.onos.apps.sdnip
    BgpRoute.java -> SdnIp.java
    IBgpRouteService.java -> ISdnIpService.java

created new package for web classes: net.onrc.onos.apps.sdnip.web
    BgpRouteResource.java -> IncomingRequestResource.java
    BgpRouteResourceSynch.java -> OutgoingRequestResource.java
    BgpRouteWebRoutable.java -> SdnIpWebRoutable.java

Change-Id: Ie6b1cbe4e95736d4cbd53b9f4def7cc3e0b46132
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/FlowCache.java b/src/main/java/net/onrc/onos/apps/sdnip/FlowCache.java
new file mode 100644
index 0000000..8c518d7
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/sdnip/FlowCache.java
@@ -0,0 +1,164 @@
+package net.onrc.onos.apps.sdnip;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPort;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FlowCache {
+    private static final Logger log = LoggerFactory.getLogger(FlowCache.class);
+
+    private final IFloodlightProviderService floodlightProvider;
+
+    private final Map<Long, List<OFFlowMod>> flowCacheMap;
+
+    private final Comparator<OFFlowMod> cookieComparator =
+            new Comparator<OFFlowMod>() {
+        @Override
+        public int compare(OFFlowMod fm1, OFFlowMod fm2) {
+            long difference = fm2.getCookie() - fm1.getCookie();
+
+            if (difference > 0) {
+                return 1;
+            } else if (difference < 0) {
+                return -1;
+            } else {
+                return 0;
+            }
+        }
+    };
+
+    public FlowCache(IFloodlightProviderService floodlightProvider) {
+        this.floodlightProvider = floodlightProvider;
+
+        flowCacheMap = new HashMap<Long, List<OFFlowMod>>();
+    }
+
+    public void write(long dpid, OFFlowMod flowMod) {
+        synchronized (this) {
+            List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
+            flowModList.add(flowMod);
+            write(dpid, flowModList);
+        }
+    }
+
+    public void write(long dpid, List<OFFlowMod> flowMods) {
+        synchronized (this) {
+            ensureCacheForSwitch(dpid);
+
+            List<OFFlowMod> clones = new ArrayList<OFFlowMod>(flowMods.size());
+
+            // Somehow the OFFlowMods we get passed in will change later on.
+            // No idea how this happens, but we can just clone to prevent problems
+            try {
+                for (OFFlowMod fm : flowMods) {
+                    clones.add(fm.clone());
+                }
+            } catch (CloneNotSupportedException e) {
+                log.debug("Clone exception", e);
+            }
+
+            flowCacheMap.get(dpid).addAll(clones);
+
+            IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+
+            if (sw == null) {
+                log.debug("Switch not found when writing flow mods");
+                return;
+            }
+
+            List<OFMessage> msgList = new ArrayList<OFMessage>(clones.size());
+            msgList.addAll(clones);
+
+            try {
+                sw.write(msgList, null);
+            } catch (IOException e) {
+                log.error("Error writing to switch", e);
+            }
+        }
+    }
+
+    public void delete(long dpid, OFFlowMod flowMod) {
+        synchronized (this) {
+            List<OFFlowMod> flowModList = new ArrayList<OFFlowMod>(1);
+            flowModList.add(flowMod);
+            delete(dpid, flowModList);
+        }
+    }
+
+    public void delete(long dpid, List<OFFlowMod> flowMods) {
+        synchronized (this) {
+            ensureCacheForSwitch(dpid);
+
+            // Remove the flow mods from the cache first before we alter them
+            flowCacheMap.get(dpid).removeAll(flowMods);
+
+            // Alter the original flow mods to make them delete flow mods
+            for (OFFlowMod fm : flowMods) {
+                fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT)
+                        .setOutPort(OFPort.OFPP_NONE)
+                        .setLengthU(OFFlowMod.MINIMUM_LENGTH);
+
+                fm.getActions().clear();
+            }
+
+            IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+            if (sw == null) {
+                log.debug("Switch not found when writing flow mods");
+                return;
+            }
+
+            List<OFMessage> msgList = new ArrayList<OFMessage>(flowMods.size());
+            msgList.addAll(flowMods);
+
+            try {
+                sw.write(msgList, null);
+            } catch (IOException e) {
+                log.error("Error writing to switch", e);
+            }
+        }
+    }
+
+    public void switchConnected(IOFSwitch sw) {
+        synchronized (this) {
+            log.debug("Switch connected: {}", sw);
+
+            ensureCacheForSwitch(sw.getId());
+
+            List<OFFlowMod> flowMods = flowCacheMap.get(sw.getId());
+
+            Collections.sort(flowMods, cookieComparator);
+
+            sw.clearAllFlowMods();
+
+            List<OFMessage> messages = new ArrayList<OFMessage>(flowMods.size());
+            messages.addAll(flowMods);
+
+            try {
+                sw.write(messages, null);
+            } catch (IOException e) {
+                log.error("Failure writing flow mods to switch {}",
+                        HexString.toHexString(sw.getId()));
+            }
+        }
+    }
+
+    private void ensureCacheForSwitch(long dpid) {
+        if (!flowCacheMap.containsKey(dpid)) {
+            flowCacheMap.put(dpid, new ArrayList<OFFlowMod>());
+        }
+    }
+}