Fixed "Intent" problem: Add flow removed event by using "DEL_ACK".
Fixed "Fowarding" to make it work on changed "Intent".
Did cleanup some of "Intent" measurement code.
Deleted unused receiver in FlowProgrammer.java.

Memo:
ReactiveForwarding can set idle timeout.
You can specify it from 1 ~ second.
Out of this range, the application set it to 5 sec (default).

Sample: (in onos.properties file)
net.onrc.onos.apps.forwarding.Forwarding.idletimeout = 5

When you test, please be careful we only set the value to the first switch and the other switches has +2 second idle timeout values.

Change-Id: I1b261a8c771356a412af004c7c0cd93b539ebba7
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index 9fd8870..e59b33c 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -68,7 +68,8 @@
     private ITopologyService topologyService;
     private Topology topology;
     private IPathCalcRuntimeService pathRuntime;
-    private IntentMap intentMap;
+    private IntentMap pathIntentMap;
+    private IntentMap highLevelIntentMap;
 
     // TODO it seems there is a Guava collection that will time out entries.
     // We should see if this will work here.
@@ -191,8 +192,9 @@
         packetService.registerPacketListener(this);
 
         topology = topologyService.getTopology();
-        intentMap = pathRuntime.getPathIntents();
-        intentMap.addChangeListener(this);
+        highLevelIntentMap = pathRuntime.getHighLevelIntents();
+        pathIntentMap = pathRuntime.getPathIntents();
+        pathIntentMap.addChangeListener(this);
     }
 
     @Override
@@ -273,7 +275,7 @@
 
     private void continueHandlePacketIn(Switch sw, Port inPort, Ethernet eth, Device deviceObject) {
 
-        log.debug("Start continuehandlePacketIn");
+        log.trace("Start continuehandlePacketIn");
 
         //Iterator<IPortObject> ports = deviceObject.getAttachedPorts().iterator();
         Iterator<net.onrc.onos.core.topology.Port> ports = deviceObject.getAttachmentPoints().iterator();
@@ -300,10 +302,12 @@
 
         MACAddress srcMacAddress = MACAddress.valueOf(eth.getSourceMACAddress());
         MACAddress dstMacAddress = MACAddress.valueOf(eth.getDestinationMACAddress());
+        Path pathspec = new Path(srcMacAddress, dstMacAddress);
+        IntentOperationList operations = new IntentOperationList();
 
         synchronized (lock) {
             //TODO check concurrency
-            Path pathspec = new Path(srcMacAddress, dstMacAddress);
+
             PushedFlow existingFlow = pendingFlows.get(pathspec);
 
             //A path is installed side by side to reduce a path timeout and a wrong state.
@@ -323,23 +327,58 @@
                     // Flow has been sent to the switches so it is safe to
                     // send a packet out now
 
-                    Intent intent = intentMap.getIntent(existingFlow.intentId);
-                    PathIntent pathIntent = null;
-                    if (intent instanceof PathIntent) {
-                        pathIntent = (PathIntent) intent;
+                    // TODO Here highLevelIntentMap and pathIntentMap would be problem,
+                    // because it doesn't have global information as of May 2014.
+                    // However usually these lines here is used when we got packet-in and this class think
+                    // the path for the packet is installed already, so it is pretty rare.
+                    // I will leave it for now, and will work in the next step.
+                    Intent highLevelIntent = highLevelIntentMap.getIntent(existingFlow.intentId);
+                    if (highLevelIntent == null) {
+                        log.debug("Intent ID {} is null in HighLevelIntentMap. return.", existingFlow.intentId);
+                        return;
+                    }
+
+                    if (highLevelIntent.getState() != IntentState.INST_ACK) {
+                        log.debug("Intent ID {}'s state is not INST_ACK. return.", existingFlow.intentId);
+                        return;
+                    }
+
+                    ShortestPathIntent spfIntent = null;
+                    if (highLevelIntent instanceof ShortestPathIntent) {
+                        spfIntent = (ShortestPathIntent) highLevelIntent;
                     } else {
                         log.debug("Intent ID {} is not PathIntent or null. return.", existingFlow.intentId);
                         return;
                     }
 
-                    Boolean isflowEntryForThisSwitch = false;
+                    PathIntent pathIntent = (PathIntent) pathIntentMap.getIntent(spfIntent.getPathIntentId());
+                    if (pathIntent == null) {
+                        log.debug("PathIntent ID {} is null in PathIntentMap. return.", existingFlow.intentId);
+                        return;
+                    }
+
+                    if (pathIntent.getState() != IntentState.INST_ACK) {
+                        log.debug("Intent ID {}'s state is not INST_ACK. return.", existingFlow.intentId);
+                        return;
+                    }
+
+                    boolean isflowEntryForThisSwitch = false;
                     net.onrc.onos.core.intent.Path path = pathIntent.getPath();
+                    long outPort = -1;
+
+                    if (spfIntent.getDstSwitchDpid() == sw.getDpid()) {
+                        log.trace("The packet-in sw dpid {} is on the path.", sw.getDpid());
+                        isflowEntryForThisSwitch = true;
+                        outPort = spfIntent.getDstPortNumber();
+                    }
 
                     for (Iterator<LinkEvent> i = path.iterator(); i.hasNext();) {
                         LinkEvent le = i.next();
+
                         if (le.getSrc().dpid.equals(sw.getDpid())) {
-                            log.debug("src {} dst {}", le.getSrc(), le.getDst());
+                            log.trace("The packet-in sw dpid {} is on the path.", sw.getDpid());
                             isflowEntryForThisSwitch = true;
+                            outPort = le.getSrc().getNumber();
                             break;
                         }
                     }
@@ -352,25 +391,24 @@
                                 existingFlow.intentId,
                                 srcMacAddress, dstMacAddress);
                     } else {
-                        log.debug("Sending packet out from sw {}, outport{}", sw, existingFlow.firstOutPort);
+                        if (outPort < 0) {
+                            outPort = existingFlow.firstOutPort;
+                        }
 
+                        log.debug("Sending packet out from sw {}, outport{}", sw.getDpid(), outPort);
                         packetService.sendPacket(eth, new SwitchPort(
-                                        sw.getDpid(), existingFlow.firstOutPort));
+                                sw.getDpid(), (short) outPort));
                     }
                 } else {
                     // Flow path has not yet been installed to switches so save the
                     // packet out for later
-                    log.debug("Put a packet into the waiting list. flowId {}", existingFlow.intentId);
+                    log.trace("Put a packet into the waiting list. flowId {}", existingFlow.intentId);
                     waitingPackets.put(existingFlow.intentId, new PacketToPush(eth, sw.getDpid()));
                 }
                 return;
             }
 
