Merge IntentInstaller's role into IntentCompiler

It resolves naming mismatch in naming of IntentProcessPhases and states
handled in the phases. It is described in ONOS-1064.

- Define FlowRuleIntent that enables flow rule level operation
  as an intent.
- Remove IntentInstaller interface
- Existing installable intents such as PathIntent, LinkCollectionIntent,
  OpticalPathIntent and MplsPathIntent now become non installable intents.
  Only FlowRuleIntent is categorized as installable intent now.
- Implement intent compilers for PathIntent, LinkCollectionIntent,
  OpticalPathIntent and MplsPathIntent. They generates FlowRuleIntents.
- Write unit tests for the newly created intent compilers according to
  the intent installers' unit tests
- Remove all intent installers and their unit tests

Change-Id: I22d6c7acb65a4c066145de0018bd0727f44bd54a
diff --git a/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java b/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java
new file mode 100644
index 0000000..3f66f3b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/intent/FlowRuleIntent.java
@@ -0,0 +1,87 @@
+/*
+ * 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;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.FlowRule;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An intent that enables to tell flow level operation.
+ * This instance holds a collection of flow rules that may be executed in parallel.
+ */
+public class FlowRuleIntent extends Intent {
+
+    private final Collection<FlowRule> flowRules;
+
+    /**
+     * Creates an flow rule intent with the specified flow rules to be set.
+     *
+     * @param appId     application id
+     * @param flowRules flow rules to be set.
+     */
+    public FlowRuleIntent(ApplicationId appId, List<FlowRule> flowRules) {
+        this(appId, null, flowRules, Collections.emptyList());
+    }
+
+    /**
+     * Creates an flow rule intent with the specified key, flow rules to be set, and
+     * required network resources.
+     *
+     * @param appId     application id
+     * @param key       key
+     * @param flowRules flow rules
+     * @param resources network resources
+     */
+    public FlowRuleIntent(ApplicationId appId, Key key, Collection<FlowRule> flowRules,
+                          Collection<NetworkResource> resources) {
+        super(appId, key, resources, DEFAULT_INTENT_PRIORITY);
+        this.flowRules = ImmutableList.copyOf(checkNotNull(flowRules));
+    }
+
+    /**
+     * Returns a collection of flow rules to be set.
+     *
+     * @return a collection of flow rules
+     */
+    public Collection<FlowRule> flowRules() {
+        return flowRules;
+    }
+
+    @Override
+    public boolean isInstallable() {
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("id", id())
+                .add("key", key())
+                .add("appId", appId())
+                .add("resources", resources())
+                .add("flowRule", flowRules)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java b/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java
index cefcb90..1d7c5ae 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentExtensionService.java
@@ -45,28 +45,4 @@
      * @return the set of compiler bindings
      */
     Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> getCompilers();
-
-    /**
-     * Registers the specified installer for the given installable intent class.
-     *
-     * @param cls       installable intent class
-     * @param installer intent installer
-     * @param <T>       the type of installable intent
-     */
-    <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
-
-    /**
-     * Unregisters the installer for the given installable intent class.
-     *
-     * @param cls installable intent class
-     * @param <T> the type of installable intent
-     */
-    <T extends Intent> void unregisterInstaller(Class<T> cls);
-
-    /**
-     * Returns immutable set of bindings of currently registered intent installers.
-     *
-     * @return the set of installer bindings
-     */
-    Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers();
 }
diff --git a/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java b/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java
index 8cea253..bc12ab7 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/LinkCollectionIntent.java
@@ -222,11 +222,6 @@
     }
 
     @Override
-    public boolean isInstallable() {
-        return true;
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
diff --git a/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java b/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java
index 754d433..438f208 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/OpticalPathIntent.java
@@ -154,11 +154,6 @@
     }
 
     @Override
-    public boolean isInstallable() {
-        return true;
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
diff --git a/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java b/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java
index 1cb960f..fd9789f 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/PathIntent.java
@@ -184,12 +184,6 @@
     }
 
     @Override
-    public boolean isInstallable() {
-        return true;
-    }
-
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
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 dca55d1..56ffb5d 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
@@ -37,8 +37,6 @@
     private final Set<IntentListener> listeners = new HashSet<>();
 
     private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
-    private final Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> installers
-        = new HashMap<>();
 
     private final ExecutorService executor = Executors.newSingleThreadExecutor();
     private final List<IntentException> exceptions = new ArrayList<>();
@@ -88,16 +86,6 @@
         return compiler;
     }
 
-    private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
-        @SuppressWarnings("unchecked")
-        IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
-                .getClass());
-        if (installer == null) {
-            throw new IntentException("no installer for class " + intent.getClass());
-        }
-        return installer;
-    }
-
     private <T extends Intent> void executeCompilingPhase(T intent) {
         setState(intent, IntentState.COMPILING);
         try {
@@ -118,10 +106,6 @@
                                         List<Intent> installable) {
         setState(intent, IntentState.INSTALLING);
         try {
-            for (Intent ii : installable) {
-                registerSubclassInstallerIfNeeded(ii);
-                getInstaller(ii).install(ii);
-            }
             setState(intent, IntentState.INSTALLED);
             putInstallable(intent.key(), installable);
             dispatch(new IntentEvent(IntentEvent.Type.INSTALLED, intent));
@@ -136,9 +120,6 @@
                                          List<Intent> installable) {
         setState(intent, IntentState.WITHDRAWING);
         try {
-            for (Intent ii : installable) {
-                getInstaller(ii).uninstall(ii);
-            }
             removeInstallable(intent.key());
             setState(intent, IntentState.WITHDRAWN);
             dispatch(new IntentEvent(IntentEvent.Type.WITHDRAWN, intent));
@@ -263,23 +244,6 @@
         return Collections.unmodifiableMap(compilers);
     }
 
-    @Override
-    public <T extends Intent> void registerInstaller(Class<T> cls,
-            IntentInstaller<T> installer) {
-        installers.put(cls, installer);
-    }
-
-    @Override
-    public <T extends Intent> void unregisterInstaller(Class<T> cls) {
-        installers.remove(cls);
-    }
-
-    @Override
-    public Map<Class<? extends Intent>,
-    IntentInstaller<? extends Intent>> getInstallers() {
-        return Collections.unmodifiableMap(installers);
-    }
-
     private void registerSubclassCompilerIfNeeded(Intent intent) {
         if (!compilers.containsKey(intent.getClass())) {
             Class<?> cls = intent.getClass();
@@ -296,23 +260,4 @@
             }
         }
     }
-
-    private void registerSubclassInstallerIfNeeded(Intent intent) {
-        if (!installers.containsKey(intent.getClass())) {
-            Class<?> cls = intent.getClass();
-            while (cls != Object.class) {
-                // As long as we're within the Intent class
-                // descendants
-                if (Intent.class.isAssignableFrom(cls)) {
-                    IntentInstaller<?> installer = installers.get(cls);
-                    if (installer != null) {
-                        installers.put(intent.getClass(), installer);
-                        return;
-                    }
-                }
-                cls = cls.getSuperclass();
-            }
-        }
-    }
-
 }
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentServiceTest.java b/core/api/src/test/java/org/onosproject/net/intent/IntentServiceTest.java
index c733933..58b21ef 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentServiceTest.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentServiceTest.java
@@ -19,12 +19,10 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.core.IdGenerator;
-import org.onosproject.net.flow.FlowRuleOperation;
 import org.onosproject.net.resource.LinkResourceAllocations;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -76,7 +74,6 @@
 
         // Register a compiler and an installer both setup for success.
         service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
-        service.registerInstaller(TestInstallableIntent.class, new TestInstaller(false));
 
         final Intent intent = new TestIntent(IID);
         service.submit(intent);
@@ -143,29 +140,6 @@
         validateEvents(intent, INSTALL_REQ, FAILED);
     }
 
-    @Test
-    public void failedInstallation() {
-        // Register a compiler programmed for success and installer for failure
-        service.registerCompiler(TestIntent.class, new TestCompiler(new TestInstallableIntent(INSTALLABLE_IID)));
-        service.registerInstaller(TestInstallableIntent.class, new TestInstaller(true));
-
-        // Submit an intent
-        final Intent intent = new TestIntent(IID);
-        service.submit(intent);
-
-        // Allow a small window of time until the intent is in the expected state
-        TestTools.assertAfter(GRACE_MS, new Runnable() {
-            @Override
-            public void run() {
-                assertEquals("incorrect intent state", IntentState.FAILED,
-                             service.getIntentState(intent.key()));
-            }
-        });
-
-        // Make sure that all expected events have been emitted
-        validateEvents(intent, INSTALL_REQ, FAILED);
-    }
-
     /**
      * Validates that the test event listener has received the following events
      * for the specified intent. Events received for other intents will not be
@@ -210,23 +184,6 @@
     }
 
     @Test
-    public void installerBasics() {
-        // Make sure there are no installers
-        assertEquals("incorrect installer count", 0, service.getInstallers().size());
-
-        // Add an installer and make sure that it appears in the map
-        IntentInstaller<TestInstallableIntent> installer = new TestInstaller(false);
-        service.registerInstaller(TestInstallableIntent.class, installer);
-        assertEquals("incorrect installer", installer,
-                     service.getInstallers().get(TestInstallableIntent.class));
-
-        // Remove the same and make sure that it no longer appears in the map
-        service.unregisterInstaller(TestInstallableIntent.class);
-        assertNull("installer should not be registered",
-                   service.getInstallers().get(TestInstallableIntent.class));
-    }
-
-    @Test
     public void implicitRegistration() {
         // Add a compiler and make sure that it appears in the map
         IntentCompiler<TestIntent> compiler = new TestCompiler(new TestSubclassInstallableIntent(INSTALLABLE_IID));
@@ -234,13 +191,6 @@
         assertEquals("incorrect compiler", compiler,
                      service.getCompilers().get(TestIntent.class));
 
-        // Add a installer and make sure that it appears in the map
-        IntentInstaller<TestInstallableIntent> installer = new TestInstaller(false);
-        service.registerInstaller(TestInstallableIntent.class, installer);
-        assertEquals("incorrect installer", installer,
-                     service.getInstallers().get(TestInstallableIntent.class));
-
-
         // Submit an intent which is a subclass of the one we registered
         final Intent intent = new TestSubclassIntent(IID);
         service.submit(intent);
@@ -259,11 +209,6 @@
         assertEquals("incorrect compiler", compiler,
                      service.getCompilers().get(TestSubclassIntent.class));
 
-        // Make sure that now we have an implicit registration of the installer
-        // under the intent subclass
-        assertEquals("incorrect installer", installer,
-                     service.getInstallers().get(TestSubclassInstallableIntent.class));
-
         // TODO: discuss whether or if implicit registration should require implicit unregistration
         // perhaps unregister by compiler or installer itself, rather than by class would be better
     }
@@ -304,36 +249,4 @@
             return compiled;
         }
     }
-
-    // Controllable installer
-    private class TestInstaller implements IntentInstaller<TestInstallableIntent> {
-        private final boolean fail;
-
-        TestInstaller(boolean fail) {
-            this.fail = fail;
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> install(TestInstallableIntent intent) {
-            if (fail) {
-                throw new IntentException("install failed by design");
-            }
-            return null;
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> uninstall(TestInstallableIntent intent) {
-            if (fail) {
-                throw new IntentException("remove failed by design");
-            }
-            return null;
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> replace(TestInstallableIntent intent,
-                                                    TestInstallableIntent newIntent) {
-            return null;
-        }
-    }
-
 }
diff --git a/core/api/src/test/java/org/onosproject/net/intent/LinkCollectionIntentTest.java b/core/api/src/test/java/org/onosproject/net/intent/LinkCollectionIntentTest.java
index 4263531..9d1028c 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/LinkCollectionIntentTest.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/LinkCollectionIntentTest.java
@@ -113,7 +113,7 @@
 
         final Set<Link> createdLinks = collectionIntent.links();
         assertThat(createdLinks, hasSize(1));
-        assertThat(collectionIntent.isInstallable(), is(true));
+        assertThat(collectionIntent.isInstallable(), is(false));
         assertThat(collectionIntent.treatment(), is(treatment));
         assertThat(collectionIntent.selector(), is(selector));
         assertThat(collectionIntent.ingressPoints(), is(ImmutableSet.of(ingress)));
@@ -147,7 +147,7 @@
 
         final Set<Link> createdLinks = collectionIntent.links();
         assertThat(createdLinks, hasSize(1));
-        assertThat(collectionIntent.isInstallable(), is(true));
+        assertThat(collectionIntent.isInstallable(), is(false));
         assertThat(collectionIntent.treatment(), is(treatment));
         assertThat(collectionIntent.selector(), is(selector));
         assertThat(collectionIntent.ingressPoints(), is(ImmutableSet.of(ingress)));
@@ -169,7 +169,7 @@
 
         final Set<Link> createdLinks = collectionIntent.links();
         assertThat(createdLinks, nullValue());
-        assertThat(collectionIntent.isInstallable(), is(true));
+        assertThat(collectionIntent.isInstallable(), is(false));
         assertThat(collectionIntent.treatment(), nullValue());
         assertThat(collectionIntent.selector(), nullValue());
         assertThat(collectionIntent.ingressPoints(), nullValue());
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/InstallerRegistry.java b/core/net/src/main/java/org/onosproject/net/intent/impl/InstallerRegistry.java
deleted file mode 100644
index e0103ce..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/InstallerRegistry.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * 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.ImmutableMap;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.FlowRuleOperationsContext;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentException;
-import org.onosproject.net.intent.IntentInstaller;
-import org.onosproject.net.intent.IntentStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static com.google.common.base.Preconditions.checkState;
-import static org.onlab.util.Tools.isNullOrEmpty;
-import static org.onosproject.net.intent.IntentState.FAILED;
-import static org.onosproject.net.intent.IntentState.INSTALLED;
-import static org.onosproject.net.intent.IntentState.WITHDRAWN;
-
-// TODO: consider a better name
-class InstallerRegistry {
-
-    private static final Logger log = LoggerFactory.getLogger(InstallerRegistry.class);
-
-    private final ConcurrentMap<Class<? extends Intent>,
-            IntentInstaller<? extends Intent>> installers = new ConcurrentHashMap<>();
-    /**
-     * Registers the specified installer for the given installable intent class.
-     *
-     * @param cls       installable intent class
-     * @param installer intent installer
-     * @param <T>       the type of installable intent
-     */
-    <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
-        installers.put(cls, installer);
-    }
-
-    /**
-     * Unregisters the installer for the given installable intent class.
-     *
-     * @param cls installable intent class
-     * @param <T> the type of installable intent
-     */
-    <T extends Intent> void unregisterInstaller(Class<T> cls) {
-        installers.remove(cls);
-    }
-
-    /**
-     * Returns immutable set of bindings of currently registered intent installers.
-     *
-     * @return the set of installer bindings
-     */
-    Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
-        return ImmutableMap.copyOf(installers);
-    }
-
-    /**
-     * Returns the corresponding intent installer to the specified installable intent.
-     *
-     * @param intent intent
-     * @param <T>    the type of installable intent
-     * @return intent installer corresponding to the specified installable intent
-     */
-    private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
-        @SuppressWarnings("unchecked")
-        IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass());
-        if (installer == null) {
-            throw new IntentException("no installer for class " + intent.getClass());
-        }
-        return installer;
-    }
-
-    /**
-     * Registers an intent installer of the specified intent if an intent installer
-     * for the intent is not registered. This method traverses the class hierarchy of
-     * the intent. Once an intent installer for a parent type is found, this method
-     * registers the found intent installer.
-     *
-     * @param intent intent
-     */
-    private void registerSubclassInstallerIfNeeded(Intent intent) {
-        if (!installers.containsKey(intent.getClass())) {
-            Class<?> cls = intent.getClass();
-            while (cls != Object.class) {
-                // As long as we're within the Intent class descendants
-                if (Intent.class.isAssignableFrom(cls)) {
-                    IntentInstaller<?> installer = installers.get(cls);
-                    if (installer != null) {
-                        installers.put(intent.getClass(), installer);
-                        return;
-                    }
-                }
-                cls = cls.getSuperclass();
-            }
-        }
-    }
-
-    /**
-     * Generate a {@link FlowRuleOperations} instance from the specified intent data.
-     *
-     * @param current        intent data stored in the store
-     * @param pending        intent data being processed
-     * @param store          intent store saving the intent state in this method
-     * @param trackerService objective tracker that is used in this method
-     * @return flow rule operations
-     */
-    public FlowRuleOperations coordinate(IntentData current, IntentData pending,
-                                         IntentStore store, ObjectiveTrackerService trackerService) {
-        List<Intent> oldInstallables = (current != null) ? current.installables() : null;
-        List<Intent> newInstallables = pending.installables();
-
-        checkState(isNullOrEmpty(oldInstallables) ||
-                        oldInstallables.size() == newInstallables.size(),
-                "Old and New Intent must have equivalent installable intents.");
-
-        List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
-        for (int i = 0; i < newInstallables.size(); i++) {
-            Intent newInstallable = newInstallables.get(i);
-            registerSubclassInstallerIfNeeded(newInstallable);
-            //TODO consider migrating installers to FlowRuleOperations
-            /* FIXME
-               - we need to do another pass on this method about that doesn't
-               require the length of installables to be equal, and also doesn't
-               depend on ordering
-               - we should also reconsider when to start/stop tracking resources
-             */
-            if (isNullOrEmpty(oldInstallables)) {
-                plans.add(getInstaller(newInstallable).install(newInstallable));
-            } else {
-                Intent oldInstallable = oldInstallables.get(i);
-                checkState(oldInstallable.getClass().equals(newInstallable.getClass()),
-                        "Installable Intent type mismatch.");
-                trackerService.removeTrackedResources(pending.key(), oldInstallable.resources());
-                plans.add(getInstaller(newInstallable).replace(oldInstallable, newInstallable));
-            }
-            trackerService.addTrackedResources(pending.key(), newInstallable.resources());
-//            } catch (IntentException e) {
-//                log.warn("Unable to update intent {} due to:", oldIntent.id(), e);
-//                //FIXME... we failed. need to uninstall (if same) or revert (if different)
-//                trackerService.removeTrackedResources(newIntent.id(), newInstallable.resources());
-//                exception = e;
-//                batches = uninstallIntent(oldIntent, oldInstallables);
-//            }
-        }
-
-        return merge(plans).build(new FlowRuleOperationsContext() { // TODO move this out
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                log.debug("Completed installing: {}", pending.key());
-                pending.setState(INSTALLED);
-                store.write(pending);
-            }
-
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                log.warn("Failed installation: {} {} on {}", pending.key(),
-                        pending.intent(), ops);
-                //TODO store.write(pending.setState(BROKEN));
-                pending.setState(FAILED);
-                store.write(pending);
-            }
-        });
-    }
-
-    /**
-     * Generate a {@link FlowRuleOperations} instance from the specified intent data.
-     *
-     * @param current        intent data stored in the store
-     * @param pending        intent date being processed
-     * @param store          intent store saving the intent state in this method
-     * @param trackerService objective tracker that is used in this method
-     * @return flow rule operations
-     */
-    FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending,
-                                                  IntentStore store, ObjectiveTrackerService trackerService) {
-        List<Intent> installables = current.installables();
-        List<List<Collection<FlowRuleOperation>>> plans = new ArrayList<>();
-        for (Intent installable : installables) {
-            plans.add(getInstaller(installable).uninstall(installable));
-            trackerService.removeTrackedResources(pending.key(), installable.resources());
-        }
-
-        return merge(plans).build(new FlowRuleOperationsContext() {
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                log.debug("Completed withdrawing: {}", pending.key());
-                pending.setState(WITHDRAWN);
-                pending.setInstallables(Collections.emptyList());
-                store.write(pending);
-            }
-
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                log.warn("Failed withdraw: {}", pending.key());
-                pending.setState(FAILED);
-                store.write(pending);
-            }
-        });
-    }
-
-
-    // TODO needs tests... or maybe it's just perfect
-    private FlowRuleOperations.Builder merge(List<List<Collection<FlowRuleOperation>>> plans) {
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        // Build a batch one stage at a time
-        for (int stageNumber = 0;; stageNumber++) {
-            // Get the sub-stage from each plan (List<Set<FlowRuleOperation>)
-            for (Iterator<List<Collection<FlowRuleOperation>>> itr = plans.iterator(); itr.hasNext();) {
-                List<Collection<FlowRuleOperation>> plan = itr.next();
-                if (plan.size() <= stageNumber) {
-                    // we have consumed all stages from this plan, so remove it
-                    itr.remove();
-                    continue;
-                }
-                // write operations from this sub-stage into the builder
-                Collection<FlowRuleOperation> stage = plan.get(stageNumber);
-                for (FlowRuleOperation entry : stage) {
-                    builder.operation(entry);
-                }
-            }
-            // we are done with the stage, start the next one...
-            if (plans.isEmpty()) {
-                break; // we don't need to start a new stage, we are done.
-            }
-            builder.newStage();
-        }
-        return builder;
-    }
-}
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 982aa0c..351016d 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
@@ -26,15 +26,17 @@
 import org.onosproject.core.IdGenerator;
 import org.onosproject.event.AbstractListenerRegistry;
 import org.onosproject.event.EventDeliveryService;
