adding purge option to IntentRemoveCommand

Change-Id: Ic97acd9a8308355cd3135ea5df0a470b3579106e
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java
index a8a760b..8a488a8 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentPushTestCommand.java
@@ -221,7 +221,7 @@
                 log.warn("install event latch is null");
             }
         } else if (IGNORE_EVENT.contains(event.type())) {
-            log.info("Unexpected intent event: {}", event);
+            log.debug("Unexpected intent event: {}", event);
         }
     }
 }
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
index de6984f..0820958 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
@@ -17,14 +17,24 @@
 
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentListener;
 import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
 import org.onosproject.net.intent.Key;
 
 import java.math.BigInteger;
+import java.util.Objects;
+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;
 
 /**
  * Removes an intent.
@@ -43,6 +53,16 @@
               required = true, multiValued = false)
     String id = null;
 
+    @Option(name = "-p", aliases = "--purge",
+            description = "Purge the intent from the store after removal",
+            required = false, multiValued = false)
+    private boolean purgeAfterRemove = false;
+
+    @Option(name = "-s", aliases = "--sync",
+            description = "Waits for the removal before returning",
+            required = false, multiValued = false)
+    private boolean sync = false;
+
     @Override
     protected void execute() {
         IntentService intentService = get(IntentService.class);
@@ -63,8 +83,38 @@
 
         Key key = Key.of(new BigInteger(id, 16).longValue(), appId);
         Intent intent = intentService.getIntent(key);
+
+
         if (intent != null) {
+            // set up latch and listener to track uninstall progress
+            CountDownLatch latch = new CountDownLatch(1);
+            IntentListener listener = (IntentEvent event) -> {
+                if (Objects.equals(event.subject().key(), key) &&
+                        (event.type() == IntentEvent.Type.WITHDRAWN
+                                || event.type() == IntentEvent.Type.WITHDRAWN)) {
+                    latch.countDown();
+                }
+            };
+            intentService.addListener(listener);
+
+            // request the withdraw
             intentService.withdraw(intent);
+
+            if (purgeAfterRemove || sync) {
+                try {
+                    latch.await(5, TimeUnit.SECONDS);
+                } catch (InterruptedException e) {
+                    print("Timed out waiting for intent {}", key);
+                }
+                // double check the state
+                IntentState state = intentService.getIntentState(key);
+                if (purgeAfterRemove && (state == WITHDRAWN || state == FAILED)) {
+                    intentService.purge(key);
+                }
+            }
+            // clean up the listener
+            intentService.removeListener(listener);
         }
+
     }
 }
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentService.java b/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
index 0d14a38..b86d793 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentService.java
@@ -112,4 +112,11 @@
      * @param listener listener to be removed
      */
     void removeListener(IntentListener listener);
+
+    /**
+     * Purges a specific intent from the system if it is FAILED or WITHDRAWN.
+     *
+     * @param key key of the intent to purge
+     */
+    void purge(Key key);
 }
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java b/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
index 5cfae17..2bf1ef1 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentStore.java
@@ -109,4 +109,10 @@
      * @return pending intents
      */
     Iterable<Intent> getPending();
+
+    /** Purges a specific intent from the system if it is FAILED or WITHDRAWN.
+     *
+     * @param key key of the intent to purge
+     */
+    void purge(Key key);
 }
diff --git a/core/api/src/test/java/org/onosproject/net/intent/FakeIntentManager.java b/core/api/src/test/java/org/onosproject/net/intent/FakeIntentManager.java
index 3d2475b..f232cbc 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/FakeIntentManager.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/FakeIntentManager.java
@@ -230,6 +230,11 @@
         listeners.remove(listener);
     }
 
+    @Override
+    public void purge(Key key) {
+        // FIXME implement this
+    }
+
     private void dispatch(IntentEvent event) {
         for (IntentListener listener : listeners) {
             listener.event(event);
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/intent/IntentServiceAdapter.java
index d100121..2d912eb 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentServiceAdapter.java
@@ -76,4 +76,9 @@
     public void removeListener(IntentListener listener) {
 
     }
+
+    @Override
+    public void purge(Key key) {
+
+    }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 1993729..ed1552a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -193,6 +193,11 @@
     }
 
     @Override
+    public void purge(Key key) {
+        store.purge(key);
+    }
+
+    @Override
     public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) {
         compilerRegistry.registerCompiler(cls, compiler);
     }
diff --git a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
index 4bc0ed0..bbdbdb7 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/intent/impl/GossipIntentStore.java
@@ -278,6 +278,14 @@
                 .collect(Collectors.toList());
     }
 
+    @Override
+    public void purge(Key key) {
+        IntentData data = currentMap.get(key);
+        if (data.state() == WITHDRAWN || data.state() == FAILED) {
+            currentMap.remove(key, data);
+        }
+    }
+
     private void notifyDelegateIfNotNull(IntentEvent event) {
         if (event != null) {
             notifyDelegate(event);
diff --git a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
index 0a4fcb5..25ff1fb 100644
--- a/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
+++ b/core/store/trivial/src/main/java/org/onosproject/store/trivial/impl/SimpleIntentStore.java
@@ -253,4 +253,12 @@
                 .map(IntentData::intent)
                 .collect(Collectors.toList());
     }
+
+    @Override
+    public void purge(Key key) {
+        IntentData data = current.get(key);
+        if (data.state() == IntentState.WITHDRAWN || data.state() == IntentState.FAILED) {
+            current.remove(key, data);
+        }
+    }
 }