Merged master fixed conflict.

Change-Id: I1260048f4cc90c422ce6033d506c25ec38d6cc3a
diff --git a/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java b/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
index 61ea43d..0e28795 100644
--- a/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/WipeOutCommand.java
@@ -21,6 +21,8 @@
 import org.onosproject.net.Host;
 import org.onosproject.net.Link;
 import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.group.GroupService;
 import org.onosproject.net.host.HostAdminService;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentService;
@@ -28,6 +30,11 @@
 import org.onosproject.net.link.LinkAdminService;
 import org.onosproject.net.region.RegionAdminService;
 import org.onosproject.ui.UiTopoLayoutService;
+import java.util.EnumSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import static org.onosproject.net.intent.IntentState.FAILED;
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
 
 /**
  * Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
@@ -37,7 +44,7 @@
 public class WipeOutCommand extends ClustersListCommand {
 
     private static final String PLEASE = "please";
-
+    private static final EnumSet<IntentState> CAN_PURGE = EnumSet.of(WITHDRAWN, FAILED);
     @Argument(index = 0, name = "please", description = "Confirmation phrase",
             required = false, multiValued = false)
     String please = null;
@@ -51,6 +58,8 @@
 
         wipeOutIntents();
         wipeOutHosts();
+        wipeOutFlows();
+        wipeOutGroups();
         wipeOutDevices();
         wipeOutLinks();
 
@@ -61,11 +70,38 @@
     private void wipeOutIntents() {
         print("Wiping intents");
         IntentService intentService = get(IntentService.class);
+        final CountDownLatch withdrawLatch;
+        withdrawLatch = new CountDownLatch(1);
         for (Intent intent : intentService.getIntents()) {
             if (intentService.getIntentState(intent.key()) != IntentState.WITHDRAWN) {
                 intentService.withdraw(intent);
+                try { // wait for withdraw event
+                    withdrawLatch.await(5, TimeUnit.SECONDS);
+                } catch (InterruptedException e) {
+                    print("Timed out waiting for intent {} withdraw");
+                }
             }
-            intentService.purge(intent);
+            if (CAN_PURGE.contains(intentService.getIntentState(intent.key()))) {
+                intentService.purge(intent);
+            }
+        }
+    }
+
+    private void wipeOutFlows() {
+        print("Wiping Flows");
+        FlowRuleService flowRuleService = get(FlowRuleService.class);
+        DeviceAdminService deviceAdminService = get(DeviceAdminService.class);
+        for (Device device : deviceAdminService.getDevices()) {
+            flowRuleService.purgeFlowRules(device.id());
+        }
+    }
+
+    private void wipeOutGroups() {
+        print("Wiping groups");
+        GroupService groupService = get(GroupService.class);
+        DeviceAdminService deviceAdminService = get(DeviceAdminService.class);
+        for (Device device : deviceAdminService.getDevices()) {
+            groupService.purgeGroupEntries(device.id());
         }
     }
 
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java
index 9b8ef81..52af84a 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleService.java
@@ -61,6 +61,12 @@
     void applyFlowRules(FlowRule... flowRules);
 
     /**
+     * Purges all the flow rules on the specified device.
+     * @param deviceId device identifier
+     */
+    void purgeFlowRules(DeviceId deviceId);
+
+    /**
      * Removes the specified flow rules from their respective devices. If the
      * device is not presently connected to the controller, these flow will
      * be removed once the device reconnects.
diff --git a/core/api/src/main/java/org/onosproject/net/group/GroupService.java b/core/api/src/main/java/org/onosproject/net/group/GroupService.java
index d56518a..369cc37 100644
--- a/core/api/src/main/java/org/onosproject/net/group/GroupService.java
+++ b/core/api/src/main/java/org/onosproject/net/group/GroupService.java
@@ -107,6 +107,12 @@
                                 ApplicationId appId);
 
     /**
+     * Purges all the group entries on the specified device.
+     * @param deviceId device identifier
+     */
+    void purgeGroupEntries(DeviceId deviceId);
+
+    /**
      * Deletes a group associated to an application cookie.
      * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
      * provided along with cookie depending on the result of the
diff --git a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleServiceAdapter.java
index a12308d..4335983 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleServiceAdapter.java
@@ -38,6 +38,10 @@
     }
 
     @Override
+    public void purgeFlowRules(DeviceId deviceId){
+    }
+
+    @Override
     public void removeFlowRules(FlowRule... flowRules) {
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
index 6e0adbc..e5220b5 100644
--- a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
@@ -244,6 +244,12 @@
     }
 
     @Override
+    public void purgeFlowRules(DeviceId deviceId) {
+        checkPermission(FLOWRULE_WRITE);
+        store.purgeFlowRule(deviceId);
+    }
+
+    @Override
     public void removeFlowRules(FlowRule... flowRules) {
         checkPermission(FLOWRULE_WRITE);
 
diff --git a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
index 091265a..1150d05 100644
--- a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
+++ b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
@@ -224,6 +224,13 @@
                                      newCookie);
     }
 
+    @Override
+    public void purgeGroupEntries(DeviceId deviceId) {
+        checkPermission(GROUP_WRITE);
+        store.purgeGroupEntry(deviceId);
+    }
+
+
     /**
      * Delete a group associated to an application cookie.
      * GROUP_DELETED or GROUP_DELETE_FAILED notifications would be
diff --git a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
index 235699d..014cb95 100644
--- a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
@@ -260,6 +260,22 @@
     }
 
     @Test
+    public void purgeFlowRules() {
+        FlowRule f1 = addFlowRule(1);
+        FlowRule f2 = addFlowRule(2);
+        FlowRule f3 = addFlowRule(3);
+        assertEquals("3 rules should exist", 3, flowCount());
+        FlowEntry fe1 = new DefaultFlowEntry(f1);
+        FlowEntry fe2 = new DefaultFlowEntry(f2);
+        FlowEntry fe3 = new DefaultFlowEntry(f3);
+        providerService.pushFlowMetrics(DID, ImmutableList.of(fe1, fe2, fe3));
+        validateEvents(RULE_ADD_REQUESTED, RULE_ADD_REQUESTED, RULE_ADD_REQUESTED,
+                RULE_ADDED, RULE_ADDED, RULE_ADDED);
+        mgr.purgeFlowRules(DID);
+        assertEquals("0 rule should exist", 0, flowCount());
+    }
+
+    @Test
     public void removeFlowRules() {
         FlowRule f1 = addFlowRule(1);
         FlowRule f2 = addFlowRule(2);
diff --git a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
index 40ed988..065da4d 100644
--- a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
@@ -188,6 +188,21 @@
     }
 
     /**
+     * Tests group Purge Operation.
+     */
+    @Test
+    public void testPurgeGroups() {
+        //Test Group creation before AUDIT process
+        testGroupCreationBeforeAudit(DID);
+        programmableTestCleanUp();
+        testAuditWithExtraneousMissingGroups(DID);
+        // Test group add bucket operations
+        testAddBuckets(DID);
+        // Test group Purge operations
+        testPurgeGroupEntry(DID);
+    }
+
+    /**
      * Tests group bucket modifications (additions and deletions) and
      * Tests group deletion.
      */
@@ -507,6 +522,13 @@
         internalListener.validateEvent(Collections.singletonList(GroupEvent.Type.GROUP_UPDATED));
     }
 
+    // Test purge group entry operations
+    private void testPurgeGroupEntry(DeviceId deviceId) {
+        assertEquals(1, Iterables.size(groupService.getGroups(deviceId, appId)));
+        groupService.purgeGroupEntries(deviceId);
+        assertEquals(0, Iterables.size(groupService.getGroups(deviceId, appId)));
+    }
+
     // Test group remove operations
     private void testRemoveGroup(DeviceId deviceId) {
         GroupKey currKey = new DefaultGroupKey("group1RemoveBuckets".getBytes());