+import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
 import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.intent.FlowRuleIntent;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentBatchDelegate;
 import org.onosproject.net.intent.IntentCompiler;
 import org.onosproject.net.intent.IntentData;
 import org.onosproject.net.intent.IntentEvent;
 import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentInstaller;
 import org.onosproject.net.intent.IntentListener;
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.IntentState;
@@ -47,6 +49,7 @@
 import org.slf4j.Logger;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -60,7 +63,9 @@
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.intent.IntentState.FAILED;
+import static org.onosproject.net.intent.IntentState.INSTALLED;
 import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
 import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
 import static org.onosproject.net.intent.impl.phase.IntentProcessPhase.newInitialPhase;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -105,7 +110,6 @@
     private ExecutorService workerExecutor;
 
     private final CompilerRegistry compilerRegistry = new CompilerRegistry();
-    private final InstallerRegistry installerRegistry = new InstallerRegistry();
     private final InternalIntentProcessor processor = new InternalIntentProcessor();
     private final IntentStoreDelegate delegate = new InternalStoreDelegate();
     private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
@@ -215,21 +219,6 @@
     }
 
     @Override
-    public <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) {
-        installerRegistry.registerInstaller(cls, installer);
-    }
-
-    @Override
-    public <T extends Intent> void unregisterInstaller(Class<T> cls) {
-        installerRegistry.unregisterInstaller(cls);
-    }
-
-    @Override
-    public Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers() {
-        return installerRegistry.getInstallers();
-    }
-
-    @Override
     public Iterable<Intent> getPending() {
         return store.getPending();
     }
@@ -370,18 +359,92 @@
         }
 
         @Override
-        public FlowRuleOperations coordinate(IntentData current, IntentData pending) {
-            return installerRegistry.coordinate(current, pending, store, trackerService);
+        public void install(IntentData data) {
+            IntentManager.this.install(data);
         }
 
         @Override
-        public FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending) {
-            return installerRegistry.uninstallCoordinate(current, pending, store, trackerService);
+        public void uninstall(IntentData data) {
+            IntentManager.this.uninstall(data);
         }
 
-        @Override
-        public void applyFlowRules(FlowRuleOperations flowRules) {
-            flowRuleService.apply(flowRules);
+    }
+
+    private void install(IntentData data) {
+        // need to consider if FlowRuleIntent is only one as installable intent or not
+        List<Intent> installables = data.installables();
+        if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
+            throw new IllegalStateException("installable intents must be FlowRuleIntent");
         }
+
+        installables.forEach(x -> trackerService.addTrackedResources(data.key(), x.resources()));
+
+        List<Collection<FlowRule>> stages = installables.stream()
+                .map(x -> (FlowRuleIntent) x)
+                .map(FlowRuleIntent::flowRules)
+                .collect(Collectors.toList());
+
+        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
+        for (Collection<FlowRule> rules : stages) {
+            rules.forEach(builder::add);
+            builder.newStage();
+        }
+
+        FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                log.debug("Completed installing: {}", data.key());
+                data.setState(INSTALLED);
+                store.write(data);
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                log.warn("Failed installation: {} {} on {}", data.key(), data.intent(), ops);
+                data.setState(FAILED);
+                store.write(data);
+            }
+        });
+
+        flowRuleService.apply(operations);
+    }
+
+    private void uninstall(IntentData data) {
+        List<Intent> installables = data.installables();
+        if (!installables.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
+            throw new IllegalStateException("installable intents must be FlowRuleIntent");
+        }
+
+        installables.forEach(x -> trackerService.removeTrackedResources(data.intent().key(), x.resources()));
+
+        List<Collection<FlowRule>> stages = installables.stream()
+                .map(x -> (FlowRuleIntent) x)
+                .map(FlowRuleIntent::flowRules)
+                .collect(Collectors.toList());
+
+        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
+        for (Collection<FlowRule> rules : stages) {
+            rules.forEach(builder::remove);
+            builder.newStage();
+        }
+
+        FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                log.debug("Completed withdrawing: {}", data.key());
+                data.setState(WITHDRAWN);
+                data.setInstallables(Collections.emptyList());
+                store.write(data);
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                log.warn("Failed withdraw: {}", data.key());
+                data.setState(FAILED);
+                store.write(data);
+            }
+        });
+
+        flowRuleService.apply(operations);
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentProcessor.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentProcessor.java
index c613a8d..d946804 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentProcessor.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentProcessor.java
@@ -15,7 +15,6 @@
  */
 package org.onosproject.net.intent.impl;
 
-import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentData;
 
@@ -39,30 +38,16 @@
     List<Intent> compile(Intent intent, List<Intent> previousInstallables);
 
     /**
-     * Generate a {@link FlowRuleOperations} instance from the specified intent data.
+     * Installs an intent included in the specified intent data.
      *
-     * @param current intent data stored in the store
-     * @param pending intent data being processed
-     * @return flow rule operations
+     * @param data intent data containing an intent to be installed
      */
-    FlowRuleOperations coordinate(IntentData current, IntentData pending);
+    void install(IntentData data);
 
     /**
-     * Generate a {@link FlowRuleOperations} instance from the specified intent data.
+     * Uninstalls an intent included in the specified intent data.
      *
-     * @param current intent data stored in the store
-     * @param pending intent data being processed
-     * @return flow rule operations
+     * @param data intent data containing an intent to be uninstalled
      */
-    FlowRuleOperations uninstallCoordinate(IntentData current, IntentData pending);
-
-    /**
-     * Applies a batch operation of FlowRules.
-     *
-     * @param flowRules batch operation to apply
-     */
-    // TODO: consider a better name
-    // This methods gives strangeness a bit because
-    // it doesn't receive/return intent related information
-    void applyFlowRules(FlowRuleOperations flowRules);
+    void uninstall(IntentData data);
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java
new file mode 100644
index 0000000..e9e319e
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java
@@ -0,0 +1,134 @@
+/*
+ * 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.compiler;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.SetMultimap;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentCompiler;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.resource.LinkResourceAllocations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Component(immediate = true)
+public class LinkCollectionIntentCompiler implements IntentCompiler<LinkCollectionIntent> {
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentExtensionService intentManager;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    private ApplicationId appId;
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication("org.onosproject.net.intent");
+        intentManager.registerCompiler(LinkCollectionIntent.class, this);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        intentManager.unregisterCompiler(LinkCollectionIntent.class);
+    }
+
+    @Override
+    public List<Intent> compile(LinkCollectionIntent intent, List<Intent> installable,
+                                Set<LinkResourceAllocations> resources) {
+        SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
+        SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
+
+        for (Link link : intent.links()) {
+            inputPorts.put(link.dst().deviceId(), link.dst().port());
+            outputPorts.put(link.src().deviceId(), link.src().port());
+        }
+
+        for (ConnectPoint ingressPoint : intent.ingressPoints()) {
+            inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
+        }
+
+        for (ConnectPoint egressPoint : intent.egressPoints()) {
+            outputPorts.put(egressPoint.deviceId(), egressPoint.port());
+        }
+
+        List<FlowRule> rules = new ArrayList<>();
+        for (DeviceId deviceId: outputPorts.keys()) {
+            rules.addAll(createRules(intent, deviceId, inputPorts.get(deviceId), outputPorts.get(deviceId)));
+        }
+        return Arrays.asList(new FlowRuleIntent(appId, rules));
+    }
+
+    private List<FlowRule> createRules(LinkCollectionIntent intent, DeviceId deviceId,
+                                       Set<PortNumber> inPorts, Set<PortNumber> outPorts) {
+        Set<PortNumber> ingressPorts = intent.ingressPoints().stream()
+                .filter(point -> point.deviceId().equals(deviceId))
+                .map(ConnectPoint::port)
+                .collect(Collectors.toSet());
+
+        TrafficTreatment.Builder defaultTreatmentBuilder = DefaultTrafficTreatment.builder();
+        outPorts.stream()
+                .forEach(defaultTreatmentBuilder::setOutput);
+        TrafficTreatment defaultTreatment = defaultTreatmentBuilder.build();
+
+        TrafficTreatment.Builder ingressTreatmentBuilder = DefaultTrafficTreatment.builder(intent.treatment());
+        outPorts.stream()
+                .forEach(ingressTreatmentBuilder::setOutput);
+        TrafficTreatment ingressTreatment = ingressTreatmentBuilder.build();
+
+        List<FlowRule> rules = new ArrayList<>(inPorts.size());
+        for (PortNumber inPort: inPorts) {
+            TrafficSelector selector = DefaultTrafficSelector.builder(intent.selector()).matchInPort(inPort).build();
+            TrafficTreatment treatment;
+            if (ingressPorts.contains(inPort)) {
+                treatment = ingressTreatment;
+            } else {
+                treatment = defaultTreatment;
+            }
+
+            DefaultFlowRule rule = new DefaultFlowRule(deviceId, selector, treatment, 123, appId,
+                    new DefaultGroupId((short) (intent.id().fingerprint() & 0xffff)), 0, true);
+
+            rules.add(rule);
+        }
+
+        return rules;
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
similarity index 61%
rename from core/net/src/main/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstaller.java
rename to core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
index bb38fa5..b3bd864 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstaller.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
@@ -1,7 +1,20 @@
-package org.onosproject.net.intent.impl.installer;
+/*
+ * 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.compiler;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -19,14 +32,14 @@
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperation;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentCompiler;
 import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentInstaller;
 import org.onosproject.net.intent.MplsPathIntent;
 import org.onosproject.net.link.LinkStore;
 import org.onosproject.net.resource.DefaultLinkResourceRequest;
@@ -39,24 +52,22 @@
 import org.onosproject.net.resource.ResourceType;
 import org.slf4j.Logger;
 
-import java.util.Collection;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.slf4j.LoggerFactory.getLogger;
 
-/**
- * Installer for {@link MplsPathIntent packet path connectivity intents}.
- */
 @Component(immediate = true)
