Pull out inner IntentUpdate sub-classes from IntentManager

Change-Id: Iefec2e3d5929d0e85e40bee24ba4fd0679c13b19
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java
new file mode 100644
index 0000000..5b7953c
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Compiling.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class Compiling implements IntentUpdate {
+
+    private static final Logger log = LoggerFactory.getLogger(Compiling.class);
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+
+    Compiling(IntentManager intentManager, Intent intent) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+    }
+
+    @Override
+    public Optional<IntentUpdate> execute() {
+        try {
+            return Optional.of(new Installing(intentManager, intent, intentManager.compileIntent(intent, null)));
+        } catch (PathNotFoundException e) {
+            log.debug("Path not found for intent {}", intent);
+            // TODO: revisit to implement failure handling
+            return Optional.of(new DoNothing());
+        } catch (IntentException e) {
+            log.warn("Unable to compile intent {} due to:", intent.id(), e);
+            // TODO: revisit to implement failure handling
+            return Optional.of(new DoNothing());
+        }
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/InstallRequest.java b/core/net/src/main/java/org/onosproject/net/intent/impl/InstallRequest.java
new file mode 100644
index 0000000..42b9e1d
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/InstallRequest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+// TODO pull out the IntentUpdate inner classes
+class InstallRequest implements IntentUpdate {
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final IntentData currentState;
+
+    InstallRequest(IntentManager intentManager, Intent intent, IntentData currentState) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.currentState = currentState;
+    }
+
+    @Override
+    public Optional<IntentUpdate> execute() {
+        return Optional.of(new Compiling(intentManager, intent)); //FIXME
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Installed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Installed.java
new file mode 100644
index 0000000..316821b
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Installed.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentState;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.intent.IntentState.FAILED;
+import static org.onosproject.net.intent.IntentState.INSTALLING;
+
+class Installed implements CompletedIntentUpdate {
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final List<Intent> installables;
+    private IntentState intentState;
+    private final List<FlowRuleBatchOperation> batches;
+    private int currentBatch = 0;
+
+    Installed(IntentManager intentManager,
+              Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.installables = ImmutableList.copyOf(checkNotNull(installables));
+        this.batches = new LinkedList<>(checkNotNull(batches));
+        this.intentState = INSTALLING;
+    }
+
+    @Override
+    public void batchSuccess() {
+        currentBatch++;
+    }
+
+    @Override
+    public List<Intent> allInstallables() {
+        return installables;
+    }
+
+    @Override
+    public FlowRuleBatchOperation currentBatch() {
+        return currentBatch < batches.size() ? batches.get(currentBatch) : null;
+    }
+
+    @Override
+    public void batchFailed() {
+        for (int i = batches.size() - 1; i >= currentBatch; i--) {
+            batches.remove(i);
+        }
+        intentState = FAILED;
+        batches.addAll(intentManager.uninstallIntent(intent, installables));
+
+        // TODO we might want to try to recompile the new intent
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java
new file mode 100644
index 0000000..b5274b5
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Installing.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.intent.Intent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+// TODO: better naming because install() method actually generate FlowRuleBatchOperations
+class Installing implements IntentUpdate {
+
+    private static final Logger log = LoggerFactory.getLogger(Installing.class);
+
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final List<Intent> installables;
+
+    // TODO: define an interface and use it, instead of IntentManager
+    Installing(IntentManager intentManager, Intent intent, List<Intent> installables) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.installables = ImmutableList.copyOf(checkNotNull(installables));
+    }
+
+    @Override
+    public Optional<IntentUpdate> execute() {
+        try {
+            List<FlowRuleBatchOperation> converted = intentManager.convert(installables);
+            // TODO: call FlowRuleService API to push FlowRules and track resources,
+            // which the submitted intent will use.
+            return Optional.of(new Installed(intentManager, intent, installables, converted));
+        } catch (FlowRuleBatchOperationConvertionException e) {
+            log.warn("Unable to install intent {} due to:", intent.id(), e.getCause());
+            return Optional.of(new InstallingFailed(intentManager, intent, installables, e.converted()));
+        }
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/InstallingFailed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/InstallingFailed.java
new file mode 100644
index 0000000..0a7a5c4
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/InstallingFailed.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.intent.Intent;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class InstallingFailed implements CompletedIntentUpdate {
+
+    private IntentManager intentManager;
+    private final Intent intent;
+    private final List<Intent> installables;
+    private final List<FlowRuleBatchOperation> batches;
+    private int currentBatch = 0;
+
+    InstallingFailed(IntentManager intentManager,
+                     Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
+        this.intentManager = intentManager;
+        this.intent = checkNotNull(intent);
+        this.installables = ImmutableList.copyOf(checkNotNull(installables));
+        this.batches = new LinkedList<>(checkNotNull(batches));
+    }
+
+    @Override
+    public List<Intent> allInstallables() {
+        return installables;
+    }
+
+    @Override
+    public void batchSuccess() {
+        currentBatch++;
+    }
+
+    @Override
+    public FlowRuleBatchOperation currentBatch() {
+        return currentBatch < batches.size() ? batches.get(currentBatch) : null;
+    }
+
+    @Override
+    public void batchFailed() {
+        for (int i = batches.size() - 1; i >= currentBatch; i--) {
+            batches.remove(i);
+        }
+        batches.addAll(intentManager.uninstallIntent(intent, installables));
+
+        // TODO we might want to try to recompile the new intent
+    }
+}
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 511086f..c29a336 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
@@ -19,7 +19,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -69,7 +68,6 @@
 import static java.util.concurrent.Executors.newFixedThreadPool;
 import static org.onlab.util.Tools.namedThreads;
 import static org.onosproject.net.intent.IntentState.FAILED;
-import static org.onosproject.net.intent.IntentState.INSTALLING;
 import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
 import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -269,7 +267,7 @@
      * @param intent intent
      * @return result of compilation
      */
-    private List<Intent> compileIntent(Intent intent, List<Intent> previousInstallables) {
+    List<Intent> compileIntent(Intent intent, List<Intent> previousInstallables) {
         if (intent.isInstallable()) {
             return ImmutableList.of(intent);
         }
@@ -290,7 +288,7 @@
      * @param installables installable intents
      * @return list of batches to uninstall intent
      */
-    private List<FlowRuleBatchOperation> uninstallIntent(Intent intent, List<Intent> installables) {
+    List<FlowRuleBatchOperation> uninstallIntent(Intent intent, List<Intent> installables) {
         List<FlowRuleBatchOperation> batches = Lists.newArrayList();
         for (Intent installable : installables) {
             trackerService.removeTrackedResources(intent.id(),
@@ -415,9 +413,9 @@
         IntentData currentState = store.getIntentData(intentData.key());
         switch (intentData.state()) {
             case INSTALL_REQ:
-                return new InstallRequest(intentData.intent(), currentState);
+                return new InstallRequest(this, intentData.intent(), currentState);
             case WITHDRAW_REQ:
-                return new WithdrawRequest(intentData.intent(), currentState);
+                return new WithdrawRequest(this, intentData.intent(), currentState);
             // fallthrough
             case COMPILING:
             case INSTALLING:
@@ -432,89 +430,7 @@
         }
     }
 
-    // TODO pull out the IntentUpdate inner classes
-    private class InstallRequest implements IntentUpdate {
-
-        private final Intent intent;
-        private final IntentData currentState;
-
-        InstallRequest(Intent intent, IntentData currentState) {
-            this.intent = checkNotNull(intent);
-            this.currentState = currentState;
-        }
-
-        @Override
-        public Optional<IntentUpdate> execute() {
-            return Optional.of(new Compiling(intent)); //FIXME
-        }
-    }
-
-    private class WithdrawRequest implements IntentUpdate {
-
-        private final Intent intent;
-        private final IntentData currentState;
-
-        WithdrawRequest(Intent intent, IntentData currentState) {
-            this.intent = checkNotNull(intent);
-            this.currentState = currentState;
-        }
-
-        @Override
-        public Optional<IntentUpdate> execute() {
-            return Optional.of(new Withdrawing(intent, currentState.installables())); //FIXME
-        }
-    }
-
-    private class Compiling implements IntentUpdate {
-
-        private final Intent intent;
-
-        Compiling(Intent intent) {
-            this.intent = checkNotNull(intent);
-        }
-
-        @Override
-        public Optional<IntentUpdate> execute() {
-            try {
-                return Optional.of(new Installing(intent, compileIntent(intent, null)));
-            } catch (PathNotFoundException e) {
-                log.debug("Path not found for intent {}", intent);
-                // TODO: revisit to implement failure handling
-                return Optional.of(new DoNothing());
-            } catch (IntentException e) {
-                log.warn("Unable to compile intent {} due to:", intent.id(), e);
-                // TODO: revisit to implement failure handling
-                return Optional.of(new DoNothing());
-            }
-        }
-    }
-
-    // TODO: better naming because install() method actually generate FlowRuleBatchOperations
-    private class Installing implements IntentUpdate {
-
-        private final Intent intent;
-        private final List<Intent> installables;
-
-        Installing(Intent intent, List<Intent> installables) {
-            this.intent = checkNotNull(intent);
-            this.installables = ImmutableList.copyOf(checkNotNull(installables));
-        }
-
-        @Override
-        public Optional<IntentUpdate> execute() {
-            try {
-                List<FlowRuleBatchOperation> converted = convert(installables);
-                // TODO: call FlowRuleService API to push FlowRules and track resources,
-                // which the submitted intent will use.
-                return Optional.of(new Installed(intent, installables, converted));
-            } catch (FlowRuleBatchOperationConvertionException e) {
-                log.warn("Unable to install intent {} due to:", intent.id(), e.getCause());
-                return Optional.of(new InstallingFailed(intent, installables, e.converted()));
-            }
-        }
-    }
-
-    private List<FlowRuleBatchOperation> convert(List<Intent> installables) {
+    List<FlowRuleBatchOperation> convert(List<Intent> installables) {
         List<FlowRuleBatchOperation> batches = new ArrayList<>(installables.size());
         for (Intent installable : installables) {
             try {
@@ -527,143 +443,6 @@
         return batches;
     }
 
-    private class Withdrawing implements IntentUpdate {
-
-        private final Intent intent;
-        private final List<Intent> installables;
-
-        Withdrawing(Intent intent, List<Intent> installables) {
-            this.intent = checkNotNull(intent);
-            this.installables = ImmutableList.copyOf(installables);
-        }
-
-        @Override
-        public Optional<IntentUpdate> execute() {
-            List<FlowRuleBatchOperation> batches = uninstallIntent(intent, installables);
-
-            return Optional.of(new Withdrawn(intent, installables, batches));
-        }
-    }
-
-    private class Installed implements CompletedIntentUpdate {
-
-        private final Intent intent;
-        private final List<Intent> installables;
-        private IntentState intentState;
-        private final List<FlowRuleBatchOperation> batches;
-        private int currentBatch = 0;
-
-        Installed(Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
-            this.intent = checkNotNull(intent);
-            this.installables = ImmutableList.copyOf(checkNotNull(installables));
-            this.batches = new LinkedList<>(checkNotNull(batches));
-            this.intentState = INSTALLING;
-        }
-
-        @Override
-        public void batchSuccess() {
-            currentBatch++;
-        }
-
-        @Override
-        public List<Intent> allInstallables() {
-            return installables;
-        }
-
-        @Override
-        public FlowRuleBatchOperation currentBatch() {
-            return currentBatch < batches.size() ? batches.get(currentBatch) : null;
-        }
-
-        @Override
-        public void batchFailed() {
-            for (int i = batches.size() - 1; i >= currentBatch; i--) {
-                batches.remove(i);
-            }
-            intentState = FAILED;
-            batches.addAll(uninstallIntent(intent, installables));
-
-            // TODO we might want to try to recompile the new intent
-        }
-    }
-
-    private class Withdrawn implements CompletedIntentUpdate {
-
-        private final Intent intent;
-        private final List<Intent> installables;
-        private final List<FlowRuleBatchOperation> batches;
-        private int currentBatch;
-
-        Withdrawn(Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
-            this.intent = checkNotNull(intent);
-            this.installables = ImmutableList.copyOf(installables);
-            this.batches = new LinkedList<>(batches);
-            this.currentBatch = 0;
-        }
-
-        @Override
-        public List<Intent> allInstallables() {
-            return installables;
-        }
-
-        @Override
-        public void batchSuccess() {
-            currentBatch++;
-        }
-
-        @Override
-        public FlowRuleBatchOperation currentBatch() {
-            return currentBatch < batches.size() ? batches.get(currentBatch) : null;
-        }
-
-        @Override
-        public void batchFailed() {
-            for (int i = batches.size() - 1; i >= currentBatch; i--) {
-                batches.remove(i);
-            }
-            batches.addAll(uninstallIntent(intent, installables));
-        }
-    }
-
-    private class InstallingFailed implements CompletedIntentUpdate {
-
-        private final Intent intent;
-        private final List<Intent> installables;
-        private final List<FlowRuleBatchOperation> batches;
-        private int currentBatch = 0;
-
-        InstallingFailed(Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
-            this.intent = checkNotNull(intent);
-            this.installables = ImmutableList.copyOf(checkNotNull(installables));
-            this.batches = new LinkedList<>(checkNotNull(batches));
-        }
-
-        @Override
-        public List<Intent> allInstallables() {
-            return installables;
-        }
-
-        @Override
-        public void batchSuccess() {
-            currentBatch++;
-        }
-
-        @Override
-        public FlowRuleBatchOperation currentBatch() {
-            return currentBatch < batches.size() ? batches.get(currentBatch) : null;
-        }
-
-        @Override
-        public void batchFailed() {
-            for (int i = batches.size() - 1; i >= currentBatch; i--) {
-                batches.remove(i);
-            }
-            batches.addAll(uninstallIntent(intent, installables));
-
-            // TODO we might want to try to recompile the new intent
-        }
-    }
-
     private class IntentBatchPreprocess implements Runnable {
 
         // TODO make this configurable
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/WithdrawRequest.java b/core/net/src/main/java/org/onosproject/net/intent/impl/WithdrawRequest.java
new file mode 100644
index 0000000..dee793b
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/WithdrawRequest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class WithdrawRequest implements IntentUpdate {
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final IntentData currentState;
+
+    WithdrawRequest(IntentManager intentManager, Intent intent, IntentData currentState) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.currentState = currentState;
+    }
+
+    @Override
+    public Optional<IntentUpdate> execute() {
+        return Optional.of(new Withdrawing(intentManager, intent, currentState.installables())); //FIXME
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawing.java
new file mode 100644
index 0000000..c1da0ad
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawing.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.intent.Intent;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class Withdrawing implements IntentUpdate {
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final List<Intent> installables;
+
+    Withdrawing(IntentManager intentManager, Intent intent, List<Intent> installables) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.installables = ImmutableList.copyOf(installables);
+    }
+
+    @Override
+    public Optional<IntentUpdate> execute() {
+        List<FlowRuleBatchOperation> batches = intentManager.uninstallIntent(intent, installables);
+
+        return Optional.of(new Withdrawn(intentManager, intent, installables, batches));
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawn.java b/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawn.java
new file mode 100644
index 0000000..a313fea
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/Withdrawn.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.intent.Intent;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+class Withdrawn implements CompletedIntentUpdate {
+
+    // TODO: define an interface and use it, instead of IntentManager
+    private final IntentManager intentManager;
+    private final Intent intent;
+    private final List<Intent> installables;
+    private final List<FlowRuleBatchOperation> batches;
+    private int currentBatch;
+
+    Withdrawn(IntentManager intentManager,
+              Intent intent, List<Intent> installables, List<FlowRuleBatchOperation> batches) {
+        this.intentManager = checkNotNull(intentManager);
+        this.intent = checkNotNull(intent);
+        this.installables = ImmutableList.copyOf(installables);
+        this.batches = new LinkedList<>(batches);
+        this.currentBatch = 0;
+    }
+
+    @Override
+    public List<Intent> allInstallables() {
+        return installables;
+    }
+
+    @Override
+    public void batchSuccess() {
+        currentBatch++;
+    }
+
+    @Override
+    public FlowRuleBatchOperation currentBatch() {
+        return currentBatch < batches.size() ? batches.get(currentBatch) : null;
+    }
+
+    @Override
+    public void batchFailed() {
+        for (int i = batches.size() - 1; i >= currentBatch; i--) {
+            batches.remove(i);
+        }
+        batches.addAll(intentManager.uninstallIntent(intent, installables));
+    }
+}