Refactoring intent API.
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/ConnectivityIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/ConnectivityIntentTest.java
index 10a0069..03b101a 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/ConnectivityIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/ConnectivityIntentTest.java
@@ -2,6 +2,8 @@
 
 import java.util.Set;
 
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.TestApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.PortNumber;
@@ -15,6 +17,8 @@
  */
 public abstract class ConnectivityIntentTest extends IntentTest {
 
+    public static final ApplicationId APPID = new TestApplicationId("foo");
+
     public static final IntentId IID = new IntentId(123);
     public static final TrafficSelector MATCH = DefaultTrafficSelector.builder().build();
     public static final TrafficTreatment NOP = DefaultTrafficTreatment.builder().build();
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/FakeIntentManager.java b/core/api/src/test/java/org/onlab/onos/net/intent/FakeIntentManager.java
index 58c5a9c..4b3fd37 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/FakeIntentManager.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/FakeIntentManager.java
@@ -18,11 +18,11 @@
 
     private final Map<IntentId, Intent> intents = new HashMap<>();
     private final Map<IntentId, IntentState> intentStates = new HashMap<>();
-    private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>();
+    private final Map<IntentId, List<Intent>> installables = new HashMap<>();
     private final Set<IntentListener> listeners = new HashSet<>();
 
     private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
-    private final Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> installers
+    private final Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> installers
         = new HashMap<>();
 
     private final ExecutorService executor = Executors.newSingleThreadExecutor();
@@ -54,7 +54,7 @@
             @Override
             public void run() {
                 try {
-                    List<InstallableIntent> installable = getInstallable(intent.id());
+                    List<Intent> installable = getInstallable(intent.id());
                     executeWithdrawingPhase(intent, installable);
                 } catch (IntentException e) {
                     exceptions.add(e);
@@ -73,7 +73,7 @@
         return compiler;
     }
 
-    private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
+    private <T extends Intent> IntentInstaller<T> getInstaller(T intent) {
         @SuppressWarnings("unchecked")
         IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
                 .getClass());
@@ -87,9 +87,9 @@
         setState(intent, IntentState.COMPILING);
         try {
             // For the fake, we compile using a single level pass
-            List<InstallableIntent> installable = new ArrayList<>();
+            List<Intent> installable = new ArrayList<>();
             for (Intent compiled : getCompiler(intent).compile(intent)) {
-                installable.add((InstallableIntent) compiled);
+                installable.add((Intent) compiled);
             }
             executeInstallingPhase(intent, installable);
 
@@ -100,10 +100,10 @@
     }
 
     private void executeInstallingPhase(Intent intent,
-                                        List<InstallableIntent> installable) {
+                                        List<Intent> installable) {
         setState(intent, IntentState.INSTALLING);
         try {
-            for (InstallableIntent ii : installable) {
+            for (Intent ii : installable) {
                 registerSubclassInstallerIfNeeded(ii);
                 getInstaller(ii).install(ii);
             }
@@ -118,10 +118,10 @@
     }
 
     private void executeWithdrawingPhase(Intent intent,
-                                         List<InstallableIntent> installable) {
+                                         List<Intent> installable) {
         setState(intent, IntentState.WITHDRAWING);
         try {
-            for (InstallableIntent ii : installable) {
+            for (Intent ii : installable) {
                 getInstaller(ii).uninstall(ii);
             }
             removeInstallable(intent.id());
@@ -139,7 +139,7 @@
         intentStates.put(intent.id(), state);
     }
 
-    private void putInstallable(IntentId id, List<InstallableIntent> installable) {
+    private void putInstallable(IntentId id, List<Intent> installable) {
         installables.put(id, installable);
     }
 
@@ -147,8 +147,8 @@
         installables.remove(id);
     }
 
-    private List<InstallableIntent> getInstallable(IntentId id) {
-        List<InstallableIntent> installable = installables.get(id);
+    private List<Intent> getInstallable(IntentId id) {
+        List<Intent> installable = installables.get(id);
         if (installable != null) {
             return installable;
         } else {
@@ -228,19 +228,19 @@
     }
 
     @Override
-    public <T extends InstallableIntent> void registerInstaller(Class<T> cls,
+    public <T extends Intent> void registerInstaller(Class<T> cls,
             IntentInstaller<T> installer) {
         installers.put(cls, installer);
     }
 
     @Override
-    public <T extends InstallableIntent> void unregisterInstaller(Class<T> cls) {
+    public <T extends Intent> void unregisterInstaller(Class<T> cls) {
         installers.remove(cls);
     }
 
     @Override
-    public Map<Class<? extends InstallableIntent>,
-    IntentInstaller<? extends InstallableIntent>> getInstallers() {
+    public Map<Class<? extends Intent>,
+    IntentInstaller<? extends Intent>> getInstallers() {
         return Collections.unmodifiableMap(installers);
     }
 
@@ -261,13 +261,13 @@
         }
     }
 
-    private void registerSubclassInstallerIfNeeded(InstallableIntent 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 InstallableIntent class
+                // As long as we're within the Intent class
                 // descendants
-                if (InstallableIntent.class.isAssignableFrom(cls)) {
+                if (Intent.class.isAssignableFrom(cls)) {
                     IntentInstaller<?> installer = installers.get(cls);
                     if (installer != null) {
                         installers.put(intent.getClass(), installer);
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/IntentIdTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/IntentIdTest.java
index 2a0824c..471e397 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/IntentIdTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/IntentIdTest.java
@@ -44,14 +44,8 @@
 
     @Test
     public void valueOf() {
-        IntentId id = new IntentId(12345);
-        assertEquals("incorrect valueOf", id, IntentId.valueOf("12345"));
-    }
-
-    @Test
-    public void valueOfHex() {
         IntentId id = new IntentId(0xdeadbeefL);
-        assertEquals("incorrect valueOf", id, IntentId.valueOf(id.toString()));
+        assertEquals("incorrect valueOf", id, IntentId.valueOf(0xdeadbeefL));
     }
 
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/IntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/IntentTest.java
index a6cedf9..084017b 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/IntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/IntentTest.java
@@ -1,14 +1,12 @@
 package org.onlab.onos.net.intent;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.junit.Test;
+import static org.junit.Assert.*;
 
 /**
  * Base facilities to test various intent tests.
@@ -33,11 +31,7 @@
 
         assertTrue("should be equal", one.equals(like));
         assertEquals("incorrect hashCode", one.hashCode(), like.hashCode());
-
         assertFalse("should not be equal", one.equals(another));
-
-        assertFalse("should not be equal", one.equals(null));
-        assertFalse("should not be equal", one.equals("foo"));
     }
 
     @Test
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntentTest.java
index 66d294a..83bec15 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntentTest.java
@@ -12,7 +12,7 @@
     @Test
     public void basics() {
         MultiPointToSinglePointIntent intent = createOne();
-        assertEquals("incorrect id", IID, intent.id());
+        assertEquals("incorrect id", APPID, intent.appId());
         assertEquals("incorrect match", MATCH, intent.selector());
         assertEquals("incorrect ingress", PS1, intent.ingressPoints());
         assertEquals("incorrect egress", P2, intent.egressPoint());
@@ -20,11 +20,11 @@
 
     @Override
     protected MultiPointToSinglePointIntent createOne() {
-        return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS1, P2);
+        return new MultiPointToSinglePointIntent(APPID, MATCH, NOP, PS1, P2);
     }
 
     @Override
     protected MultiPointToSinglePointIntent createAnother() {
-        return new MultiPointToSinglePointIntent(IID, MATCH, NOP, PS2, P1);
+        return new MultiPointToSinglePointIntent(APPID, MATCH, NOP, PS2, P1);
     }
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
index 7c15c37..715c998 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/PathIntentTest.java
@@ -16,21 +16,19 @@
     @Test
     public void basics() {
         PathIntent intent = createOne();
-        assertEquals("incorrect id", IID, intent.id());
+        assertEquals("incorrect id", APPID, intent.appId());
         assertEquals("incorrect match", MATCH, intent.selector());
         assertEquals("incorrect action", NOP, intent.treatment());
-        assertEquals("incorrect ingress", P1, intent.ingressPoint());
-        assertEquals("incorrect egress", P2, intent.egressPoint());
         assertEquals("incorrect path", PATH1, intent.path());
     }
 
     @Override
     protected PathIntent createOne() {
-        return new PathIntent(IID, MATCH, NOP, P1, P2, PATH1);
+        return new PathIntent(APPID, MATCH, NOP, PATH1);
     }
 
     @Override
     protected PathIntent createAnother() {
-        return new PathIntent(IID, MATCH, NOP, P1, P3, PATH2);
+        return new PathIntent(APPID, MATCH, NOP, PATH2);
     }
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/PointToPointIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/PointToPointIntentTest.java
index e0c5562..9fbc255 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/PointToPointIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/PointToPointIntentTest.java
@@ -12,7 +12,7 @@
     @Test
     public void basics() {
         PointToPointIntent intent = createOne();
-        assertEquals("incorrect id", IID, intent.id());
+        assertEquals("incorrect id", APPID, intent.appId());
         assertEquals("incorrect match", MATCH, intent.selector());
         assertEquals("incorrect ingress", P1, intent.ingressPoint());
         assertEquals("incorrect egress", P2, intent.egressPoint());
@@ -20,11 +20,11 @@
 
     @Override
     protected PointToPointIntent createOne() {
-        return new PointToPointIntent(IID, MATCH, NOP, P1, P2);
+        return new PointToPointIntent(APPID, MATCH, NOP, P1, P2);
     }
 
     @Override
     protected PointToPointIntent createAnother() {
-        return new PointToPointIntent(IID, MATCH, NOP, P2, P1);
+        return new PointToPointIntent(APPID, MATCH, NOP, P2, P1);
     }
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntentTest.java b/core/api/src/test/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntentTest.java
index 64c9292..a1c68ee 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntentTest.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntentTest.java
@@ -12,7 +12,7 @@
     @Test
     public void basics() {
         SinglePointToMultiPointIntent intent = createOne();
-        assertEquals("incorrect id", IID, intent.id());
+        assertEquals("incorrect id", APPID, intent.appId());
         assertEquals("incorrect match", MATCH, intent.selector());
         assertEquals("incorrect ingress", P1, intent.ingressPoint());
         assertEquals("incorrect egress", PS2, intent.egressPoints());
@@ -20,11 +20,11 @@
 
     @Override
     protected SinglePointToMultiPointIntent createOne() {
-        return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P1, PS2);
+        return new SinglePointToMultiPointIntent(APPID, MATCH, NOP, P1, PS2);
     }
 
     @Override
     protected SinglePointToMultiPointIntent createAnother() {
-        return new SinglePointToMultiPointIntent(IID, MATCH, NOP, P2, PS1);
+        return new SinglePointToMultiPointIntent(APPID, MATCH, NOP, P2, PS1);
     }
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/TestInstallableIntent.java b/core/api/src/test/java/org/onlab/onos/net/intent/TestInstallableIntent.java
index 3265925..9476190 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/TestInstallableIntent.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/TestInstallableIntent.java
@@ -1,25 +1,18 @@
 package org.onlab.onos.net.intent;
-//TODO is this the right package?
 
-import org.onlab.onos.net.Link;
-
-import java.util.Collection;
+import org.onlab.onos.TestApplicationId;
 
 /**
  * An installable intent used in the unit test.
- *
- * FIXME: we don't want to expose this class publicly, but the current Kryo
- * serialization mechanism does not allow this class to be private and placed
- * on testing directory.
  */
-public class TestInstallableIntent extends AbstractIntent implements InstallableIntent {
+public class TestInstallableIntent extends Intent {
     /**
      * Constructs an instance with the specified intent ID.
      *
      * @param id intent ID
      */
     public TestInstallableIntent(IntentId id) {
-        super(id);
+        super(id, new TestApplicationId("foo"), null);
     }
 
     /**
@@ -30,7 +23,8 @@
     }
 
     @Override
-    public Collection<Link> requiredLinks() {
-        return null;
+    public boolean isInstallable() {
+        return true;
     }
+
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/TestIntent.java b/core/api/src/test/java/org/onlab/onos/net/intent/TestIntent.java
index 2f30727..a9d1656 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/TestIntent.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/TestIntent.java
@@ -1,21 +1,18 @@
 package org.onlab.onos.net.intent;
-//TODO is this the right package?
+
+import org.onlab.onos.TestApplicationId;
 
 /**
  * An intent used in the unit test.
- *
- * FIXME: we don't want to expose this class publicly, but the current Kryo
- * serialization mechanism does not allow this class to be private and placed
- * on testing directory.
  */
-public class TestIntent extends AbstractIntent {
+public class TestIntent extends Intent {
     /**
      * Constructs an instance with the specified intent ID.
      *
      * @param id intent ID
      */
     public TestIntent(IntentId id) {
-        super(id);
+        super(id, new TestApplicationId("foo"), null);
     }
 
     /**
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassInstallableIntent.java b/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassInstallableIntent.java
index 40765c2..bfeb985 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassInstallableIntent.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassInstallableIntent.java
@@ -1,14 +1,9 @@
 package org.onlab.onos.net.intent;
-//TODO is this the right package?
 
 /**
  * An intent used in the unit test.
- *
- * FIXME: we don't want to expose this class publicly, but the current Kryo
- * serialization mechanism does not allow this class to be private and placed
- * on testing directory.
  */
-public class TestSubclassInstallableIntent extends TestInstallableIntent implements InstallableIntent {
+public class TestSubclassInstallableIntent extends TestInstallableIntent {
     /**
      * Constructs an instance with the specified intent ID.
      *
diff --git a/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassIntent.java b/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassIntent.java
index 43bb0dd..c8d6996 100644
--- a/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassIntent.java
+++ b/core/api/src/test/java/org/onlab/onos/net/intent/TestSubclassIntent.java
@@ -1,12 +1,7 @@
 package org.onlab.onos.net.intent;
-//TODO is this the right package?
 
 /**
  * An intent used in the unit test.
- *
- * FIXME: we don't want to expose this class publicly, but the current Kryo
- * serialization mechanism does not allow this class to be private and placed
- * on testing directory.
  */
 public class TestSubclassIntent extends TestIntent {
     /**