-public class MplsPathIntentInstaller implements IntentInstaller<MplsPathIntent> {
+public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
 
     private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected IntentExtensionService intentManager;
+    protected IntentExtensionService intentExtensionService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
@@ -69,45 +80,27 @@
 
     protected ApplicationId appId;
 
+    @Override
+    public List<Intent> compile(MplsPathIntent intent, List<Intent> installable,
+                                Set<LinkResourceAllocations> resources) {
+        LinkResourceAllocations allocations = assignMplsLabel(intent);
+        List<FlowRule> rules = generateRules(intent, allocations);
+
+        return Arrays.asList(new FlowRuleIntent(appId, rules));
+    }
+
     @Activate
     public void activate() {
         appId = coreService.registerApplication("org.onosproject.net.intent");
-        intentManager.registerInstaller(MplsPathIntent.class, this);
+        intentExtensionService.registerCompiler(MplsPathIntent.class, this);
     }
 
     @Deactivate
     public void deactivate() {
-        intentManager.unregisterInstaller(MplsPathIntent.class);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> install(MplsPathIntent intent) {
-        LinkResourceAllocations allocations = assignMplsLabel(intent);
-        return generateRules(intent, allocations, FlowRuleOperation.Type.ADD);
-
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> uninstall(MplsPathIntent intent) {
-        LinkResourceAllocations allocations = resourceService
-                .getAllocations(intent.id());
-        resourceService.releaseResources(allocations);
-
-        return generateRules(intent, allocations, FlowRuleOperation.Type.REMOVE);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> replace(MplsPathIntent oldIntent,
-                                                 MplsPathIntent newIntent) {
-        //FIXME this is brute force
-        List<Collection<FlowRuleOperation>> batches = Lists.newArrayList();
-        batches.addAll(uninstall(oldIntent));
-        batches.addAll(install(newIntent));
-        return batches;
+        intentExtensionService.unregisterCompiler(MplsPathIntent.class);
     }
 
     private LinkResourceAllocations assignMplsLabel(MplsPathIntent intent) {
-
         // TODO: do it better... Suggestions?
         Set<Link> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
                 .links().size() - 2);
@@ -126,9 +119,7 @@
         return reqMpls;
     }
 
-    private MplsLabel getMplsLabel(LinkResourceAllocations allocations,
-                                   Link link) {
-
+    private MplsLabel getMplsLabel(LinkResourceAllocations allocations, Link link) {
         for (ResourceAllocation allocation : allocations
                 .getResourceAllocation(link)) {
             if (allocation.type() == ResourceType.MPLS_LABEL) {
@@ -140,9 +131,8 @@
         return null;
     }
 
-    private List<Collection<FlowRuleOperation>> generateRules(MplsPathIntent intent,
-                                                       LinkResourceAllocations allocations,
-                                                       FlowRuleOperation.Type operation) {
+    private List<FlowRule> generateRules(MplsPathIntent intent,
+                                         LinkResourceAllocations allocations) {
 
         Iterator<Link> links = intent.path().links().iterator();
         Link srcLink = links.next();
@@ -150,14 +140,14 @@
 
         Link link = links.next();
         // List of flow rules to be installed
-        List<FlowRuleOperation> rules = Lists.newLinkedList();
+        List<FlowRule> rules = new LinkedList<>();
 
         // Ingress traffic
         // Get the new MPLS label
         MplsLabel mpls = getMplsLabel(allocations, link);
         checkNotNull(mpls);
         MplsLabel prevLabel = mpls;
-        rules.add(ingressFlow(prev.port(), link, intent, mpls, operation));
+        rules.add(ingressFlow(prev.port(), link, intent, mpls));
 
         prev = link.dst();
 
@@ -171,24 +161,22 @@
                 mpls = getMplsLabel(allocations, link);
                 checkNotNull(mpls);
                 rules.add(transitFlow(prev.port(), link, intent,
-                                      prevLabel, mpls, operation));
+                        prevLabel, mpls));
                 prevLabel = mpls;
 
             } else {
                 // Egress traffic
                 rules.add(egressFlow(prev.port(), link, intent,
-                                     prevLabel, operation));
+                        prevLabel));
             }
 
             prev = link.dst();
         }
-        return Lists.newArrayList(ImmutableSet.of(rules));
+        return rules;
     }
 
-    private FlowRuleOperation ingressFlow(PortNumber inPort, Link link,
-                                           MplsPathIntent intent,
-                                           MplsLabel label,
-                                           FlowRuleOperation.Type operation) {
+    private FlowRule ingressFlow(PortNumber inPort, Link link,
+                                 MplsPathIntent intent, MplsLabel label) {
 
         TrafficSelector.Builder ingressSelector = DefaultTrafficSelector
                 .builder(intent.selector());
@@ -208,16 +196,13 @@
         // Add the output action
         treat.setOutput(link.src().port());
 
-        return flowRuleOperation(intent, link.src().deviceId(),
-                ingressSelector.build(), treat.build(),
-                operation);
+        return createFlowRule(intent, link.src().deviceId(), ingressSelector.build(), treat.build());
     }
 
-    private FlowRuleOperation transitFlow(PortNumber inPort, Link link,
-                                           MplsPathIntent intent,
-                                           MplsLabel prevLabel,
-                                           MplsLabel outLabel,
-                                           FlowRuleOperation.Type operation) {
+    private FlowRule transitFlow(PortNumber inPort, Link link,
+                                          MplsPathIntent intent,
+                                          MplsLabel prevLabel,
+                                          MplsLabel outLabel) {
 
         // Ignore the ingress Traffic Selector and use only the MPLS label
         // assigned in the previous link
@@ -233,14 +218,12 @@
         }
 
         treat.setOutput(link.src().port());
-        return flowRuleOperation(intent, link.src().deviceId(),
-                selector.build(), treat.build(), operation);
+        return createFlowRule(intent, link.src().deviceId(), selector.build(), treat.build());
     }
 
-    private FlowRuleOperation egressFlow(PortNumber inPort, Link link,
-                                          MplsPathIntent intent,
-                                          MplsLabel prevLabel,
-                                          FlowRuleOperation.Type operation) {
+    private FlowRule egressFlow(PortNumber inPort, Link link,
+                                         MplsPathIntent intent,
+                                         MplsLabel prevLabel) {
         // egress point: either set the egress MPLS label or pop the
         // MPLS label based on the intent annotations
 
@@ -257,9 +240,9 @@
         } else {
             // if the ingress ethertype is defined, the egress traffic
             // will be use that value, otherwise the IPv4 ethertype is used.
-            Criterion c = intent.selector().getCriterion(Type.ETH_TYPE);
-            if (c != null && c instanceof EthTypeCriterion) {
-                EthTypeCriterion ethertype = (EthTypeCriterion) c;
+            Criterion c = intent.selector().getCriterion(Criterion.Type.ETH_TYPE);
+            if (c != null && c instanceof Criteria.EthTypeCriterion) {
+                Criteria.EthTypeCriterion ethertype = (Criteria.EthTypeCriterion) c;
                 treat.popMpls((short) ethertype.ethType());
             } else {
                 treat.popMpls(Ethernet.TYPE_IPV4);
@@ -267,24 +250,12 @@
 
         }
         treat.setOutput(link.src().port());
-        return flowRuleOperation(intent, link.src().deviceId(),
-                selector.build(), treat.build(), operation);
+        return createFlowRule(intent, link.src().deviceId(),
+                selector.build(), treat.build());
     }
 
-    protected FlowRuleOperation flowRuleOperation(MplsPathIntent intent,
-                                                    DeviceId deviceId,
-                                                    TrafficSelector selector,
-                                                    TrafficTreatment treat,
-                                                    FlowRuleOperation.Type operation) {
-        FlowRule rule = new DefaultFlowRule(
-                                            deviceId,
-                                            selector,
-                                            treat,
-                                            intent.priority(),
-                                            appId,
-                                            0,
-                                            true);
-        return new FlowRuleOperation(rule, operation);
-
+    protected FlowRule createFlowRule(MplsPathIntent intent, DeviceId deviceId,
+                                      TrafficSelector selector, TrafficTreatment treat) {
+        return new DefaultFlowRule(deviceId, selector, treat, intent.priority(), appId, 0, true);
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java
new file mode 100644
index 0000000..856499c
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompiler.java
@@ -0,0 +1,150 @@
+/*
+ * 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.compiler;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentCompiler;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.OpticalPathIntent;
+import org.onosproject.net.intent.impl.IntentCompilationException;
+import org.onosproject.net.resource.DefaultLinkResourceRequest;
+import org.onosproject.net.resource.Lambda;
+import org.onosproject.net.resource.LambdaResourceAllocation;
+import org.onosproject.net.resource.LinkResourceAllocations;
+import org.onosproject.net.resource.LinkResourceRequest;
+import org.onosproject.net.resource.LinkResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceType;
+import org.onosproject.net.topology.TopologyService;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
+
+@Component(immediate = true)
+public class OpticalPathIntentCompiler implements IntentCompiler<OpticalPathIntent> {
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentExtensionService intentManager;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    private ApplicationId appId;
+
+    static final short SIGNAL_TYPE = (short) 1;
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication("org.onosproject.net.intent");
+        intentManager.registerCompiler(OpticalPathIntent.class, this);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        intentManager.unregisterCompiler(OpticalPathIntent.class);
+    }
+
+    @Override
+    public List<Intent> compile(OpticalPathIntent intent, List<Intent> installable,
+                                Set<LinkResourceAllocations> resources) {
+        LinkResourceAllocations allocations = assignWavelength(intent);
+
+        return Arrays.asList(new FlowRuleIntent(appId, createRules(intent, allocations)));
+    }
+
+    private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
+        LinkResourceRequest.Builder request = DefaultLinkResourceRequest
+                .builder(intent.id(), intent.path().links())
+                .addLambdaRequest();
+        return resourceService.requestResources(request.build());
+    }
+
+    private List<FlowRule> createRules(OpticalPathIntent intent, LinkResourceAllocations allocations) {
+        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+        selectorBuilder.matchInPort(intent.src().port());
+
+        List<FlowRule> rules = new LinkedList<>();
+        ConnectPoint prev = intent.src();
+
+        for (Link link : intent.path().links()) {
+            ResourceAllocation allocation = allocations.getResourceAllocation(link).stream()
+                    .filter(x -> x.type() == ResourceType.LAMBDA)
+                    .findFirst()
+                    .orElseThrow(() -> new IntentCompilationException("Lambda was not assigned successfully"));
+            Lambda la = ((LambdaResourceAllocation) allocation).lambda();
+
+            TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+            treatmentBuilder.setLambda((short) la.toInt());
+            treatmentBuilder.setOutput(link.src().port());
+
+            FlowRule rule = new DefaultFlowRule(prev.deviceId(),
+                    selectorBuilder.build(),
+                    treatmentBuilder.build(),
+                    100,
+                    appId,
+                    100,
+                    true);
+
+            rules.add(rule);
+
+            prev = link.dst();
+            selectorBuilder.matchInPort(link.dst().port());
+            selectorBuilder.matchOpticalSignalType(SIGNAL_TYPE);
+            selectorBuilder.matchLambda((short) la.toInt());
+
+        }
+
+        // build the last T port rule
+        TrafficTreatment.Builder treatmentLast = builder();
+        treatmentLast.setOutput(intent.dst().port());
+        FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(),
+                selectorBuilder.build(),
+                treatmentLast.build(),
+                100,
+                appId,
+                100,
+                true);
+        rules.add(rule);
+
+        return rules;
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java
new file mode 100644
index 0000000..56515ec
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PathIntentCompiler.java
@@ -0,0 +1,106 @@
+/*
+ * 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.compiler;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentCompiler;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.PathIntent;
+import org.onosproject.net.resource.LinkResourceAllocations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+@Component(immediate = true)
+public class PathIntentCompiler implements IntentCompiler<PathIntent> {
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IntentExtensionService intentManager;
+
+    private ApplicationId appId;
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication("org.onosproject.net.intent");
+        intentManager.registerCompiler(PathIntent.class, this);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        intentManager.unregisterCompiler(PathIntent.class);
+    }
+
+    @Override
+    public List<Intent> compile(PathIntent intent, List<Intent> installable,
+                                Set<LinkResourceAllocations> resources) {
+        // Note: right now recompile is not considered
+        // TODO: implement recompile behavior
+
+        List<Link> links = intent.path().links();
+        List<FlowRule> rules = new ArrayList<>(links.size() - 1);
+
+        for (int i = 0; i < links.size() - 1; i++) {
+            ConnectPoint ingress = links.get(i).dst();
+            ConnectPoint egress = links.get(i + 1).src();
+            FlowRule rule = createFlowRule(intent.selector(), intent.treatment(), ingress, egress, isLast(links, i));
+            rules.add(rule);
+        }
+
+        return Arrays.asList(new FlowRuleIntent(appId, rules));
+    }
+
+    private FlowRule createFlowRule(TrafficSelector originalSelector, TrafficTreatment originalTreatment,
+                                    ConnectPoint ingress, ConnectPoint egress, boolean last) {
+        TrafficSelector selector = DefaultTrafficSelector.builder(originalSelector)
+                .matchInPort(ingress.port())
+                .build();
+
+        TrafficTreatment.Builder treatmentBuilder;
+        if (last) {
+            treatmentBuilder = DefaultTrafficTreatment.builder(originalTreatment);
+        } else {
+            treatmentBuilder = DefaultTrafficTreatment.builder();
+        }
+        TrafficTreatment treatment = treatmentBuilder.setOutput(egress.port()).build();
+
+        return new DefaultFlowRule(ingress.deviceId(), selector, treatment, 123, appId, 0, true);
+    }
+
+    private boolean isLast(List<Link> links, int i) {
+        return i == links.size() - 2;
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstaller.java
deleted file mode 100644
index e715b87..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstaller.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2014 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.installer;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.SetMultimap;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.core.DefaultGroupId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentInstaller;
-import org.onosproject.net.intent.LinkCollectionIntent;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Installer for {@link org.onosproject.net.intent.LinkCollectionIntent} path
- * segment intents.
- */
-@Component(immediate = true)
-public class LinkCollectionIntentInstaller
-        implements IntentInstaller<LinkCollectionIntent> {
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected IntentExtensionService intentManager;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
-
-    private ApplicationId appId;
-
-    @Activate
-    public void activate() {
-        appId = coreService.registerApplication("org.onosproject.net.intent");
-        intentManager.registerInstaller(LinkCollectionIntent.class, this);
-    }
-
-    @Deactivate
-    public void deactivate() {
-        intentManager.unregisterInstaller(LinkCollectionIntent.class);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> install(LinkCollectionIntent intent) {
-        return generateBatchOperations(intent, FlowRuleOperation.Type.ADD);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> uninstall(LinkCollectionIntent intent) {
-        return generateBatchOperations(intent, FlowRuleOperation.Type.REMOVE);
-    }
-
-    private List<Collection<FlowRuleOperation>> generateBatchOperations(
-            LinkCollectionIntent intent, FlowRuleOperation.Type operation) {
-
-        //TODO do we need a set here?
-        SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
-        SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
-
-        for (Link link : intent.links()) {
-            inputPorts.put(link.dst().deviceId(), link.dst().port());
-            outputPorts.put(link.src().deviceId(), link.src().port());
-        }
-
-        for (ConnectPoint ingressPoint : intent.ingressPoints()) {
-            inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
-        }
-
-        for (ConnectPoint egressPoint : intent.egressPoints()) {
-            outputPorts.put(egressPoint.deviceId(), egressPoint.port());
-        }
-
-        List<FlowRuleOperation> rules = Lists.newArrayList();
-        outputPorts.keys().stream()
-            .map(deviceId -> createBatchEntries(operation,
-                                                intent, deviceId,
-                                                inputPorts.get(deviceId),
-                                                outputPorts.get(deviceId)))
-            .forEach(rules::addAll);
-
-        return Lists.newArrayList(ImmutableSet.of(rules));
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> replace(LinkCollectionIntent oldIntent,
-                                                LinkCollectionIntent newIntent) {
-        // FIXME: implement this in a more intelligent/less brute force way
-        List<Collection<FlowRuleOperation>> batches = Lists.newArrayList();
-        batches.addAll(uninstall(oldIntent));
-        batches.addAll(install(newIntent));
-        return batches;
-    }
-
-    /**
-     * Creates a collection of FlowRuleOperation based on the provided
-     * parameters.
-     *
-     * @param operation the FlowRuleOperation type to use
-     * @param intent the link collection intent
-     * @param deviceId the device ID for the flow rule
-     * @param inPorts the logical input ports of the flow rule
-     * @param outPorts the set of output ports for the flow rule
-     * @return a collection with the new flow rule batch entries
-     */
-    private Collection<FlowRuleOperation> createBatchEntries(
-                                FlowRuleOperation.Type operation,
-                                LinkCollectionIntent intent,
-                                DeviceId deviceId,
-                                Set<PortNumber> inPorts,
-                                Set<PortNumber> outPorts) {
-        Collection<FlowRuleOperation> result = Lists.newLinkedList();
-        Set<PortNumber> ingressPorts = new HashSet<PortNumber>();
-
-        //
-        // Collect all ingress ports for this device.
-        // The intent treatment is applied only on those ports.
-        //
-        for (ConnectPoint cp : intent.ingressPoints()) {
-            if (cp.deviceId().equals(deviceId)) {
-                ingressPorts.add(cp.port());
-            }
-        }
-
-        //
-        // Create two treatments: one for setting the output ports,
-        // and a second one that applies the intent treatment and sets the
-        // output ports.
-        // NOTE: The second one is created only if there are ingress ports.
-        //
-        TrafficTreatment.Builder defaultTreatmentBuilder =
-            DefaultTrafficTreatment.builder();
-        for (PortNumber outPort : outPorts) {
-            defaultTreatmentBuilder.setOutput(outPort);
-        }
-        TrafficTreatment defaultTreatment = defaultTreatmentBuilder.build();
-        TrafficTreatment intentTreatment = null;
-        if (!ingressPorts.isEmpty()) {
-            TrafficTreatment.Builder intentTreatmentBuilder =
-                DefaultTrafficTreatment.builder(intent.treatment());
-            for (PortNumber outPort : outPorts) {
-                intentTreatmentBuilder.setOutput(outPort);
-            }
-            intentTreatment = intentTreatmentBuilder.build();
-        }
-
-        for (PortNumber inPort : inPorts) {
-            TrafficSelector selector = DefaultTrafficSelector
-                .builder(intent.selector()).matchInPort(inPort).build();
-            TrafficTreatment treatment = defaultTreatment;
-            if (ingressPorts.contains(inPort)) {
-                // Use the intent treatment if this is ingress port
-                treatment = intentTreatment;
-            }
-            FlowRule rule = new DefaultFlowRule(deviceId,
-                selector, treatment, intent.priority(), appId,
-                new DefaultGroupId((short) (intent.id().fingerprint() & 0xffff)),
-                0, true);
-            result.add(new FlowRuleOperation(rule, operation));
-        }
-
-        return result;
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstaller.java
deleted file mode 100644
index 43f6bfe..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstaller.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2014 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.installer;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentInstaller;
-import org.onosproject.net.intent.OpticalPathIntent;
-import org.onosproject.net.resource.DefaultLinkResourceRequest;
-import org.onosproject.net.resource.Lambda;
-import org.onosproject.net.resource.LambdaResourceAllocation;
-import org.onosproject.net.resource.LinkResourceAllocations;
-import org.onosproject.net.resource.LinkResourceRequest;
-import org.onosproject.net.resource.LinkResourceService;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceType;
-import org.onosproject.net.topology.TopologyService;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.List;
-
-import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Installer for {@link org.onosproject.net.intent.OpticalPathIntent optical path connectivity intents}.
- */
-@Component(immediate = true)
-public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
-    private final Logger log = getLogger(getClass());
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected IntentExtensionService intentManager;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowRuleService flowRuleService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected TopologyService topologyService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected LinkResourceService resourceService;
-
-    private ApplicationId appId;
-
-    static final short SIGNAL_TYPE = (short) 1;
-
-    @Activate
-    public void activate() {
-        appId = coreService.registerApplication("org.onosproject.net.intent");
-        intentManager.registerInstaller(OpticalPathIntent.class, this);
-    }
-
-    @Deactivate
-    public void deactivate() {
-        intentManager.unregisterInstaller(OpticalPathIntent.class);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> install(OpticalPathIntent intent) {
-        LinkResourceAllocations allocations = assignWavelength(intent);
-        return generateRules(intent, allocations, FlowRuleOperation.Type.ADD);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> uninstall(OpticalPathIntent intent) {
-        LinkResourceAllocations allocations = resourceService.getAllocations(intent.id());
-        List<Collection<FlowRuleOperation>> rules = generateRules(intent, allocations, FlowRuleOperation.Type.REMOVE);
-        log.info("uninstall rules: {}", rules);
-        return rules;
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> replace(OpticalPathIntent oldIntent,
-                                                OpticalPathIntent newIntent) {
-        // FIXME: implement this
-        List<Collection<FlowRuleOperation>> batches = Lists.newArrayList();
-        batches.addAll(uninstall(oldIntent));
-        batches.addAll(install(newIntent));
-        return batches;
-    }
-
-    private LinkResourceAllocations assignWavelength(OpticalPathIntent intent) {
-        LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(),
-                                                                                 intent.path().links())
-                .addLambdaRequest();
-        LinkResourceAllocations retLambda = resourceService.requestResources(request.build());
-        return retLambda;
-    }
-
-    private List<Collection<FlowRuleOperation>> generateRules(OpticalPathIntent intent,
-                                                        LinkResourceAllocations allocations,
-                                                        FlowRuleOperation.Type operation) {
-        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchInPort(intent.src().port());
-
-        List<FlowRuleOperation> rules = Lists.newLinkedList();
-        ConnectPoint prev = intent.src();
-
-        //FIXME check for null allocations
-        //TODO throw exception if the lambda was not assigned successfully
-        for (Link link : intent.path().links()) {
-            Lambda la = null;
-            for (ResourceAllocation allocation : allocations.getResourceAllocation(link)) {
-                if (allocation.type() == ResourceType.LAMBDA) {
-                    la = ((LambdaResourceAllocation) allocation).lambda();
-                    break;
-                }
-            }
-
-            if (la == null) {
-                log.info("Lambda was not assigned successfully");
-                return null;
-            }
-
-            TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
-            treatmentBuilder.setLambda((short) la.toInt());
-            treatmentBuilder.setOutput(link.src().port());
-
-            FlowRule rule = new DefaultFlowRule(prev.deviceId(),
-                                                selectorBuilder.build(),
-                                                treatmentBuilder.build(),
-                                                100,
-                                                appId,
-                                                100,
-                                                true);
-
-            rules.add(new FlowRuleOperation(rule, operation));
-
-            prev = link.dst();
-            selectorBuilder.matchInPort(link.dst().port());
-            selectorBuilder.matchOpticalSignalType(SIGNAL_TYPE); //todo
-            selectorBuilder.matchLambda((short) la.toInt());
-
-        }
-
-        // build the last T port rule
-        TrafficTreatment.Builder treatmentLast = builder();
-        treatmentLast.setOutput(intent.dst().port());
-        FlowRule rule = new DefaultFlowRule(intent.dst().deviceId(),
-                                            selectorBuilder.build(),
-                                            treatmentLast.build(),
-                                            100,
-                                            appId,
-                                            100,
-                                            true);
-        rules.add(new FlowRuleOperation(rule, operation));
-
-        //FIXME change to new api
-        return Lists.newArrayList(ImmutableSet.of(rules));
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/PathIntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/installer/PathIntentInstaller.java
deleted file mode 100644
index 7a06024..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/installer/PathIntentInstaller.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2014 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.installer;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.core.DefaultGroupId;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.DefaultFlowRule;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.Constraint;
-import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentInstaller;
-import org.onosproject.net.intent.PathIntent;
-import org.onosproject.net.resource.DefaultLinkResourceRequest;
-import org.onosproject.net.resource.LinkResourceAllocations;
-import org.onosproject.net.resource.LinkResourceRequest;
-import org.onosproject.net.resource.LinkResourceService;
-import org.slf4j.Logger;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-import static org.onosproject.net.flow.DefaultTrafficTreatment.builder;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Installer for {@link PathIntent packet path connectivity intents}.
- */
-@Component(immediate = true)
-public class PathIntentInstaller implements IntentInstaller<PathIntent> {
-
-    private final Logger log = getLogger(getClass());
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected IntentExtensionService intentManager;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected LinkResourceService resourceService;
-
-    protected ApplicationId appId;
-
-    @Activate
-    public void activate() {
-        appId = coreService.registerApplication("org.onosproject.net.intent");
-        intentManager.registerInstaller(PathIntent.class, this);
-    }
-
-    @Deactivate
-    public void deactivate() {
-        intentManager.unregisterInstaller(PathIntent.class);
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> install(PathIntent intent) {
-        LinkResourceAllocations allocations = allocateResources(intent);
-
-        TrafficSelector.Builder builder =
-                DefaultTrafficSelector.builder(intent.selector());
-        Iterator<Link> links = intent.path().links().iterator();
-        ConnectPoint prev = links.next().dst();
-        List<FlowRuleOperation> rules = Lists.newLinkedList();
-        // TODO Generate multiple batches
-        while (links.hasNext()) {
-            builder.matchInPort(prev.port());
-            Link link = links.next();
-            // if this is the last flow rule, apply the intent's treatments
-            TrafficTreatment treatment =
-                    (links.hasNext() ? builder() : builder(intent.treatment()))
-                    .setOutput(link.src().port()).build();
-
-            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
-                    builder.build(), treatment, intent.priority(),
-                    appId,
-                    new DefaultGroupId((short) (intent.id().fingerprint() & 0xffff)),
-                    0, true);
-            rules.add(new FlowRuleOperation(rule, FlowRuleOperation.Type.ADD));
-            prev = link.dst();
-        }
-
-        return Lists.newArrayList(ImmutableSet.of(rules));
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> uninstall(PathIntent intent) {
-        deallocateResources(intent);
-        TrafficSelector.Builder builder =
-                DefaultTrafficSelector.builder(intent.selector());
-        Iterator<Link> links = intent.path().links().iterator();
-        ConnectPoint prev = links.next().dst();
-        List<FlowRuleOperation> rules = Lists.newLinkedList();
-        // TODO Generate multiple batches
-        while (links.hasNext()) {
-            builder.matchInPort(prev.port());
-            Link link = links.next();
-            // if this is the last flow rule, apply the intent's treatments
-            TrafficTreatment treatment =
-                    (links.hasNext() ? builder() : builder(intent.treatment()))
-                            .setOutput(link.src().port()).build();
-            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
-                    builder.build(), treatment, intent.priority(), appId,
-                    new DefaultGroupId((short) (intent.id().fingerprint() & 0xffff)),
-                    0, true);
-            rules.add(new FlowRuleOperation(rule, FlowRuleOperation.Type.REMOVE));
-            prev = link.dst();
-        }
-        // FIXME this should change to new api
-        return Lists.newArrayList(ImmutableSet.of(rules));
-    }
-
-    @Override
-    public List<Collection<FlowRuleOperation>> replace(PathIntent oldIntent, PathIntent newIntent) {
-        // FIXME: implement this
-        List<Collection<FlowRuleOperation>> batches = Lists.newArrayList();
-        batches.addAll(uninstall(oldIntent));
-        batches.addAll(install(newIntent));
-        return batches;
-    }
-
-    /**
-     * Allocate resources required for an intent.
-     *
-     * @param intent intent to allocate resource for
-     * @return allocated resources if any are required, null otherwise
-     */
-    private LinkResourceAllocations allocateResources(PathIntent intent) {
-        LinkResourceRequest.Builder builder =
-                DefaultLinkResourceRequest.builder(intent.id(), intent.path().links());
-        for (Constraint constraint : intent.constraints()) {
-            builder.addConstraint(constraint);
-        }
-        LinkResourceRequest request = builder.build();
-        return request.resources().isEmpty() ? null : resourceService.requestResources(request);
-    }
-
-    /**
-     * Deallocate resources held by an intent.
-     *
-     * @param intent intent to deallocate resources for
-     */
-    private void deallocateResources(PathIntent intent) {
-        if (intent.constraints().isEmpty()) {
-            return;
-        }
-
-        LinkResourceAllocations allocatedResources = resourceService.getAllocations(intent.id());
-        if (allocatedResources != null) {
-            resourceService.releaseResources(allocatedResources);
-        }
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompilingFailed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompileFailed.java
similarity index 89%
rename from core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompilingFailed.java
rename to core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompileFailed.java
index e537308..234e222 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompilingFailed.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/CompileFailed.java
@@ -20,14 +20,14 @@
 /**
  * Represents a phase where the compile has failed.
  */
-public class CompilingFailed extends AbstractFailed {
+public class CompileFailed extends AbstractFailed {
 
     /**
      * Create an instance with the specified data.
      *
      * @param intentData intentData
      */
-    public CompilingFailed(IntentData intentData) {
+    public CompileFailed(IntentData intentData) {
         super(intentData);
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Compiling.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Compiling.java
index 97ea18e..060ae53 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Compiling.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Compiling.java
@@ -15,14 +15,12 @@
  */
 package org.onosproject.net.intent.impl.phase;
 
-import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentData;
 import org.onosproject.net.intent.IntentException;
 import org.onosproject.net.intent.impl.IntentProcessor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
 import java.util.Optional;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -35,24 +33,27 @@
     private static final Logger log = LoggerFactory.getLogger(Compiling.class);
 
     private final IntentProcessor processor;
-    private final IntentData pending;
-    private final IntentData current;
+    private final IntentData data;
 
-    Compiling(IntentProcessor processor, IntentData pending, IntentData current) {
+    /**
+     * Creates an compiling phase.
+     *
+     * @param processor intent processor that does work for compiling
+     * @param data      intent data containing an intent to be compiled
+     */
+    Compiling(IntentProcessor processor, IntentData data) {
         this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(pending);
-        this.current = current;
+        this.data = checkNotNull(data);
     }
 
     @Override
     public Optional<IntentProcessPhase> execute() {
         try {
-            List<Intent> installables = (current != null) ? current.installables() : null;
-            pending.setInstallables(processor.compile(pending.intent(), installables));
-            return Optional.of(new InstallCoordinating(processor, pending, current));
+            data.setInstallables(processor.compile(data.intent(), null));
+            return Optional.of(new Installing(processor, data));
         } catch (IntentException e) {
-            log.debug("Unable to compile intent {} due to: {}", pending.intent(), e);
-            return Optional.of(new CompilingFailed(pending));
+            log.debug("Unable to compile intent {} due to: {}", data.intent(), e);
+            return Optional.of(new CompileFailed(data));
         }
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/FinalIntentProcessPhase.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/FinalIntentProcessPhase.java
index 72451a5..c67b93b 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/FinalIntentProcessPhase.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/FinalIntentProcessPhase.java
@@ -26,8 +26,19 @@
 
     @Override
     public final Optional<IntentProcessPhase> execute() {
+        preExecute();
         return Optional.empty();
     }
 
+    /**
+     * Executes operations that must take place before the phase starts.
+     */
+    protected void preExecute() {}
+
+    /**
+     * Returns the IntentData object being acted on by this phase.
+     *
+     * @return intent data object for the phase
+     */
     public abstract IntentData data();
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallCoordinating.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallCoordinating.java
deleted file mode 100644
index 645fe6c..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallCoordinating.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.phase;
-
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentException;
-import org.onosproject.net.intent.impl.IntentProcessor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Optional;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Represents a phase to create a {@link FlowRuleOperations} instance
- * with using registered intent installers.
- */
-final class InstallCoordinating implements IntentProcessPhase {
-
-    private static final Logger log = LoggerFactory.getLogger(InstallCoordinating.class);
-
-    private final IntentProcessor processor;
-    private final IntentData pending;
-    private final IntentData current;
-
-    InstallCoordinating(IntentProcessor processor, IntentData pending, IntentData current) {
-        this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(pending);
-        this.current = current;
-    }
-
-    @Override
-    public Optional<IntentProcessPhase> execute() {
-        try {
-            //FIXME we orphan flow rules that are currently on the data plane
-            // ... should either reuse them or remove them
-            FlowRuleOperations flowRules = processor.coordinate(current, pending);
-            return Optional.of(new Installing(processor, pending, flowRules));
-        } catch (IntentException e) {
-            log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", pending.intent().id(), e);
-            return Optional.of(new InstallingFailed(pending));
-        }
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallRequest.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallRequest.java
index 1944aad..9e09788 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallRequest.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallRequest.java
@@ -27,18 +27,30 @@
  */
 final class InstallRequest implements IntentProcessPhase {
 
-    private final IntentProcessor intentManager;
-    private final IntentData pending;
-    private final Optional<IntentData> current;
+    private final IntentProcessor processor;
+    private final IntentData data;
+    private final Optional<IntentData> stored;
 
-    InstallRequest(IntentProcessor processor, IntentData intentData, Optional<IntentData> current) {
-        this.intentManager = checkNotNull(processor);
-        this.pending = checkNotNull(intentData);
-        this.current = checkNotNull(current);
+    /**
+     * Creates an install request phase.
+     *
+     * @param processor  intent processor to be passed to intent process phases
+     *                   generated after this phase
+     * @param intentData intent data to be processed
+     * @param stored     intent data stored in the store
+     */
+    InstallRequest(IntentProcessor processor, IntentData intentData, Optional<IntentData> stored) {
+        this.processor = checkNotNull(processor);
+        this.data = checkNotNull(intentData);
+        this.stored = checkNotNull(stored);
     }
 
     @Override
     public Optional<IntentProcessPhase> execute() {
-        return Optional.of(new Compiling(intentManager, pending, current.orElse(null)));
+        if (!stored.isPresent() || stored.get().installables() == null || stored.get().installables().isEmpty()) {
+            return Optional.of(new Compiling(processor, data));
+        } else {
+            return Optional.of(new Recompiling(processor, data, stored.get()));
+        }
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installed.java
deleted file mode 100644
index cd4d14e..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installed.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.phase;
-
-import org.onosproject.net.intent.IntentData;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.net.intent.IntentState.INSTALLING;
-
-/**
- * Represent a phase where an intent has been installed.
- */
-class Installed extends FinalIntentProcessPhase {
-
-    private final IntentData intentData;
-
-    Installed(IntentData intentData) {
-        this.intentData = checkNotNull(intentData);
-        this.intentData.setState(INSTALLING);
-    }
-
-    @Override
-    public IntentData data() {
-        return intentData;
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installing.java
index 3a290ae..de042e5 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installing.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Installing.java
@@ -15,45 +15,39 @@
  */
 package org.onosproject.net.intent.impl.phase;
 
-import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentException;
 import org.onosproject.net.intent.impl.IntentProcessor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Optional;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.intent.IntentState.INSTALLING;
 
 /**
- * Represents a phase of installing an intent with calling
- * {@link org.onosproject.net.flow.FlowRuleService}.
+ * Represents a phase where an intent is being installed.
  */
-final class Installing implements IntentProcessPhase {
-
-    private static final Logger log = LoggerFactory.getLogger(Installing.class);
+class Installing extends FinalIntentProcessPhase {
 
     private final IntentProcessor processor;
-    private final IntentData pending;
-    private final FlowRuleOperations flowRules;
+    private final IntentData data;
 
-    Installing(IntentProcessor processor, IntentData pending, FlowRuleOperations flowRules) {
+    /**
+     * Create an installing phase.
+     *
+     * @param processor intent processor that does work for installing
+     * @param data      intent data containing an intent to be installed
+     */
+    Installing(IntentProcessor processor, IntentData data) {
         this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(pending);
-        this.flowRules = flowRules;
+        this.data = checkNotNull(data);
+        this.data.setState(INSTALLING);
     }
 
     @Override
-    public Optional<IntentProcessPhase> execute() {
-        try {
-            processor.applyFlowRules(flowRules);
-            return Optional.of(new Installed(pending));
-        // What kinds of exceptions are thrown by FlowRuleService.apply()?
-        // Is IntentException a correct exception abstraction?
-        } catch (IntentException e) {
-            log.warn("Unable to install intent {} due to: {}", pending.intent().id(), e);
-            return Optional.of(new InstallingFailed(pending));
-        }
+    public void preExecute() {
+        processor.install(data);
+    }
+
+    @Override
+    public IntentData data() {
+        return data;
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/IntentProcessPhase.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/IntentProcessPhase.java
index dfa9d11..ea5a590 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/IntentProcessPhase.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/IntentProcessPhase.java
@@ -21,7 +21,6 @@
 import java.util.Optional;
 
 import static org.onlab.util.Tools.isNullOrEmpty;
-import static org.onosproject.net.intent.IntentState.WITHDRAWN;
 
 /**
  * Represents a phase of processing an intent.
@@ -52,7 +51,7 @@
                 return new InstallRequest(processor, data, Optional.ofNullable(current));
             case WITHDRAW_REQ:
                 if (current == null || isNullOrEmpty(current.installables())) {
-                    return new Withdrawn(data, WITHDRAWN);
+                    return new Withdrawn(data);
                 } else {
                     return new WithdrawRequest(processor, data, current);
                 }
@@ -60,7 +59,7 @@
                 return new PurgeRequest(data, current);
             default:
                 // illegal state
-                return new CompilingFailed(data);
+                return new CompileFailed(data);
         }
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Recompiling.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Recompiling.java
new file mode 100644
index 0000000..110f42f
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Recompiling.java
@@ -0,0 +1,55 @@
+/*
+ * 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.phase;
+
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.impl.IntentProcessor;
+
+import java.util.List;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a phase where an intent is being recompiled.
+ */
+class Recompiling implements IntentProcessPhase {
+
+    private final IntentProcessor processor;
+    private final IntentData data;
+    private final IntentData stored;
+
+    /**
+     * Creates a intent recompiling phase.
+     *
+     * @param processor intent processor that does work for recompiling
+     * @param data      intent data containing an intent to be recompiled
+     * @param stored    intent data stored in the store
+     */
+    Recompiling(IntentProcessor processor, IntentData data, IntentData stored) {
+        this.processor = checkNotNull(processor);
+        this.data = checkNotNull(data);
+        this.stored = checkNotNull(stored);
+    }
+
+    @Override
+    public Optional<IntentProcessPhase> execute() {
+        List<Intent> compiled = processor.compile(data.intent(), stored.installables());
+        data.setInstallables(compiled);
+        return Optional.of(new Replacing(processor, data, stored));
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallingFailed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/ReplaceFailed.java
similarity index 90%
rename from core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallingFailed.java
rename to core/net/src/main/java/org/onosproject/net/intent/impl/phase/ReplaceFailed.java
index b3bf3a3..3fcf97b 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/InstallingFailed.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/ReplaceFailed.java
@@ -20,14 +20,14 @@
 /**
  * Represent a phase where the install has failed.
  */
-class InstallingFailed extends AbstractFailed {
+class ReplaceFailed extends AbstractFailed {
 
     /**
      * Create an instance with the specified data.
      *
      * @param intentData intentData
      */
-    InstallingFailed(IntentData intentData) {
+    ReplaceFailed(IntentData intentData) {
         super(intentData);
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Replacing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Replacing.java
new file mode 100644
index 0000000..911139c
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Replacing.java
@@ -0,0 +1,62 @@
+/*
+ * 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.phase;
+
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentException;
+import org.onosproject.net.intent.impl.IntentProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a phase to replace an intent.
+ */
+final class Replacing implements IntentProcessPhase {
+
+    private static final Logger log = LoggerFactory.getLogger(Replacing.class);
+
+    private final IntentProcessor processor;
+    private final IntentData data;
+    private final IntentData stored;
+
+    /**
+     * Creates a replacing phase.
+     *
+     * @param processor intent processor that does work for replacing
+     * @param data      intent data containing an intent to be replaced
+     * @param stored    intent data stored in the store
+     */
+    Replacing(IntentProcessor processor, IntentData data, IntentData stored) {
+        this.processor = checkNotNull(processor);
+        this.data = checkNotNull(data);
+        this.stored = checkNotNull(stored);
+    }
+
+    @Override
+    public Optional<IntentProcessPhase> execute() {
+        try {
+            processor.uninstall(stored);
+            return Optional.of(new Installing(processor, data));
+        } catch (IntentException e) {
+            log.warn("Unable to generate a FlowRuleOperations from intent {} due to:", data.intent().id(), e);
+            return Optional.of(new ReplaceFailed(data));
+        }
+    }
+}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinating.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinating.java
deleted file mode 100644
index ee854c8..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinating.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.phase;
-
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentException;
-import org.onosproject.net.intent.impl.IntentProcessor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Optional;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Represents a phase to create a {@link FlowRuleOperations} instance
- * with using registered intent installers.
- */
-final class WithdrawCoordinating implements IntentProcessPhase {
-
-    private static final Logger log = LoggerFactory.getLogger(WithdrawCoordinating.class);
-
-    private final IntentProcessor processor;
-    private final IntentData pending;
-    private final IntentData current;
-
-    WithdrawCoordinating(IntentProcessor processor, IntentData pending, IntentData current) {
-        this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(pending);
-        this.current = checkNotNull(current);
-    }
-
-    @Override
-    public Optional<IntentProcessPhase> execute() {
-        try {
-            // Note: current.installables() are not null or empty due to createIntentUpdate check
-            FlowRuleOperations flowRules = processor.uninstallCoordinate(current, pending);
-            pending.setInstallables(current.installables());
-            return Optional.of(new Withdrawing(processor, pending, flowRules));
-        } catch (IntentException e) {
-            log.warn("Unable to generate generate a FlowRuleOperations from intent {} due to:", pending.intent(), e);
-            return Optional.of(new WithdrawingFailed(pending));
-        }
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawRequest.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawRequest.java
index 7940cf7..004bb33 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawRequest.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawRequest.java
@@ -28,13 +28,21 @@
 final class WithdrawRequest implements IntentProcessPhase {
 
     private final IntentProcessor processor;
-    private final IntentData pending;
-    private final IntentData current;
+    private final IntentData data;
+    private final IntentData stored;
 
-    WithdrawRequest(IntentProcessor processor, IntentData intentData, IntentData current) {
+    /**
+     * Creates a withdraw request phase.
+     *
+     * @param processor  intent processor to be passed to intent process phases
+     *                   generated after this phase
+     * @param intentData intent data to be processed
+     * @param stored     intent data stored in the store
+     */
+    WithdrawRequest(IntentProcessor processor, IntentData intentData, IntentData stored) {
         this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(intentData);
-        this.current = checkNotNull(current);
+        this.data = checkNotNull(intentData);
+        this.stored = checkNotNull(stored);
     }
 
     @Override
@@ -42,6 +50,7 @@
         //TODO perhaps we want to validate that the pending and current are the
         // same version i.e. they are the same
         // Note: this call is not just the symmetric version of submit
-        return Optional.of(new WithdrawCoordinating(processor, pending, current));
+        data.setInstallables(stored.installables());
+        return Optional.of(new Withdrawing(processor, data));
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawing.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawing.java
index 9198d0e..9351a96 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawing.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawing.java
@@ -15,33 +15,40 @@
  */
 package org.onosproject.net.intent.impl.phase;
 
-import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.intent.IntentData;
 import org.onosproject.net.intent.impl.IntentProcessor;
 
-import java.util.Optional;
-
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.intent.IntentState.WITHDRAWING;
 
 /**
- * Represents a phase of withdrawing an intent with calling
- * {@link org.onosproject.net.flow.FlowRuleService}.
+ * Represents a phase where an intent is withdrawing.
  */
-class Withdrawing implements IntentProcessPhase {
+class Withdrawing extends FinalIntentProcessPhase {
 
     private final IntentProcessor processor;
-    private final IntentData pending;
-    private final FlowRuleOperations flowRules;
+    private final IntentData data;
 
-    Withdrawing(IntentProcessor processor, IntentData pending, FlowRuleOperations flowRules) {
+    /**
+     * Creates a withdrawing phase.
+     *
+     * @param processor intent processor that does work for withdrawing
+     * @param data      intent data containing an intent to be withdrawn
+     */
+    Withdrawing(IntentProcessor processor, IntentData data) {
         this.processor = checkNotNull(processor);
-        this.pending = checkNotNull(pending);
-        this.flowRules = checkNotNull(flowRules);
+        this.data = checkNotNull(data);
+
+        this.data.setState(WITHDRAWING);
     }
 
     @Override
-    public Optional<IntentProcessPhase> execute() {
-        processor.applyFlowRules(flowRules);
-        return Optional.of(new Withdrawn(pending));
+    protected void preExecute() {
+        processor.uninstall(data);
+    }
+
+    @Override
+    public IntentData data() {
+        return data;
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawingFailed.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawingFailed.java
deleted file mode 100644
index 4e6874e..0000000
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/WithdrawingFailed.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.phase;
-
-import org.onosproject.net.intent.IntentData;
-
-/**
- * Represents a phase where the withdraw has failed.
- */
-final class WithdrawingFailed extends AbstractFailed {
-
-    /**
-     * Create an instance with the specified data.
-     *
-     * @param intentData intentData
-     */
-    WithdrawingFailed(IntentData intentData) {
-        super(intentData);
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawn.java b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawn.java
index b8e724b..264f74c 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawn.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/phase/Withdrawn.java
@@ -16,29 +16,29 @@
 package org.onosproject.net.intent.impl.phase;
 
 import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.IntentState;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.net.intent.IntentState.WITHDRAWING;
+import static org.onosproject.net.intent.IntentState.WITHDRAWN;
 
 /**
  * Represents a phase where an intent has been withdrawn.
  */
 final class Withdrawn extends FinalIntentProcessPhase {
 
-    private final IntentData intentData;
+    private final IntentData data;
 
-    Withdrawn(IntentData intentData) {
-        this(intentData, WITHDRAWING);
-    }
-
-    Withdrawn(IntentData intentData, IntentState newState) {
-        this.intentData = checkNotNull(intentData);
-        this.intentData.setState(newState);
+    /**
+     * Create a withdrawn phase.
+     *
+     * @param data intent data containing an intent to be withdrawn
+     */
+    Withdrawn(IntentData data) {
+        this.data = checkNotNull(data);
+        this.data.setState(WITHDRAWN);
     }
 
     @Override
     public IntentData data() {
-        return intentData;
+        return data;
     }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
index 64c963b..87ca8c7 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/IntentManagerTest.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.net.intent.impl;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -34,15 +35,13 @@
 import org.onosproject.core.impl.TestCoreManager;
 import org.onosproject.event.impl.TestEventDispatcher;
 import org.onosproject.net.NetworkResource;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleOperation;
+import org.onosproject.net.intent.FlowRuleIntent;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentCompiler;
 import org.onosproject.net.intent.IntentEvent;
 import org.onosproject.net.intent.IntentEvent.Type;
 import org.onosproject.net.intent.IntentExtensionService;
 import org.onosproject.net.intent.IntentId;
-import org.onosproject.net.intent.IntentInstaller;
 import org.onosproject.net.intent.IntentListener;
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.IntentState;
@@ -51,7 +50,6 @@
 import org.onosproject.store.trivial.impl.SimpleIntentStore;
 
 import com.google.common.collect.HashMultimap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
@@ -95,7 +93,6 @@
     protected IntentExtensionService extensionService;
     protected TestListener listener = new TestListener();
     protected TestIntentCompiler compiler = new TestIntentCompiler();
-    protected TestIntentInstaller installer = new TestIntentInstaller();
 
     private static class TestListener implements IntentListener {
         final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
@@ -152,14 +149,10 @@
         }
     }
 
-    private static class MockInstallableIntent extends MockIntent {
-        public MockInstallableIntent(Long number) {
-            super(number);
-        }
+    private static class MockInstallableIntent extends FlowRuleIntent {
 
-        @Override
-        public boolean isInstallable() {
-            return true;
+        public MockInstallableIntent() {
+            super(APPID, Arrays.asList(new MockFlowRule(100)));
         }
     }
 
@@ -167,7 +160,7 @@
         @Override
         public List<Intent> compile(MockIntent intent, List<Intent> installable,
                                     Set<LinkResourceAllocations> resources) {
-            return Lists.newArrayList(new MockInstallableIntent(intent.number()));
+            return Lists.newArrayList(new MockInstallableIntent());
         }
     }
 
@@ -179,53 +172,6 @@
         }
     }
 
-    private static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
-        @Override
-        public List<Collection<org.onosproject.net.flow.FlowRuleOperation>> install(MockInstallableIntent intent) {
-            FlowRule fr = new MockFlowRule(intent.number().intValue());
-            Set<FlowRuleOperation> rules = ImmutableSet.of(
-                    new FlowRuleOperation(fr, FlowRuleOperation.Type.ADD));
-            return Lists.newArrayList(ImmutableSet.of(rules));
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> uninstall(MockInstallableIntent intent) {
-            FlowRule fr = new MockFlowRule(intent.number().intValue());
-            Set<FlowRuleOperation> rules = ImmutableSet.of(
-                    new FlowRuleOperation(fr, FlowRuleOperation.Type.REMOVE));
-            return Lists.newArrayList(ImmutableSet.of(rules));
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> replace(MockInstallableIntent oldIntent,
-                                                           MockInstallableIntent newIntent) {
-            FlowRule fr = new MockFlowRule(oldIntent.number().intValue());
-            FlowRule fr2 = new MockFlowRule(newIntent.number().intValue());
-            Set<FlowRuleOperation> rules = ImmutableSet.of(
-                    new FlowRuleOperation(fr, FlowRuleOperation.Type.REMOVE),
-                    new FlowRuleOperation(fr2, FlowRuleOperation.Type.ADD));
-            return Lists.newArrayList(ImmutableSet.of(rules));
-        }
-    }
-
-    private static class TestIntentErrorInstaller implements IntentInstaller<MockInstallableIntent> {
-        @Override
-        public List<Collection<FlowRuleOperation>> install(MockInstallableIntent intent) {
-            throw new IntentInstallationException("install() always fails");
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> uninstall(MockInstallableIntent intent) {
-            throw new IntentRemovalException("uninstall() always fails");
-        }
-
-        @Override
-        public List<Collection<FlowRuleOperation>> replace(MockInstallableIntent oldIntent,
-                                                           MockInstallableIntent newIntent) {
-            throw new IntentInstallationException("replace() always fails");
-        }
-    }
-
     /**
      * Hamcrest matcher to check that a conllection of Intents contains an
      * Intent with the specified Intent Id.
@@ -274,7 +220,6 @@
         manager.activate();
         service.addListener(listener);
         extensionService.registerCompiler(MockIntent.class, compiler);
-        extensionService.registerInstaller(MockInstallableIntent.class, installer);
 
         assertTrue("store should be empty",
                    Sets.newHashSet(service.getIntents()).isEmpty());
@@ -307,7 +252,6 @@
     @After
     public void tearDown() {
         extensionService.unregisterCompiler(MockIntent.class);
-        extensionService.unregisterInstaller(MockInstallableIntent.class);
         service.removeListener(listener);
         manager.deactivate();
         // TODO null the other refs?
@@ -428,22 +372,6 @@
     }
 
     /**
-     * Tests handling of an error that is generated by the intent installer.
-     */
-    @Test
-    public void errorIntentInstallFromInstaller() {
-        final TestIntentErrorInstaller errorInstaller = new TestIntentErrorInstaller();
-        extensionService.registerInstaller(MockInstallableIntent.class, errorInstaller);
-        MockIntent intent = new MockIntent(MockIntent.nextId());
-        listener.setLatch(1, Type.INSTALL_REQ);
-        listener.setLatch(1, Type.FAILED);
-        service.submit(intent);
-        listener.await(Type.INSTALL_REQ);
-        listener.await(Type.FAILED);
-        verifyState();
-    }
-
-    /**
      * Tests handling a future that contains an unresolvable error as a result of
      * installing an intent.
      */
@@ -521,9 +449,6 @@
      */
     @Test
     public void intentWithoutInstaller() {
-
-        extensionService.unregisterInstaller(MockInstallableIntent.class);
-
         MockIntent intent = new MockIntent(MockIntent.nextId());
         listener.setLatch(1, Type.INSTALL_REQ);
         listener.setLatch(1, Type.FAILED);
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java
new file mode 100644
index 0000000..f314fe9
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.compiler;
+
+import com.google.common.collect.ImmutableSet;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.MockIdGenerator;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.PID;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+public class LinkCollectionIntentCompilerTest {
+
+    private final ApplicationId appId = new TestApplicationId("test");
+
+    private final ConnectPoint d1p1 = connectPoint("s1", 0);
+    private final ConnectPoint d2p0 = connectPoint("s2", 0);
+    private final ConnectPoint d2p1 = connectPoint("s2", 1);
+    private final ConnectPoint d3p1 = connectPoint("s3", 1);
+    private final ConnectPoint d3p0 = connectPoint("s3", 10);
+    private final ConnectPoint d1p0 = connectPoint("s1", 10);
+
+    private final Set<Link> links = ImmutableSet.of(
+            new DefaultLink(PID, d1p1, d2p0, DIRECT),
+            new DefaultLink(PID, d2p1, d3p1, DIRECT),
+            new DefaultLink(PID, d1p1, d3p1, DIRECT));
+
+    private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+    private CoreService coreService;
+    private IntentExtensionService intentExtensionService;
+    private IdGenerator idGenerator = new MockIdGenerator();
+
+    private LinkCollectionIntent intent;
+
+    private LinkCollectionIntentCompiler sut;
+
+    @Before
+    public void setUP() {
+        sut = new LinkCollectionIntentCompiler();
+        coreService = createMock(CoreService.class);
+        expect(coreService.registerApplication("org.onosproject.net.intent"))
+                .andReturn(appId);
+        sut.coreService = coreService;
+
+        Intent.bindIdGenerator(idGenerator);
+
+        intent = LinkCollectionIntent.builder()
+                .appId(APP_ID)
+                .selector(selector)
+                .treatment(treatment)
+                .links(links)
+                .ingressPoints(ImmutableSet.of(d1p1))
+                .egressPoints(ImmutableSet.of(d3p1))
+                .build();
+        intentExtensionService = createMock(IntentExtensionService.class);
+        intentExtensionService.registerCompiler(LinkCollectionIntent.class, sut);
+        intentExtensionService.unregisterCompiler(LinkCollectionIntent.class);
+        sut.intentManager = intentExtensionService;
+
+        replay(coreService, intentExtensionService);
+    }
+
+    @After
+    public void tearDown() {
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    @Test
+    public void testCompile() {
+        sut.activate();
+
+        List<Intent> compiled = sut.compile(intent, Collections.emptyList(), Collections.emptySet());
+        assertThat(compiled, hasSize(1));
+
+        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+        assertThat(rules, hasSize(links.size()));
+
+        // if not found, get() raises an exception
+        FlowRule rule1 = rules.stream()
+                .filter(rule -> rule.deviceId().equals(d1p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule1.selector(), is(
+                DefaultTrafficSelector.builder(intent.selector()).matchInPort(d1p1.port()).build()
+        ));
+        assertThat(rule1.treatment(), is(
+                DefaultTrafficTreatment.builder(intent.treatment()).setOutput(d1p1.port()).build()
+        ));
+
+        FlowRule rule2 = rules.stream()
+                .filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule2.selector(), is(
+                DefaultTrafficSelector.builder(intent.selector()).matchInPort(d2p0.port()).build()
+        ));
+        assertThat(rule2.treatment(), is(
+                DefaultTrafficTreatment.builder().setOutput(d2p1.port()).build()
+        ));
+
+        FlowRule rule3 = rules.stream()
+                .filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule3.selector(), is(
+                DefaultTrafficSelector.builder(intent.selector()).matchInPort(d3p1.port()).build()
+        ));
+        assertThat(rule3.treatment(), is(
+                DefaultTrafficTreatment.builder().setOutput(d3p1.port()).build()
+        ));
+
+        sut.deactivate();
+    }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
new file mode 100644
index 0000000..574bc05
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.compiler;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.MplsPathIntent;
+import org.onosproject.store.trivial.impl.SimpleLinkStore;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.PID;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+public class MplsPathIntentCompilerTest {
+
+    private final ApplicationId appId = new TestApplicationId("test");
+
+    private final ConnectPoint d1p1 = connectPoint("s1", 0);
+    private final ConnectPoint d2p0 = connectPoint("s2", 0);
+    private final ConnectPoint d2p1 = connectPoint("s2", 1);
+    private final ConnectPoint d3p1 = connectPoint("s3", 1);
+
+    private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+    private final Optional<MplsLabel> ingressLabel =
+            Optional.of(MplsLabel.mplsLabel(10));
+    private final Optional<MplsLabel> egressLabel =
+            Optional.of(MplsLabel.mplsLabel(20));
+
+    private final List<Link> links = Arrays.asList(
+            new DefaultLink(PID, d1p1, d2p0, DIRECT),
+            new DefaultLink(PID, d2p1, d3p1, DIRECT)
+    );
+
+    private IdGenerator idGenerator = new MockIdGenerator();
+
+    private final int hops = links.size() - 1;
+    private MplsPathIntent intent;
+    private MplsPathIntentCompiler sut;
+
+    @Before
+    public void setUp() {
+        sut = new MplsPathIntentCompiler();
+        CoreService coreService = createMock(CoreService.class);
+        expect(coreService.registerApplication("org.onosproject.net.intent"))
+                .andReturn(appId);
+        sut.coreService = coreService;
+        sut.linkStore = new SimpleLinkStore();
+        sut.resourceService = new IntentTestsMocks.MockResourceService();
+
+        Intent.bindIdGenerator(idGenerator);
+
+        intent = MplsPathIntent.builder()
+                .appId(APP_ID)
+                .selector(selector)
+                .treatment(treatment)
+                .path(new DefaultPath(PID, links, hops))
+                .ingressLabel(ingressLabel)
+                .egressLabel(egressLabel)
+                .priority(55)
+                .build();
+
+        IntentExtensionService intentExtensionService = createMock(IntentExtensionService.class);
+        intentExtensionService.registerCompiler(MplsPathIntent.class, sut);
+        intentExtensionService.unregisterCompiler(MplsPathIntent.class);
+        sut.intentExtensionService = intentExtensionService;
+
+        replay(coreService, intentExtensionService);
+    }
+
+    @After
+    public void tearDown() {
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    @Test
+    public void testCompile() {
+        sut.activate();
+
+        List<Intent> compiled = sut.compile(intent, Collections.emptyList(), Collections.emptySet());
+        assertThat(compiled, hasSize(1));
+
+        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+        assertThat(rules, hasSize(1));
+
+        FlowRule rule = rules.stream()
+                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule.deviceId(), is(d2p0.deviceId()));
+
+        sut.deactivate();
+
+    }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java
new file mode 100644
index 0000000..08e8e4f
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/OpticalPathIntentCompilerTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.compiler;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.OpticalPathIntent;
+import org.onosproject.net.provider.ProviderId;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.NetTestTools.PID;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+public class OpticalPathIntentCompilerTest {
+
+    private CoreService coreService;
+    private IntentExtensionService intentExtensionService;
+    private final IdGenerator idGenerator = new MockIdGenerator();
+    private OpticalPathIntentCompiler sut;
+
+    private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+    private final ApplicationId appId = new TestApplicationId("test");
+    private final ProviderId pid = new ProviderId("of", "test");
+    private final ConnectPoint d1p1 = connectPoint("s1", 0);
+    private final ConnectPoint d2p0 = connectPoint("s2", 0);
+    private final ConnectPoint d2p1 = connectPoint("s2", 1);
+    private final ConnectPoint d3p1 = connectPoint("s3", 1);
+    private final ConnectPoint d3p0 = connectPoint("s3", 10);
+    private final ConnectPoint d1p0 = connectPoint("s1", 10);
+
+    private final List<Link> links = Arrays.asList(
+            new DefaultLink(PID, d1p1, d2p0, DIRECT),
+            new DefaultLink(PID, d2p1, d3p1, DIRECT)
+    );
+    private final int hops = links.size() + 1;
+    private OpticalPathIntent intent;
+
+    @Before
+    public void setUp() {
+        sut = new OpticalPathIntentCompiler();
+        coreService = createMock(CoreService.class);
+        expect(coreService.registerApplication("org.onosproject.net.intent"))
+                .andReturn(appId);
+        sut.coreService = coreService;
+
+        Intent.bindIdGenerator(idGenerator);
+
+        intent = OpticalPathIntent.builder()
+                .appId(appId)
+                .src(d1p1)
+                .dst(d3p1)
+                .path(new DefaultPath(PID, links, hops))
+                .build();
+        intentExtensionService = createMock(IntentExtensionService.class);
+        intentExtensionService.registerCompiler(OpticalPathIntent.class, sut);
+        intentExtensionService.unregisterCompiler(OpticalPathIntent.class);
+        sut.intentManager = intentExtensionService;
+        sut.resourceService = new IntentTestsMocks.MockResourceService();
+
+        replay(coreService, intentExtensionService);
+    }
+
+    @After
+    public void tearDown() {
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    @Test
+    public void testCompiler() {
+        sut.activate();
+
+        List<Intent> compiled = sut.compile(intent, Collections.emptyList(), Collections.emptySet());
+        assertThat(compiled, hasSize(1));
+
+        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+        rules.stream()
+                .filter(x -> x.deviceId().equals(d1p1.deviceId()))
+                .findFirst()
+                .get();
+
+        rules.stream()
+                .filter(x -> x.deviceId().equals(d2p1.deviceId()))
+                .findFirst()
+                .get();
+
+        rules.stream()
+                .filter(x -> x.deviceId().equals(d3p1.deviceId()))
+                .findFirst()
+                .get();
+
+        sut.deactivate();
+    }
+
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PathIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PathIntentCompilerTest.java
new file mode 100644
index 0000000..058b607
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PathIntentCompilerTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.compiler;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.Link;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.FlowRuleIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.MockIdGenerator;
+import org.onosproject.net.intent.PathIntent;
+import org.onosproject.net.provider.ProviderId;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.PID;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+/**
+ * Unit tests for PathIntentCompiler.
+ */
+public class PathIntentCompilerTest {
+
+    private CoreService coreService;
+    private IntentExtensionService intentExtensionService;
+    private IdGenerator idGenerator = new MockIdGenerator();
+    private PathIntentCompiler sut;
+
+    private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
+    private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+    private final ApplicationId appId = new TestApplicationId("test");
+    private final ProviderId pid = new ProviderId("of", "test");
+    private final ConnectPoint d1p1 = connectPoint("s1", 0);
+    private final ConnectPoint d2p0 = connectPoint("s2", 0);
+    private final ConnectPoint d2p1 = connectPoint("s2", 1);
+    private final ConnectPoint d3p1 = connectPoint("s3", 1);
+    private final ConnectPoint d3p0 = connectPoint("s3", 10);
+    private final ConnectPoint d1p0 = connectPoint("s1", 10);
+
+    private final List<Link> links = Arrays.asList(
+            createEdgeLink(d1p0, true),
+            new DefaultLink(PID, d1p1, d2p0, DIRECT),
+            new DefaultLink(PID, d2p1, d3p1, DIRECT),
+            createEdgeLink(d3p0, false)
+    );
+    private final int hops = links.size() - 1;
+    private PathIntent intent;
+
+    /**
+     * Configures objects used in all the test cases.
+     */
+    @Before
+    public void setUp() {
+        sut = new PathIntentCompiler();
+        coreService = createMock(CoreService.class);
+        expect(coreService.registerApplication("org.onosproject.net.intent"))
+                .andReturn(appId);
+        sut.coreService = coreService;
+
+        Intent.bindIdGenerator(idGenerator);
+
+        intent = PathIntent.builder()
+                .appId(APP_ID)
+                .selector(selector)
+                .treatment(treatment)
+                .path(new DefaultPath(pid, links, hops))
+                .build();
+        intentExtensionService = createMock(IntentExtensionService.class);
+        intentExtensionService.registerCompiler(PathIntent.class, sut);
+        intentExtensionService.unregisterCompiler(PathIntent.class);
+        sut.intentManager = intentExtensionService;
+
+        replay(coreService, intentExtensionService);
+    }
+
+    /**
+     * Tears down objects used in all the test cases.
+     */
+    @After
+    public void tearDown() {
+        Intent.unbindIdGenerator(idGenerator);
+    }
+
+    /**
+     * Tests the compilation behavior of the path intent compiler.
+     */
+    @Test
+    public void testCompile() {
+        sut.activate();
+
+        List<Intent> compiled = sut.compile(intent, Collections.emptyList(), Collections.emptySet());
+        assertThat(compiled, hasSize(1));
+
+        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+
+        FlowRule rule1 = rules.stream()
+                .filter(x -> x.deviceId().equals(d1p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule1.deviceId(), is(d1p0.deviceId()));
+        assertThat(rule1.selector(),
+                is(DefaultTrafficSelector.builder(selector).matchInPort(d1p0.port()).build()));
+        assertThat(rule1.treatment(),
+                is(DefaultTrafficTreatment.builder().setOutput(d1p1.port()).build()));
+
+        FlowRule rule2 = rules.stream()
+                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule2.deviceId(), is(d2p0.deviceId()));
+        assertThat(rule2.selector(),
+                is(DefaultTrafficSelector.builder(selector).matchInPort(d2p0.port()).build()));
+        assertThat(rule2.treatment(),
+                is(DefaultTrafficTreatment.builder().setOutput(d2p1.port()).build()));
+
+        FlowRule rule3 = rules.stream()
+                .filter(x -> x.deviceId().equals(d3p0.deviceId()))
+                .findFirst()
+                .get();
+        assertThat(rule3.deviceId(), is(d3p1.deviceId()));
+        assertThat(rule3.selector(),
+                is(DefaultTrafficSelector.builder(selector).matchInPort(d3p1.port()).build()));
+        assertThat(rule3.treatment(),
+                is(DefaultTrafficTreatment.builder(treatment).setOutput(d3p0.port()).build()));
+
+        sut.deactivate();
+    }
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/IntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/IntentInstallerTest.java
deleted file mode 100644
index e6c723c..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/IntentInstallerTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.installer;
-
-import org.junit.After;
-import org.junit.Before;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.core.CoreServiceAdapter;
-import org.onosproject.core.IdGenerator;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.FakeIntentManager;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentInstaller;
-import org.onosproject.net.intent.IntentTestsMocks;
-import org.onosproject.net.intent.MockIdGenerator;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.connectPoint;
-
-/**
- * Base class for intent installer tests.
- */
-public class IntentInstallerTest {
-
-    /**
-     * Mock for core service.
-     */
-    static class TestCoreService extends CoreServiceAdapter {
-
-        String registeredId = "";
-
-        @Override
-        public ApplicationId registerApplication(String identifier) {
-            registeredId = identifier;
-            return APP_ID;
-        }
-    }
-
-    /**
-     * Mock for intent manager service. Checks that the PathIntent
-     * installer installs and uninstalls properly.
-     */
-    static class MockIntentManager extends FakeIntentManager {
-
-        boolean installerRegistered = false;
-        final Class expectedClass;
-
-        private MockIntentManager() {
-            expectedClass = null;
-        }
-
-        MockIntentManager(Class expectedInstaller) {
-            this.expectedClass = expectedInstaller;
-        }
-
-        @Override
-        public <T extends Intent> void registerInstaller(
-                Class<T> cls,
-                IntentInstaller<T> installer) {
-            assertThat(cls, equalTo(expectedClass));
-            installerRegistered = true;
-        }
-
-        @Override
-        public <T extends Intent> void unregisterInstaller(Class<T> cls) {
-            assertThat(cls, equalTo(expectedClass));
-            assertThat(installerRegistered, is(true));
-        }
-
-    }
-
-    CoreService testCoreService;
-    IdGenerator idGenerator = new MockIdGenerator();
-    IntentInstaller installer;
-
-    final IntentTestsMocks.MockSelector selector = new IntentTestsMocks.MockSelector();
-    final IntentTestsMocks.MockTreatment treatment = new IntentTestsMocks.MockTreatment();
-    final ConnectPoint d1p1 = connectPoint("s1", 0);
-    final ConnectPoint d2p0 = connectPoint("s2", 0);
-    final ConnectPoint d2p1 = connectPoint("s2", 1);
-    final ConnectPoint d3p1 = connectPoint("s3", 1);
-    final ConnectPoint d3p0 = connectPoint("s3", 10);
-    final ConnectPoint d1p0 = connectPoint("s1", 10);
-
-    /**
-     * Configures objects used in all the test cases.
-     */
-    @Before
-    public void setUp() {
-        testCoreService = new TestCoreService();
-        Intent.bindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Tears down objects used in all the test cases.
-     */
-    @After
-    public void tearDown() {
-        Intent.unbindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Checks that a flow operation contains the correct values.
-     *
-     * @param op flow rule operation to check
-     * @param type type the flow rule operation should have
-     * @param deviceId device id the flow rule operation should have
-     */
-    void checkFlowOperation(FlowRuleOperation op,
-                                    FlowRuleOperation.Type type,
-                                    DeviceId deviceId) {
-        assertThat(op.type(), is(type));
-        assertThat(op.rule().deviceId(), equalTo(deviceId));
-    }
-
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstallerTest.java
deleted file mode 100644
index 00ebedf..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/LinkCollectionIntentInstallerTest.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.installer;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.LinkCollectionIntent;
-
-import com.google.common.collect.ImmutableSet;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.PID;
-
-public class LinkCollectionIntentInstallerTest extends  IntentInstallerTest {
-
-    LinkCollectionIntentInstaller installer;
-
-    private final Set<Link> links = ImmutableSet.of(
-            new DefaultLink(PID, d1p1, d2p0, DIRECT),
-            new DefaultLink(PID, d2p1, d3p1, DIRECT),
-            new DefaultLink(PID, d1p1, d3p1, DIRECT));
-
-    private LinkCollectionIntent intent;
-
-    /**
-     * Configures objects used in all the test cases.
-     */
-    @Before
-    public void localSetUp() {
-        installer = new LinkCollectionIntentInstaller();
-        installer.coreService = testCoreService;
-        installer.intentManager =
-                new IntentInstallerTest.MockIntentManager(LinkCollectionIntent.class);
-        intent = LinkCollectionIntent.builder()
-                .appId(APP_ID)
-                .selector(selector)
-                .treatment(treatment)
-                .links(links)
-                .ingressPoints(ImmutableSet.of(d1p1))
-                .egressPoints(ImmutableSet.of(d3p1))
-                .build();
-    }
-
-    private FlowRuleOperation findOperation(Collection<FlowRuleOperation> ops,
-                                            DeviceId deviceId) {
-        for (FlowRuleOperation op : ops) {
-            if (op.rule().deviceId().equals(deviceId)) {
-                return op;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Tests activation and deactivation of the installer.
-     */
-    @Test
-    public void activateDeactivate() {
-        installer.activate();
-        installer.deactivate();
-    }
-
-    /**
-     * Tests installation operation of the path intent installer.
-     */
-    @Test
-    public void install() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.install(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(links.size()));
-
-        FlowRuleOperation op0 = findOperation(flowRuleOpsCollection,
-                d1p0.deviceId());
-        checkFlowOperation(op0, FlowRuleOperation.Type.ADD, d1p0.deviceId());
-
-        FlowRuleOperation op1 = findOperation(flowRuleOpsCollection,
-                d2p0.deviceId());
-        checkFlowOperation(op1, FlowRuleOperation.Type.ADD, d2p0.deviceId());
-
-        FlowRuleOperation op2 = findOperation(flowRuleOpsCollection,
-                d3p0.deviceId());
-        checkFlowOperation(op2, FlowRuleOperation.Type.ADD, d3p0.deviceId());
-
-        installer.deactivate();
-    }
-
-    /**
-     * Checks the uninstall operation of the path intent installer.
-     */
-    @Test
-    public void uninstall() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.uninstall(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(links.size()));
-
-        FlowRuleOperation op0 = findOperation(flowRuleOpsCollection,
-                d1p0.deviceId());
-        checkFlowOperation(op0, FlowRuleOperation.Type.REMOVE, d1p0.deviceId());
-
-        FlowRuleOperation op1 = findOperation(flowRuleOpsCollection,
-                d2p0.deviceId());
-        checkFlowOperation(op1, FlowRuleOperation.Type.REMOVE, d2p0.deviceId());
-
-        FlowRuleOperation op2 = findOperation(flowRuleOpsCollection,
-                d3p0.deviceId());
-        checkFlowOperation(op2, FlowRuleOperation.Type.REMOVE, d3p0.deviceId());
-
-        installer.deactivate();
-    }
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstallerTest.java
deleted file mode 100644
index e88947c..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/MplsPathIntentInstallerTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.installer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.MplsLabel;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.IntentTestsMocks;
-import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.store.trivial.impl.SimpleLinkStore;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.PID;
-
-/**
- * Unit tests for path intent installer.
- */
-public class  MplsPathIntentInstallerTest extends IntentInstallerTest {
-
-    MplsPathIntentInstaller installer;
-
-    private final Optional<MplsLabel> ingressLabel =
-            Optional.of(MplsLabel.mplsLabel(10));
-    private final Optional<MplsLabel> egressLabel =
-            Optional.of(MplsLabel.mplsLabel(20));
-
-    private final List<Link> links = Arrays.asList(
-            new DefaultLink(PID, d1p1, d2p0, DIRECT),
-            new DefaultLink(PID, d2p1, d3p1, DIRECT)
-    );
-    private final int hops = links.size() - 1;
-    private MplsPathIntent intent;
-
-    /**
-     * Configures objects used in all the test cases.
-     */
-    @Before
-    public void localSetUp() {
-        installer = new MplsPathIntentInstaller();
-        installer.coreService = testCoreService;
-        installer.intentManager = new MockIntentManager(MplsPathIntent.class);
-        installer.linkStore = new SimpleLinkStore();
-        installer.resourceService = new IntentTestsMocks.MockResourceService();
-
-        intent = MplsPathIntent.builder()
-                .appId(APP_ID)
-                .selector(selector)
-                .treatment(treatment)
-                .path(new DefaultPath(PID, links, hops))
-                .ingressLabel(ingressLabel)
-                .egressLabel(egressLabel)
-                .priority(55)
-                .build();
-    }
-
-    /**
-     * Tests activation and deactivation of the installer.
-     */
-    @Test
-    public void activateDeactivate() {
-        installer.activate();
-        installer.deactivate();
-    }
-
-    /**
-     * Tests installation operation of the MPLS path intent installer.
-     */
-    @Test
-    public void install() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.install(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.ADD, d2p0.deviceId());
-
-        installer.deactivate();
-    }
-
-    /**
-     * Checks the uninstall operation of the path intent installer.
-     */
-    @Test
-    public void uninstall() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.uninstall(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.REMOVE, d2p0.deviceId());
-
-        installer.deactivate();
-    }
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstallerTest.java
deleted file mode 100644
index 4aad8a5..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/OpticalPathIntentInstallerTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.installer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.IntentTestsMocks;
-import org.onosproject.net.intent.OpticalPathIntent;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.PID;
-
-public class OpticalPathIntentInstallerTest extends IntentInstallerTest {
-
-    OpticalPathIntentInstaller installer;
-
-    private final List<Link> links = Arrays.asList(
-            new DefaultLink(PID, d1p1, d2p0, DIRECT),
-            new DefaultLink(PID, d2p1, d3p1, DIRECT)
-    );
-    private final int hops = links.size() + 1;
-    private OpticalPathIntent intent;
-
-    /**
-     * Configures objects used in all the test cases.
-     */
-    @Before
-    public void localSetUp() {
-        installer = new OpticalPathIntentInstaller();
-        installer.coreService = testCoreService;
-        installer.intentManager =
-                new IntentInstallerTest.MockIntentManager(OpticalPathIntent.class);
-        installer.resourceService = new IntentTestsMocks.MockResourceService();
-
-        intent = OpticalPathIntent.builder().appId(APP_ID)
-                .src(d1p1)
-                .dst(d3p1)
-                .path(new DefaultPath(PID, links, hops))
-                .build();
-    }
-
-    /**
-     * Tests activation and deactivation of the installer.
-     */
-    @Test
-    public void activateDeactivate() {
-        installer.activate();
-        installer.deactivate();
-    }
-
-    /**
-     * Tests installation operation of the optical path intent installer.
-     */
-    @Test
-    public void install() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.install(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.ADD, d1p1.deviceId());
-
-        FlowRuleOperation op1 = flowRuleOps[1];
-        checkFlowOperation(op1, FlowRuleOperation.Type.ADD, d2p1.deviceId());
-
-        FlowRuleOperation op2 = flowRuleOps[2];
-        checkFlowOperation(op2, FlowRuleOperation.Type.ADD, d3p1.deviceId());
-
-        installer.deactivate();
-    }
-
-    /**
-     * Checks the uninstall operation of the optical path intent installer.
-     */
-    @Test
-    public void uninstall() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.uninstall(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.REMOVE, d1p1.deviceId());
-
-        FlowRuleOperation op1 = flowRuleOps[1];
-        checkFlowOperation(op1, FlowRuleOperation.Type.REMOVE, d2p1.deviceId());
-
-        FlowRuleOperation op2 = flowRuleOps[2];
-        checkFlowOperation(op2, FlowRuleOperation.Type.REMOVE, d3p1.deviceId());
-
-        installer.deactivate();
-    }
-
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathConstraintCalculationTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathConstraintCalculationTest.java
deleted file mode 100644
index 6e7606d..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathConstraintCalculationTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2014 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.installer;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.AbstractIntentTest;
-import org.onosproject.net.intent.Constraint;
-import org.onosproject.net.intent.IntentTestsMocks;
-import org.onosproject.net.intent.PathIntent;
-import org.onosproject.net.intent.constraint.BandwidthConstraint;
-import org.onosproject.net.intent.constraint.LambdaConstraint;
-import org.onosproject.net.resource.Bandwidth;
-import org.onosproject.net.resource.Lambda;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.fail;
-import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.PID;
-import static org.onosproject.net.NetTestTools.connectPoint;
-import static org.onosproject.net.intent.IntentTestsMocks.MockResourceService.makeBandwidthResourceService;
-import static org.onosproject.net.intent.IntentTestsMocks.MockResourceService.makeLambdaResourceService;
-
-/**
- * Unit tests for calculating paths for intents with constraints.
- */
-
-public class PathConstraintCalculationTest extends AbstractIntentTest {
-
-    private final IntentTestsMocks.MockSelector selector = new IntentTestsMocks.MockSelector();
-    private final IntentTestsMocks.MockTreatment treatment = new IntentTestsMocks.MockTreatment();
-    private final ConnectPoint d1p1 = connectPoint("s1", 0);
-    private final ConnectPoint d2p0 = connectPoint("s2", 0);
-    private final ConnectPoint d2p1 = connectPoint("s2", 1);
-    private final ConnectPoint d3p1 = connectPoint("s3", 1);
-    private final ConnectPoint d3p0 = connectPoint("s3", 10);
-    private final ConnectPoint d1p0 = connectPoint("s1", 10);
-
-    private PathIntentInstaller sut;
-
-    @Before
-    public void setUpIntentInstaller() {
-        sut = new PathIntentInstaller();
-        sut.appId = APP_ID;
-    }
-
-    private PathIntent createPathIntent(List<Link> links, List<Constraint> constraints) {
-        int hops = links.size() - 1;
-        return PathIntent.builder()
-                .appId(APP_ID)
-                .selector(selector)
-                .treatment(treatment)
-                .path(new DefaultPath(PID, links, hops))
-                .constraints(constraints)
-                .priority(333)
-                .build();
-    }
-
-    /**
-     * Tests that installation of bandwidth constrained path intents are
-     * successful.
-     */
-    @Test
-    public void testInstallBandwidthConstrainedIntentSuccess() {
-
-        final Constraint constraint = new BandwidthConstraint(Bandwidth.bps(100.0));
-
-        List<Link> links = Arrays.asList(
-                createEdgeLink(d1p0, true),
-                new DefaultLink(PID, d1p1, d2p0, DIRECT),
-                new DefaultLink(PID, d2p1, d3p1, DIRECT),
-                createEdgeLink(d3p0, false)
-        );
-        PathIntent installable = createPathIntent(links, Arrays.asList(constraint));
-
-        sut.resourceService = makeBandwidthResourceService(1000.0);
-
-        final List<Collection<FlowRuleOperation>> flowOperations = sut.install(installable);
-
-        assertThat(flowOperations, notNullValue());
-        assertThat(flowOperations, hasSize(1));
-    }
-
-    /**
-     * Tests that installation of bandwidth constrained path intents fail
-     * if there are no available resources.
-     */
-    @Test
-    public void testInstallBandwidthConstrainedIntentFailure() {
-
-        final Constraint constraint = new BandwidthConstraint(Bandwidth.bps(100.0));
-
-        List<Link> links = Arrays.asList(
-                createEdgeLink(d1p0, true),
-                new DefaultLink(PID, d1p1, d2p0, DIRECT),
-                new DefaultLink(PID, d2p1, d3p1, DIRECT),
-                createEdgeLink(d3p0, false)
-        );
-        PathIntent installable = createPathIntent(links, Arrays.asList(constraint));
-
-        // Make it look like the available bandwidth was consumed
-        final IntentTestsMocks.MockResourceService resourceService = makeBandwidthResourceService(1000.0);
-        resourceService.setAvailableBandwidth(1.0);
-        sut.resourceService = resourceService;
-
-        try {
-            sut.install(installable);
-            fail("Bandwidth request with no available bandwidth did not fail.");
-        } catch (IntentTestsMocks.MockedAllocationFailure failure) {
-            assertThat(failure,
-                       instanceOf(IntentTestsMocks.MockedAllocationFailure.class));
-        }
-    }
-
-    /**
-     * Tests that installation of lambda constrained path intents are
-     * successful.
-     */
-    @Test
-    public void testInstallLambdaConstrainedIntentSuccess() {
-
-        final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
-
-        List<Link> links = Arrays.asList(
-                createEdgeLink(d1p0, true),
-                new DefaultLink(PID, d1p1, d2p0, DIRECT),
-                new DefaultLink(PID, d2p1, d3p1, DIRECT),
-                createEdgeLink(d3p0, false)
-        );
-        PathIntent installable = createPathIntent(links, Arrays.asList(constraint));
-
-        sut.resourceService = makeLambdaResourceService(1);
-
-        final List<Collection<FlowRuleOperation>> flowOperations = sut.install(installable);
-
-        assertThat(flowOperations, notNullValue());
-        assertThat(flowOperations, hasSize(1));
-    }
-
-    /**
-     * Tests that installation of lambda constrained path intents fail
-     * if there are no available resources.
-     */
-    @Test
-    public void testInstallLambdaConstrainedIntentFailure() {
-
-        final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
-
-        List<Link> links = Arrays.asList(
-                createEdgeLink(d1p0, true),
-                new DefaultLink(PID, d1p1, d2p0, DIRECT),
-                new DefaultLink(PID, d2p1, d3p1, DIRECT),
-                createEdgeLink(d3p0, false)
-        );
-        PathIntent installable = createPathIntent(links, Arrays.asList(constraint));
-
-        // Make it look like the available lambda was consumed
-        final IntentTestsMocks.MockResourceService resourceService = makeLambdaResourceService(1);
-        resourceService.setAvailableLambda(0);
-        sut.resourceService = resourceService;
-
-        try {
-            sut.install(installable);
-            fail("Lambda request with no available lambda did not fail.");
-        } catch (IntentTestsMocks.MockedAllocationFailure failure) {
-            assertThat(failure,
-                       instanceOf(IntentTestsMocks.MockedAllocationFailure.class));
-        }
-    }
-
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathIntentInstallerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathIntentInstallerTest.java
deleted file mode 100644
index 9bbd16c..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/installer/PathIntentInstallerTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.installer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.flow.FlowRuleOperation;
-import org.onosproject.net.intent.PathIntent;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.PID;
-
-/**
- * Unit tests for path intent installer.
- */
-public class PathIntentInstallerTest extends IntentInstallerTest {
-
-    PathIntentInstaller installer;
-
-    private final List<Link> links = Arrays.asList(
-            createEdgeLink(d1p0, true),
-            new DefaultLink(PID, d1p1, d2p0, DIRECT),
-            new DefaultLink(PID, d2p1, d3p1, DIRECT),
-            createEdgeLink(d3p0, false)
-    );
-    private final int hops = links.size() - 1;
-    private PathIntent intent;
-
-    /**
-     * Configures objects used in all the test cases.
-     */
-    @Before
-    public void localSetUp() {
-        installer = new PathIntentInstaller();
-        installer.coreService = testCoreService;
-        installer.intentManager = new MockIntentManager(PathIntent.class);
-        intent = PathIntent.builder()
-                .appId(APP_ID)
-                .selector(selector)
-                .treatment(treatment)
-                .path(new DefaultPath(PID, links, hops))
-                .priority(77)
-                .build();
-    }
-
-    /**
-     * Tests activation and deactivation of the installer.
-     */
-    @Test
-    public void activateDeactivate() {
-        installer.activate();
-        installer.deactivate();
-    }
-
-    /**
-     * Tests installation operation of the path intent installer.
-     */
-    @Test
-    public void install() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-            installer.install(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.ADD, d1p0.deviceId());
-
-        FlowRuleOperation op1 = flowRuleOps[1];
-        checkFlowOperation(op1, FlowRuleOperation.Type.ADD, d2p0.deviceId());
-
-        FlowRuleOperation op2 = flowRuleOps[2];
-        checkFlowOperation(op2, FlowRuleOperation.Type.ADD, d3p0.deviceId());
-
-        installer.deactivate();
-    }
-
-    /**
-     * Checks the uninstall operation of the path intent installer.
-     */
-    @Test
-    public void uninstall() {
-        installer.activate();
-
-        List<Collection<FlowRuleOperation>> operations =
-                installer.uninstall(intent);
-        assertThat(operations, notNullValue());
-        assertThat(operations, hasSize(1));
-
-        Collection<FlowRuleOperation> flowRuleOpsCollection = operations.get(0);
-        assertThat(flowRuleOpsCollection, hasSize(hops));
-        FlowRuleOperation[] flowRuleOps =
-                flowRuleOpsCollection.toArray(new FlowRuleOperation[hops]);
-
-        FlowRuleOperation op0 = flowRuleOps[0];
-        checkFlowOperation(op0, FlowRuleOperation.Type.REMOVE, d1p0.deviceId());
-
-        FlowRuleOperation op1 = flowRuleOps[1];
-        checkFlowOperation(op1, FlowRuleOperation.Type.REMOVE, d2p0.deviceId());
-
-        FlowRuleOperation op2 = flowRuleOps[2];
-        checkFlowOperation(op2, FlowRuleOperation.Type.REMOVE, d3p0.deviceId());
-
-        installer.deactivate();
-    }
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/CompilingTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/CompilingTest.java
index a968e4e..f3e91a4 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/CompilingTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/CompilingTest.java
@@ -121,12 +121,12 @@
         expect(processor.compile(input, null)).andReturn(Arrays.asList(compiled));
         replay(processor);
 
-        Compiling sut = new Compiling(processor, pending, null);
+        Compiling sut = new Compiling(processor, pending);
 
         Optional<IntentProcessPhase> output = sut.execute();
 
         verify(processor);
-        assertThat(output.get(), is(instanceOf(InstallCoordinating.class)));
+        assertThat(output.get(), is(instanceOf(Installing.class)));
     }
 
     /**
@@ -139,11 +139,11 @@
         expect(processor.compile(input, null)).andThrow(new IntentCompilationException());
         replay(processor);
 
-        Compiling sut = new Compiling(processor, pending, null);
+        Compiling sut = new Compiling(processor, pending);
 
         Optional<IntentProcessPhase> output = sut.execute();
 
         verify(processor);
-        assertThat(output.get(), is(instanceOf(CompilingFailed.class)));
+        assertThat(output.get(), is(instanceOf(CompileFailed.class)));
     }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallingTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallingTest.java
deleted file mode 100644
index 8d4b334..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallingTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.phase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.IdGenerator;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.MockIdGenerator;
-import org.onosproject.net.intent.PathIntent;
-import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.net.intent.impl.IntentInstallationException;
-import org.onosproject.net.intent.impl.IntentProcessor;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.store.Timestamp;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
-
-/**
- * Unit tests for Installing phase.
- */
-public class InstallingTest {
-
-    private final ApplicationId appId = new TestApplicationId("test");
-    private final ProviderId pid = new ProviderId("of", "test");
-    private final TrafficSelector selector = DefaultTrafficSelector.emptySelector();
-    private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
-    private final ConnectPoint cp1 = new ConnectPoint(deviceId("1"), portNumber(1));
-    private final ConnectPoint cp2 = new ConnectPoint(deviceId("1"), portNumber(2));
-    private final ConnectPoint cp3 = new ConnectPoint(deviceId("2"), portNumber(1));
-    private final ConnectPoint cp4 = new ConnectPoint(deviceId("2"), portNumber(2));
-
-    private final List<Link> links = Arrays.asList(new DefaultLink(pid, cp2, cp4, DIRECT));
-    private final Path path = new DefaultPath(pid, links, 10);
-
-    private PointToPointIntent input;
-    private PathIntent compiled;
-
-    private IdGenerator idGenerator;
-    private IntentProcessor processor;
-    private Timestamp version;
-
-    @Before
-    public void setUp() {
-        processor = createMock(IntentProcessor.class);
-        version = createMock(Timestamp.class);
-
-        idGenerator = new MockIdGenerator();
-
-        Intent.bindIdGenerator(idGenerator);
-
-        // Intent creation should be placed after binding an ID generator
-        input = PointToPointIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .ingressPoint(cp1)
-                .egressPoint(cp3)
-                .build();
-        compiled = PathIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .path(path)
-                .build();
-    }
-
-
-    @After
-    public void tearDown() {
-        Intent.unbindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Tests a next phase when no exception occurs.
-     */
-    @Test
-    public void testMoveToNextPhaseWithoutError() {
-        IntentData pending = new IntentData(input, INSTALL_REQ, version);
-        pending.setInstallables(Arrays.asList(compiled));
-
-        FlowRuleOperations operations = createMock(FlowRuleOperations.class);
-
-        processor.applyFlowRules(operations);
-        replay(processor);
-
-        Installing sut = new Installing(processor, pending, operations);
-
-        Optional<IntentProcessPhase> executed = sut.execute();
-        verify(processor);
-        assertThat(executed.get(), is(instanceOf(Installed.class)));
-    }
-
-    /**
-     * Test a next phase when IntentInstallationException occurs.
-     */
-    @Test
-    public void testWhenIntentInstallationExceptionOccurs() {
-        IntentData pending = new IntentData(input, INSTALL_REQ, version);
-        pending.setInstallables(Arrays.asList(compiled));
-
-        FlowRuleOperations operations = createMock(FlowRuleOperations.class);
-
-        processor.applyFlowRules(operations);
-        expectLastCall().andThrow(new IntentInstallationException());
-        replay(processor);
-
-        Installing sut = new Installing(processor, pending, operations);
-
-        Optional<IntentProcessPhase> executed = sut.execute();
-        verify(processor);
-        assertThat(executed.get(), is(instanceOf(InstallingFailed.class)));
-    }
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallCoordinatingTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/ReplacingTest.java
similarity index 87%
rename from core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallCoordinatingTest.java
rename to core/net/src/test/java/org/onosproject/net/intent/impl/phase/ReplacingTest.java
index 1938425..e646a3f 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/InstallCoordinatingTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/ReplacingTest.java
@@ -28,7 +28,6 @@
 import org.onosproject.net.Path;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.intent.Intent;
@@ -46,7 +45,7 @@
 import java.util.Optional;
 
 import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.hamcrest.Matchers.instanceOf;
@@ -55,12 +54,13 @@
 import static org.onosproject.net.DeviceId.deviceId;
 import static org.onosproject.net.Link.Type.DIRECT;
 import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.net.intent.IntentState.INSTALLED;
 import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
 
 /**
  * Unit tests for InstallingCoordinating phase.
  */
-public class InstallCoordinatingTest {
+public class ReplacingTest {
 
     private final ApplicationId appId = new TestApplicationId("test");
     private final ProviderId pid = new ProviderId("of", "test");
@@ -120,12 +120,13 @@
         IntentData pending = new IntentData(input, INSTALL_REQ, version);
         pending.setInstallables(Arrays.asList(compiled));
 
-        FlowRuleOperations operations = createMock(FlowRuleOperations.class);
+        IntentData current = new IntentData(input, INSTALLED, version);
+        current.setInstallables(Arrays.asList(compiled));
 
-        expect(processor.coordinate(null, pending)).andReturn(operations);
+        processor.uninstall(current);
         replay(processor);
 
-        InstallCoordinating sut = new InstallCoordinating(processor, pending, null);
+        Replacing sut = new Replacing(processor, pending, current);
 
         Optional<IntentProcessPhase> executed = sut.execute();
 
@@ -141,14 +142,17 @@
         IntentData pending = new IntentData(input, INSTALL_REQ, version);
         pending.setInstallables(Arrays.asList(compiled));
 
-        expect(processor.coordinate(null, pending)).andThrow(new IntentInstallationException());
+        IntentData current = new IntentData(input, INSTALLED, version);
+
+        processor.uninstall(current);
+        expectLastCall().andThrow(new IntentInstallationException());
         replay(processor);
 
-        InstallCoordinating sut = new InstallCoordinating(processor, pending, null);
+        Replacing sut = new Replacing(processor, pending, current);
 
         Optional<IntentProcessPhase> executed = sut.execute();
 
         verify(processor);
-        assertThat(executed.get(), is(instanceOf(InstallingFailed.class)));
+        assertThat(executed.get(), is(instanceOf(ReplaceFailed.class)));
     }
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinatingTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinatingTest.java
deleted file mode 100644
index 5d40516..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawCoordinatingTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.phase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.IdGenerator;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.MockIdGenerator;
-import org.onosproject.net.intent.PathIntent;
-import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.net.intent.impl.IntentProcessor;
-import org.onosproject.net.intent.impl.IntentRemovalException;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.store.Timestamp;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.net.intent.IntentState.INSTALLED;
-import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
-
-/**
- * Unit tests for WithdrawCoordinating phase.
- */
-public class WithdrawCoordinatingTest {
-
-    private final ApplicationId appId = new TestApplicationId("test");
-    private final ProviderId pid = new ProviderId("of", "test");
-    private final TrafficSelector selector = DefaultTrafficSelector.emptySelector();
-    private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
-    private final ConnectPoint cp1 = new ConnectPoint(deviceId("1"), portNumber(1));
-    private final ConnectPoint cp2 = new ConnectPoint(deviceId("1"), portNumber(2));
-    private final ConnectPoint cp3 = new ConnectPoint(deviceId("2"), portNumber(1));
-    private final ConnectPoint cp4 = new ConnectPoint(deviceId("2"), portNumber(2));
-
-    private final List<Link> links = Arrays.asList(new DefaultLink(pid, cp2, cp4, DIRECT));
-    private final Path path = new DefaultPath(pid, links, 10);
-
-    private PointToPointIntent input;
-    private PathIntent compiled;
-
-    private IdGenerator idGenerator;
-    private IntentProcessor processor;
-    private Timestamp version;
-
-    @Before
-    public void setUp() {
-        processor = createMock(IntentProcessor.class);
-        version = createMock(Timestamp.class);
-
-        idGenerator = new MockIdGenerator();
-
-        Intent.bindIdGenerator(idGenerator);
-
-        // Intent creation should be placed after binding an ID generator
-        input = PointToPointIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .ingressPoint(cp1)
-                .egressPoint(cp3)
-                .build();
-        compiled = PathIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .path(path)
-                .build();
-    }
-
-
-    @After
-    public void tearDown() {
-        Intent.unbindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Tests a next phase when no exception occurs.
-     */
-    @Test
-    public void testMoveToNextPhaseWithoutError() {
-        IntentData pending = new IntentData(input, WITHDRAW_REQ, version);
-        IntentData current = new IntentData(input, INSTALLED, version);
-        current.setInstallables(Arrays.asList(compiled));
-
-        FlowRuleOperations operations = createMock(FlowRuleOperations.class);
-        expect(processor.uninstallCoordinate(current, pending)).andReturn(operations);
-        replay(processor);
-
-        WithdrawCoordinating sut = new WithdrawCoordinating(processor, pending, current);
-
-        Optional<IntentProcessPhase> executed = sut.execute();
-        verify(processor);
-        assertThat(executed.get(), is(instanceOf(Withdrawing.class)));
-    }
-
-    /**
-     * Tests a next phase when IntentRemovalExceptionOccurs.
-     */
-    @Test
-    public void testWhenIntentRemovalExceptionOccurs() {
-        IntentData pending = new IntentData(input, WITHDRAW_REQ, version);
-        IntentData current = new IntentData(input, INSTALLED, version);
-        current.setInstallables(Arrays.asList(compiled));
-
-        expect(processor.uninstallCoordinate(current, pending)).andThrow(new IntentRemovalException());
-        replay(processor);
-
-        WithdrawCoordinating sut = new WithdrawCoordinating(processor, pending, current);
-
-        Optional<IntentProcessPhase> executed = sut.execute();
-        verify(processor);
-        assertThat(executed.get(), is(instanceOf(WithdrawingFailed.class)));
-    }
-
-}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawingTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawingTest.java
deleted file mode 100644
index 6f7f267..0000000
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/phase/WithdrawingTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.phase;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.onosproject.TestApplicationId;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.IdGenerator;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultLink;
-import org.onosproject.net.DefaultPath;
-import org.onosproject.net.Link;
-import org.onosproject.net.Path;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.FlowRuleOperations;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentData;
-import org.onosproject.net.intent.MockIdGenerator;
-import org.onosproject.net.intent.PathIntent;
-import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.net.intent.impl.IntentProcessor;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.store.Timestamp;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.Link.Type.DIRECT;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.net.intent.IntentState.INSTALLED;
-import static org.onosproject.net.intent.IntentState.WITHDRAW_REQ;
-
-/**
- * Unit tests for Withdrawing phase.
- */
-public class WithdrawingTest {
-
-    private final ApplicationId appId = new TestApplicationId("test");
-    private final ProviderId pid = new ProviderId("of", "test");
-    private final TrafficSelector selector = DefaultTrafficSelector.emptySelector();
-    private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
-    private final ConnectPoint cp1 = new ConnectPoint(deviceId("1"), portNumber(1));
-    private final ConnectPoint cp2 = new ConnectPoint(deviceId("1"), portNumber(2));
-    private final ConnectPoint cp3 = new ConnectPoint(deviceId("2"), portNumber(1));
-    private final ConnectPoint cp4 = new ConnectPoint(deviceId("2"), portNumber(2));
-
-    private final List<Link> links = Arrays.asList(new DefaultLink(pid, cp2, cp4, DIRECT));
-    private final Path path = new DefaultPath(pid, links, 10);
-
-    private PointToPointIntent input;
-    private PathIntent compiled;
-
-    private IdGenerator idGenerator;
-    private IntentProcessor processor;
-    private Timestamp version;
-
-    @Before
-    public void setUp() {
-        processor = createMock(IntentProcessor.class);
-        version = createMock(Timestamp.class);
-
-        idGenerator = new MockIdGenerator();
-
-        Intent.bindIdGenerator(idGenerator);
-
-        // Intent creation should be placed after binding an ID generator
-        input = PointToPointIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .ingressPoint(cp1)
-                .egressPoint(cp3)
-                .build();
-        compiled = PathIntent.builder()
-                .appId(appId)
-                .selector(selector)
-                .treatment(treatment)
-                .path(path)
-                .build();
-    }
-
-
-    @After
-    public void tearDown() {
-        Intent.unbindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Tests a next phase when no exception occurs.
-     */
-    @Test
-    public void testMoveToNextPhaseWithoutError() {
-        IntentData pending = new IntentData(input, WITHDRAW_REQ, version);
-        IntentData current = new IntentData(input, INSTALLED, version);
-        current.setInstallables(Arrays.asList(compiled));
-
-        FlowRuleOperations operations = createMock(FlowRuleOperations.class);
-        processor.applyFlowRules(operations);
-        replay(processor);
-
-        Withdrawing sut = new Withdrawing(processor, pending, operations);
-
-        Optional<IntentProcessPhase> executed = sut.execute();
-        verify(processor);
-        assertThat(executed.get(), is(instanceOf(Withdrawn.class)));
-    }
-}