-            log.debug("Adding new flow between {} at {} and {} at {}",
-                    new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
-
-            String intentId = callerId + ":" + controllerRegistryService.getNextUniqueId();
-            IntentOperationList operations = new IntentOperationList();
+            String intentId = Long.toString(controllerRegistryService.getNextUniqueId());
             ShortestPathIntent intent = new ShortestPathIntent(intentId,
                     sw.getDpid(), inPort.getNumber(), srcMacAddress.toLong(),
                     destinationDpid, destinationPort, dstMacAddress.toLong());
@@ -379,14 +417,16 @@
             intent.setFirstSwitchIdleTimeout(idleTimeout);
             IntentOperation.Operator operator = IntentOperation.Operator.ADD;
             operations.add(operator, intent);
-            pathRuntime.executeIntentOperations(operations);
-            // Add to waiting lists
-            pendingFlows.put(pathspec, new PushedFlow(intentId));
-            log.debug("Put a Path {} in the pending flow, intent ID {}", pathspec, intentId);
-            waitingPackets.put(intentId, new PacketToPush(eth, sw.getDpid()));
-            log.debug("Put a Packet in the wating list. related pathspec {}", pathspec);
+            log.debug("Adding new flow between {} at {} and {} at {}",
+                    new Object[]{srcMacAddress, srcSwitchPort, dstMacAddress, dstSwitchPort});
 
+             // Add to waiting lists
+            waitingPackets.put(intentId, new PacketToPush(eth, sw.getDpid()));
+            log.trace("Put a Packet in the wating list. intent ID {}, related pathspec {}", intentId, pathspec);
+            pendingFlows.put(pathspec, new PushedFlow(intentId));
+            log.trace("Put a Path {} in the pending flow, intent ID {}", pathspec, intentId);
         }
+        pathRuntime.executeIntentOperations(operations);
     }
 
     @Override
@@ -406,7 +446,6 @@
         MACAddress srcMacAddress = MACAddress.valueOf(spfIntent.getSrcMac());
         MACAddress dstMacAddress = MACAddress.valueOf(spfIntent.getDstMac());
         Path removedPath = new Path(srcMacAddress, dstMacAddress);
-
         synchronized (lock) {
             // There *shouldn't* be any packets queued if the flow has
             // just been removed.
@@ -414,6 +453,7 @@
             if (!packets.isEmpty()) {
                 log.warn("Removed flow {} has packets queued.", spfIntent.getId());
             }
+
             pendingFlows.remove(removedPath);
             log.debug("Removed from the pendingFlow: Path {}, Flow ID {}", removedPath, spfIntent.getId());
         }
@@ -484,7 +524,7 @@
     public void intentsChange(LinkedList<ChangedEvent> events) {
         for (ChangedEvent event : events) {
             log.debug("path intent ID {}, eventType {}", event.intent.getId() , event.eventType);
-            PathIntent pathIntent = (PathIntent) intentMap.getIntent(event.intent.getId());
+            PathIntent pathIntent = (PathIntent) pathIntentMap.getIntent(event.intent.getId());
             if (pathIntent == null) {
                 continue;
             }