Merge remote-tracking branch 'origin/master'
diff --git a/core/api/src/main/java/org/onlab/onos/net/Link.java b/core/api/src/main/java/org/onlab/onos/net/Link.java
index be2f99bf..1ae5b9d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/Link.java
+++ b/core/api/src/main/java/org/onlab/onos/net/Link.java
@@ -3,7 +3,7 @@
 /**
  * Abstraction of a network infrastructure link.
  */
-public interface Link extends Annotated, Provided {
+public interface Link extends Annotated, Provided, NetworkResource {
 
     /**
      * Coarse representation of the link type.
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/AbstractIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/AbstractIntent.java
deleted file mode 100644
index c8a4a05..0000000
--- a/core/api/src/main/java/org/onlab/onos/net/intent/AbstractIntent.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.onlab.onos.net.intent;
-
-/**
- * Base intent implementation.
- */
-public abstract class AbstractIntent implements Intent {
-
-    private final IntentId id;
-
-    /**
-     * Creates a base intent with the specified identifier.
-     *
-     * @param id intent identifier
-     */
-    protected AbstractIntent(IntentId id) {
-        this.id = id;
-    }
-
-    /**
-     * Constructor for serializer.
-     */
-    protected AbstractIntent() {
-        this.id = null;
-    }
-
-    @Override
-    public IntentId id() {
-        return id;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-
-        AbstractIntent that = (AbstractIntent) o;
-        return id.equals(that.id);
-    }
-
-    @Override
-    public int hashCode() {
-        return id.hashCode();
-    }
-
-}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
index ed0c5cc..e28d8b1 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/ConnectivityIntent.java
@@ -1,15 +1,20 @@
 package org.onlab.onos.net.intent;
 
-import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.NetworkResource;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
+import java.util.Collection;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * Abstraction of connectivity intent for traffic matching some criteria.
  */
-public abstract class ConnectivityIntent extends AbstractIntent {
+public abstract class ConnectivityIntent extends Intent {
 
     // TODO: other forms of intents should be considered for this family:
     //   point-to-point with constraints (waypoints/obstacles)
@@ -19,24 +24,26 @@
     //   ...
 
     private final TrafficSelector selector;
-    // TODO: should consider which is better for multiple actions,
-    // defining compound action class or using list of actions.
     private final TrafficTreatment treatment;
 
     /**
-     * Creates a connectivity intent that matches on the specified intent
-     * and applies the specified treatement.
+     * Creates a connectivity intent that matches on the specified selector
+     * and applies the specified treatment.
      *
-     * @param intentId   intent identifier
-     * @param selector   traffic selector
-     * @param treatement treatement
+     * @param id        intent identifier
+     * @param appId     application identifier
+     * @param resources required network resources (optional)
+     * @param selector  traffic selector
+     * @param treatment treatment
      * @throws NullPointerException if the selector or treatement is null
      */
-    protected ConnectivityIntent(IntentId intentId, TrafficSelector selector,
-                                 TrafficTreatment treatement) {
-        super(intentId);
+    protected ConnectivityIntent(IntentId id, ApplicationId appId,
+                                 Collection<NetworkResource> resources,
+                                 TrafficSelector selector,
+                                 TrafficTreatment treatment) {
+        super(id, appId, resources);
         this.selector = checkNotNull(selector);
-        this.treatment = checkNotNull(treatement);
+        this.treatment = checkNotNull(treatment);
     }
 
     /**
@@ -66,19 +73,9 @@
         return treatment;
     }
 
-    @Override
-    public boolean equals(Object o) {
-        if (!super.equals(o)) {
-            return false;
-        }
-        ConnectivityIntent that = (ConnectivityIntent) o;
-        return Objects.equal(this.selector, that.selector)
-                && Objects.equal(this.treatment, that.treatment);
-    }
 
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(super.hashCode(), selector, treatment);
+    protected static Collection<NetworkResource> resources(Collection<Link> links) {
+        return ImmutableSet.<NetworkResource>copyOf(links);
     }
 
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
index 7a894be6..92b148d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
@@ -1,12 +1,11 @@
 package org.onlab.onos.net.intent;
 
 import com.google.common.base.MoreObjects;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.HostId;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import java.util.Objects;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
@@ -21,7 +20,7 @@
      * Creates a new point-to-point intent with the supplied ingress/egress
      * ports.
      *
-     * @param intentId  intent identifier
+     * @param appId     application identifier
      * @param one       first host
      * @param two       second host
      * @param selector  action
@@ -29,10 +28,11 @@
      * @throws NullPointerException if {@code ingressPort} or {@code egressPort}
      *                              is null.
      */
-    public HostToHostIntent(IntentId intentId, HostId one, HostId two,
+    public HostToHostIntent(ApplicationId appId, HostId one, HostId two,
                             TrafficSelector selector,
                             TrafficTreatment treatment) {
-        super(intentId, selector, treatment);
+        super(id(HostToHostIntent.class, one, two, selector, treatment),
+              appId, null, selector, treatment);
         this.one = checkNotNull(one);
         this.two = checkNotNull(two);
     }
@@ -56,28 +56,6 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        HostToHostIntent that = (HostToHostIntent) o;
-        return Objects.equals(this.one, that.one)
-                && Objects.equals(this.two, that.two);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), one, two);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IdGenerator.java b/core/api/src/main/java/org/onlab/onos/net/intent/IdGenerator.java
index 0bba622..62549e9 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IdGenerator.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IdGenerator.java
@@ -1,17 +1,14 @@
 package org.onlab.onos.net.intent;
-//TODO is this the right package?
 
 /**
  * A generalized interface for ID generation
- *
+ * <p/>
  * {@link #getNewId()} generates a globally unique ID instance on
  * each invocation.
  *
  * @param <T> the type of ID
  */
-// TODO: do we need to define a base marker interface for ID,
-// then changed the type parameter to <T extends BaseId> something
-// like that?
+@Deprecated
 public interface IdGenerator<T> {
     /**
      * Returns a globally unique ID instance.
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/InstallableIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/InstallableIntent.java
deleted file mode 100644
index 488695c..0000000
--- a/core/api/src/main/java/org/onlab/onos/net/intent/InstallableIntent.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.onlab.onos.net.intent;
-
-import org.onlab.onos.net.Link;
-
-import java.util.Collection;
-
-/**
- * Abstraction of an intent that can be installed into
- * the underlying system without additional compilation.
- */
-public interface InstallableIntent extends Intent {
-
-    /**
-     * Returns the collection of links that are required for this installable
-     * intent to exist.
-     *
-     * @return collection of links
-     */
-    // FIXME: replace this with 'NetworkResource'
-    Collection<Link> requiredLinks();
-
-}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
index 3e339d1..f23a448 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/Intent.java
@@ -1,15 +1,109 @@
 package org.onlab.onos.net.intent;
 
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.net.NetworkResource;
+
+import java.util.Collection;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Abstraction of an application level intent.
  * <p/>
  * Make sure that an Intent should be immutable when a new type is defined.
  */
-public interface Intent extends BatchOperationTarget {
+public abstract class Intent implements BatchOperationTarget {
+
+    private final IntentId id;
+    private final ApplicationId appId;
+    private final Collection<NetworkResource> resources;
+
+    /**
+     * Constructor for serializer.
+     */
+    protected Intent() {
+        this.id = null;
+        this.appId = null;
+        this.resources = null;
+    }
+
+    /**
+     * Creates a new intent.
+     *
+     * @param id        intent identifier
+     * @param appId     application identifier
+     * @param resources required network resources (optional)
+     */
+    protected Intent(IntentId id, ApplicationId appId,
+                     Collection<NetworkResource> resources) {
+        this.appId = checkNotNull(appId, "Application ID cannot be null");
+        this.id = checkNotNull(id, "Fingerprint cannot be null");
+        this.resources = resources;
+    }
+
     /**
      * Returns the intent identifier.
      *
+     * @return intent fingerprint
+     */
+    public IntentId id() {
+        return id;
+    }
+
+    /**
+     * Returns the identifier of the application that requested the intent.
+     *
+     * @return application identifier
+     */
+    public ApplicationId appId() {
+        return appId;
+    }
+
+    /**
+     * Returns the collection of resources required for this intent.
+     *
+     * @return collection of resources; may be null
+     */
+    public Collection<NetworkResource> resources() {
+        return resources;
+    }
+
+    /**
+     * Produces an intent identifier backed by hash-like fingerprint for the
+     * specified class of intent and its constituent fields.
+     *
+     * @param fields intent fields
      * @return intent identifier
      */
-    IntentId id();
+    protected static IntentId id(Object... fields) {
+        return IntentId.valueOf(Objects.hash(fields));
+    }
+
+    /**
+     * Indicates whether or not the intent is installable.
+     *
+     * @return true if installable
+     */
+    public boolean isInstallable() {
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+        final Intent other = (Intent) obj;
+        return Objects.equals(this.id, other.id);
+    }
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IntentExtensionService.java b/core/api/src/main/java/org/onlab/onos/net/intent/IntentExtensionService.java
index 8deb372..50e803c 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IntentExtensionService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IntentExtensionService.java
@@ -38,7 +38,7 @@
      * @param installer intent installer
      * @param <T>       the type of installable intent
      */
-    <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
+    <T extends Intent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
 
     /**
      * Unregisters the installer for the given installable intent class.
@@ -46,12 +46,12 @@
      * @param cls installable intent class
      * @param <T> the type of installable intent
      */
-    <T extends InstallableIntent> void unregisterInstaller(Class<T> cls);
+    <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 InstallableIntent>, IntentInstaller<? extends InstallableIntent>> getInstallers();
+    Map<Class<? extends Intent>, IntentInstaller<? extends Intent>> getInstallers();
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java b/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
index 8f132c0..8285070 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IntentId.java
@@ -7,43 +7,37 @@
  */
 public final class IntentId implements BatchOperationTarget {
 
-    private static final int DEC = 10;
-    private static final int HEX = 16;
-
-    private final long id;
+    private final long fingerprint;
 
     /**
      * Creates an intent identifier from the specified string representation.
      *
-     * @param value long value
+     * @param fingerprint long value
      * @return intent identifier
      */
-    public static IntentId valueOf(String value) {
-        long id = value.toLowerCase().startsWith("0x")
-                ? Long.parseLong(value.substring(2), HEX)
-                : Long.parseLong(value, DEC);
-        return new IntentId(id);
+    static IntentId valueOf(long fingerprint) {
+        return new IntentId(fingerprint);
     }
 
     /**
      * Constructor for serializer.
      */
-    protected IntentId() {
-        this.id = 0;
+    IntentId() {
+        this.fingerprint = 0;
     }
 
     /**
      * Constructs the ID corresponding to a given long value.
      *
-     * @param id the underlying value of this ID
+     * @param fingerprint the underlying value of this ID
      */
-    public IntentId(long id) {
-        this.id = id;
+    IntentId(long fingerprint) {
+        this.fingerprint = fingerprint;
     }
 
     @Override
     public int hashCode() {
-        return (int) (id ^ (id >>> 32));
+        return (int) (fingerprint ^ (fingerprint >>> 32));
     }
 
     @Override
@@ -51,18 +45,16 @@
         if (obj == this) {
             return true;
         }
-
         if (!(obj instanceof IntentId)) {
             return false;
         }
-
         IntentId that = (IntentId) obj;
-        return this.id == that.id;
+        return this.fingerprint == that.fingerprint;
     }
 
     @Override
     public String toString() {
-        return "0x" + Long.toHexString(id);
+        return "0x" + Long.toHexString(fingerprint);
     }
 
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IntentInstaller.java b/core/api/src/main/java/org/onlab/onos/net/intent/IntentInstaller.java
index 468017f..c403846 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IntentInstaller.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IntentInstaller.java
@@ -7,7 +7,7 @@
 /**
  * Abstraction of entity capable of installing intents to the environment.
  */
-public interface IntentInstaller<T extends InstallableIntent> {
+public interface IntentInstaller<T extends Intent> {
     /**
      * Installs the specified intent to the environment.
      *
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/IntentStore.java b/core/api/src/main/java/org/onlab/onos/net/intent/IntentStore.java
index d693c9b..c234b0f 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/IntentStore.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/IntentStore.java
@@ -77,8 +77,7 @@
      * @param intentId           original intent identifier
      * @param installableIntents compiled installable intents
      */
-    void addInstallableIntents(IntentId intentId,
-                               List<InstallableIntent> installableIntents);
+    void addInstallableIntents(IntentId intentId, List<Intent> installableIntents);
 
     /**
      * Returns the list of the installable events associated with the specified
@@ -87,7 +86,7 @@
      * @param intentId original intent identifier
      * @return compiled installable intents
      */
-    List<InstallableIntent> getInstallableIntents(IntentId intentId);
+    List<Intent> getInstallableIntents(IntentId intentId);
 
     // TODO: this should be triggered from with the store as a result of removeIntent call
 
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
index 6a8b002..7a19613 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
@@ -1,21 +1,19 @@
 package org.onlab.onos.net.intent;
 
-import java.util.Collection;
-import java.util.Objects;
-import java.util.Set;
-
+import com.google.common.base.MoreObjects;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import com.google.common.base.MoreObjects;
+import java.util.Set;
 
 /**
  * Abstraction of a connectivity intent that is implemented by a set of path
  * segments.
  */
-public final class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
+public final class LinkCollectionIntent extends ConnectivityIntent {
 
     private final Set<Link> links;
 
@@ -25,34 +23,33 @@
      * Creates a new point-to-point intent with the supplied ingress/egress
      * ports and using the specified explicit path.
      *
-     * @param id          intent identifier
+     * @param appId       application identifier
      * @param selector    traffic match
      * @param treatment   action
      * @param links       traversed links
      * @param egressPoint egress point
      * @throws NullPointerException {@code path} is null
      */
-    public LinkCollectionIntent(IntentId id,
+    public LinkCollectionIntent(ApplicationId appId,
                                 TrafficSelector selector,
                                 TrafficTreatment treatment,
                                 Set<Link> links,
                                 ConnectPoint egressPoint) {
-        super(id, selector, treatment);
+        super(id(LinkCollectionIntent.class, selector, treatment, links, egressPoint),
+              appId, resources(links), selector, treatment);
         this.links = links;
         this.egressPoint = egressPoint;
     }
 
+    /**
+     * Constructor for serializer.
+     */
     protected LinkCollectionIntent() {
         super();
         this.links = null;
         this.egressPoint = null;
     }
 
-    @Override
-    public Collection<Link> requiredLinks() {
-        return links;
-    }
-
     /**
      * Returns the set of links that represent the network connections needed
      * by this intent.
@@ -73,26 +70,8 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        LinkCollectionIntent that = (LinkCollectionIntent) o;
-
-        return Objects.equals(this.links, that.links) &&
-                Objects.equals(this.egressPoint, that.egressPoint);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), links, egressPoint);
+    public boolean isInstallable() {
+        return true;
     }
 
     @Override
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
index 8ee4a9e..a09291f 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/MultiPointToSinglePointIntent.java
@@ -2,11 +2,11 @@
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.Sets;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import java.util.Objects;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -22,11 +22,11 @@
 
     /**
      * Creates a new multi-to-single point connectivity intent for the specified
-     * traffic match and action.
+     * traffic selector and treatment.
      *
-     * @param id           intent identifier
-     * @param match        traffic match
-     * @param action       action
+     * @param appId         application identifier
+     * @param selector      traffic selector
+     * @param treatment     treatment
      * @param ingressPoints set of ports from which ingress traffic originates
      * @param egressPoint   port to which traffic will egress
      * @throws NullPointerException     if {@code ingressPoints} or
@@ -34,15 +34,16 @@
      * @throws IllegalArgumentException if the size of {@code ingressPoints} is
      *                                  not more than 1
      */
-    public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match,
-                                         TrafficTreatment action,
+    public MultiPointToSinglePointIntent(ApplicationId appId,
+                                         TrafficSelector selector,
+                                         TrafficTreatment treatment,
                                          Set<ConnectPoint> ingressPoints,
                                          ConnectPoint egressPoint) {
-        super(id, match, action);
+        super(id(MultiPointToSinglePointIntent.class, selector, treatment,
+                 ingressPoints, egressPoint), appId, null, selector, treatment);
 
         checkNotNull(ingressPoints);
-        checkArgument(!ingressPoints.isEmpty(),
-                      "there should be at least one ingress port");
+        checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty");
 
         this.ingressPoints = Sets.newHashSet(ingressPoints);
         this.egressPoint = checkNotNull(egressPoint);
@@ -77,28 +78,6 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        MultiPointToSinglePointIntent that = (MultiPointToSinglePointIntent) o;
-        return Objects.equals(this.ingressPoints, that.ingressPoints)
-                && Objects.equals(this.egressPoint, that.egressPoint);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), ingressPoints, egressPoint);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
deleted file mode 100644
index b99eb70..0000000
--- a/core/api/src/main/java/org/onlab/onos/net/intent/OpticalConnectivityIntent.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.onlab.onos.net.intent;
-
-import org.onlab.onos.net.ConnectPoint;
-
-// TODO: consider if this intent should be sub-class of ConnectivityIntent
-
-/**
- * An optical layer Intent for a connectivity from a transponder port to another
- * transponder port.
- * <p/>
- * This class doesn't accepts lambda specifier. This class computes path between
- * ports and assign lambda automatically. The lambda can be specified using
- * OpticalPathFlow class.
- */
-public class OpticalConnectivityIntent extends AbstractIntent {
-    protected ConnectPoint src;
-    protected ConnectPoint dst;
-
-    /**
-     * Constructor.
-     *
-     * @param id  ID for this new Intent object.
-     * @param src The source transponder port.
-     * @param dst The destination transponder port.
-     */
-    public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
-        super(id);
-        this.src = src;
-        this.dst = dst;
-    }
-
-    /**
-     * Constructor for serializer.
-     */
-    protected OpticalConnectivityIntent() {
-        super();
-        this.src = null;
-        this.dst = null;
-    }
-
-    /**
-     * Gets source transponder port.
-     *
-     * @return The source transponder port.
-     */
-    public ConnectPoint getSrcConnectPoint() {
-        return src;
-    }
-
-    /**
-     * Gets destination transponder port.
-     *
-     * @return The source transponder port.
-     */
-    public ConnectPoint getDst() {
-        return dst;
-    }
-}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PacketConnectivityIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PacketConnectivityIntent.java
deleted file mode 100644
index 893d70e..0000000
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PacketConnectivityIntent.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package org.onlab.onos.net.intent;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.onlab.onos.net.ConnectPoint;
-import org.onlab.onos.net.flow.TrafficSelector;
-
-// TODO: consider if this intent should be sub-class of Connectivity intent
-/**
- * A packet layer Intent for a connectivity from a set of ports to a set of
- * ports.
- * <p>
- * TODO: Design methods to support the ReactiveForwarding and the SDN-IP. <br>
- * NOTE: Should this class support modifier methods? Should this object a
- * read-only object?
- */
-public class PacketConnectivityIntent extends AbstractIntent {
-    protected Set<ConnectPoint> srcConnectPoints;
-    protected TrafficSelector selector;
-    protected Set<ConnectPoint> dstConnectPoints;
-    protected boolean canSetupOpticalFlow;
-    protected int idleTimeoutValue;
-    protected int hardTimeoutValue;
-
-    /**
-     * Creates a connectivity intent for the packet layer.
-     * <p>
-     * When the "canSetupOpticalFlow" option is true, this intent will compute
-     * the packet/optical converged path, decompose it to the OpticalPathFlow
-     * and the PacketPathFlow objects, and execute the operations to add them
-     * considering the dependency between the packet and optical layers.
-     *
-     * @param id ID for this new Intent object.
-     * @param srcConnectPoints The set of source switch ports.
-     * @param match Traffic specifier for this object.
-     * @param dstConnectPoints The set of destination switch ports.
-     * @param canSetupOpticalFlow The flag whether this intent can create
-     *        optical flows if needed.
-     */
-    public PacketConnectivityIntent(IntentId id,
-            Collection<ConnectPoint> srcConnectPoints, TrafficSelector match,
-            Collection<ConnectPoint> dstConnectPoints, boolean canSetupOpticalFlow) {
-        super(id);
-        this.srcConnectPoints = new HashSet<ConnectPoint>(srcConnectPoints);
-        this.selector = match;
-        this.dstConnectPoints = new HashSet<ConnectPoint>(dstConnectPoints);
-        this.canSetupOpticalFlow = canSetupOpticalFlow;
-        this.idleTimeoutValue = 0;
-        this.hardTimeoutValue = 0;
-
-        // TODO: check consistency between these parameters.
-    }
-
-    /**
-     * Constructor for serializer.
-     */
-    protected PacketConnectivityIntent() {
-        super();
-        this.srcConnectPoints = null;
-        this.selector = null;
-        this.dstConnectPoints = null;
-        this.canSetupOpticalFlow = false;
-        this.idleTimeoutValue = 0;
-        this.hardTimeoutValue = 0;
-    }
-
-    /**
-     * Gets the set of source switch ports.
-     *
-     * @return the set of source switch ports.
-     */
-    public Collection<ConnectPoint> getSrcConnectPoints() {
-        return Collections.unmodifiableCollection(srcConnectPoints);
-    }
-
-    /**
-     * Gets the traffic specifier.
-     *
-     * @return The traffic specifier.
-     */
-    public TrafficSelector getMatch() {
-        return selector;
-    }
-
-    /**
-     * Gets the set of destination switch ports.
-     *
-     * @return the set of destination switch ports.
-     */
-    public Collection<ConnectPoint> getDstConnectPoints() {
-        return Collections.unmodifiableCollection(dstConnectPoints);
-    }
-
-    /**
-     * Adds the specified port to the set of source ports.
-     *
-     * @param port ConnectPoint object to be added
-     */
-    public void addSrcConnectPoint(ConnectPoint port) {
-        // TODO implement it.
-    }
-
-    /**
-     * Adds the specified port to the set of destination ports.
-     *
-     * @param port ConnectPoint object to be added
-     */
-    public void addDstConnectPoint(ConnectPoint port) {
-        // TODO implement it.
-    }
-
-    /**
-     * Removes the specified port from the set of source ports.
-     *
-     * @param port ConnectPoint object to be removed
-     */
-    public void removeSrcConnectPoint(ConnectPoint port) {
-        // TODO implement it.
-    }
-
-    /**
-     * Removes the specified port from the set of destination ports.
-     *
-     * @param port ConnectPoint object to be removed
-     */
-    public void removeDstConnectPoint(ConnectPoint port) {
-        // TODO implement it.
-    }
-
-    /**
-     * Sets idle-timeout value.
-     *
-     * @param timeout Idle-timeout value (seconds)
-     */
-    public void setIdleTimeout(int timeout) {
-        idleTimeoutValue = timeout;
-    }
-
-    /**
-     * Sets hard-timeout value.
-     *
-     * @param timeout Hard-timeout value (seconds)
-     */
-    public void setHardTimeout(int timeout) {
-        hardTimeoutValue = timeout;
-    }
-
-    /**
-     * Gets idle-timeout value.
-     *
-     * @return Idle-timeout value (seconds)
-     */
-    public int getIdleTimeout() {
-        return idleTimeoutValue;
-    }
-
-    /**
-     * Gets hard-timeout value.
-     *
-     * @return Hard-timeout value (seconds)
-     */
-    public int getHardTimeout() {
-        return hardTimeoutValue;
-    }
-
-    /**
-     * Returns whether this intent can create optical flows if needed.
-     *
-     * @return whether this intent can create optical flows.
-     */
-    public boolean canSetupOpticalFlow() {
-        return canSetupOpticalFlow;
-    }
-}
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
index ff2e917..4138172 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PathIntent.java
@@ -1,19 +1,15 @@
 package org.onlab.onos.net.intent;
 
 import com.google.common.base.MoreObjects;
-import org.onlab.onos.net.ConnectPoint;
-import org.onlab.onos.net.Link;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.Path;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import java.util.Collection;
-import java.util.Objects;
-
 /**
  * Abstraction of explicitly path specified connectivity intent.
  */
-public class PathIntent extends PointToPointIntent implements InstallableIntent {
+public class PathIntent extends ConnectivityIntent {
 
     private final Path path;
 
@@ -21,21 +17,22 @@
      * Creates a new point-to-point intent with the supplied ingress/egress
      * ports and using the specified explicit path.
      *
-     * @param id          intent identifier
-     * @param match       traffic match
-     * @param action      action
-     * @param ingressPort ingress port
-     * @param egressPort  egress port
-     * @param path        traversed links
+     * @param appId     application identifier
+     * @param selector  traffic selector
+     * @param treatment treatment
+     * @param path      traversed links
      * @throws NullPointerException {@code path} is null
      */
-    public PathIntent(IntentId id, TrafficSelector match, TrafficTreatment action,
-                      ConnectPoint ingressPort, ConnectPoint egressPort,
-                      Path path) {
-        super(id, match, action, ingressPort, egressPort);
+    public PathIntent(ApplicationId appId, TrafficSelector selector,
+                      TrafficTreatment treatment, Path path) {
+        super(id(PathIntent.class, selector, treatment, path), appId,
+              resources(path.links()), selector, treatment);
         this.path = path;
     }
 
+    /**
+     * Constructor for serializer.
+     */
     protected PathIntent() {
         super();
         this.path = null;
@@ -51,46 +48,18 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        PathIntent that = (PathIntent) o;
-
-        if (!path.equals(that.path)) {
-            return false;
-        }
-
+    public boolean isInstallable() {
         return true;
     }
 
     @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), path);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
                 .add("match", selector())
                 .add("action", treatment())
-                .add("ingressPort", ingressPoint())
-                .add("egressPort", egressPoint())
                 .add("path", path)
                 .toString();
     }
 
-    @Override
-    public Collection<Link> requiredLinks() {
-        return path.links();
-    }
-
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
index 7b7c18a..fa206bc 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntent.java
@@ -1,12 +1,11 @@
 package org.onlab.onos.net.intent;
 
 import com.google.common.base.MoreObjects;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import java.util.Objects;
-
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
@@ -21,18 +20,19 @@
      * Creates a new point-to-point intent with the supplied ingress/egress
      * ports.
      *
-     * @param id           intent identifier
+     * @param appId        application identifier
      * @param selector     traffic selector
      * @param treatment    treatment
      * @param ingressPoint ingress port
      * @param egressPoint  egress port
      * @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null.
      */
-    public PointToPointIntent(IntentId id, TrafficSelector selector,
+    public PointToPointIntent(ApplicationId appId, TrafficSelector selector,
                               TrafficTreatment treatment,
                               ConnectPoint ingressPoint,
                               ConnectPoint egressPoint) {
-        super(id, selector, treatment);
+        super(id(PointToPointIntent.class, selector, treatment, ingressPoint, egressPoint),
+              appId, null, selector, treatment);
         this.ingressPoint = checkNotNull(ingressPoint);
         this.egressPoint = checkNotNull(egressPoint);
     }
@@ -66,28 +66,6 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        PointToPointIntent that = (PointToPointIntent) o;
-        return Objects.equals(this.ingressPoint, that.ingressPoint)
-                && Objects.equals(this.egressPoint, that.egressPoint);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), ingressPoint, egressPoint);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
index 2a17bfe..7e40cdc 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/SinglePointToMultiPointIntent.java
@@ -2,11 +2,11 @@
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.Sets;
+import org.onlab.onos.ApplicationId;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import java.util.Objects;
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -23,7 +23,7 @@
     /**
      * Creates a new single-to-multi point connectivity intent.
      *
-     * @param id           intent identifier
+     * @param appId        application identifier
      * @param selector     traffic selector
      * @param treatment    treatment
      * @param ingressPoint port on which traffic will ingress
@@ -33,16 +33,15 @@
      * @throws IllegalArgumentException if the size of {@code egressPoints} is
      *                                  not more than 1
      */
-    public SinglePointToMultiPointIntent(IntentId id, TrafficSelector selector,
+    public SinglePointToMultiPointIntent(ApplicationId appId,
+                                         TrafficSelector selector,
                                          TrafficTreatment treatment,
                                          ConnectPoint ingressPoint,
                                          Set<ConnectPoint> egressPoints) {
-        super(id, selector, treatment);
-
+        super(id(SinglePointToMultiPointIntent.class, selector, treatment,
+                 ingressPoint, egressPoints), appId, null, selector, treatment);
         checkNotNull(egressPoints);
-        checkArgument(!egressPoints.isEmpty(),
-                      "there should be at least one egress port");
-
+        checkArgument(!egressPoints.isEmpty(), "Egress point set cannot be empty");
         this.ingressPoint = checkNotNull(ingressPoint);
         this.egressPoints = Sets.newHashSet(egressPoints);
     }
@@ -75,28 +74,6 @@
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        if (!super.equals(o)) {
-            return false;
-        }
-
-        SinglePointToMultiPointIntent that = (SinglePointToMultiPointIntent) o;
-        return Objects.equals(this.ingressPoint, that.ingressPoint)
-                && Objects.equals(this.egressPoints, that.egressPoints);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(super.hashCode(), ingressPoint, egressPoints);
-    }
-
-    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
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 {
     /**
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
index c7f656a..0ec8612 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
@@ -1,20 +1,10 @@
 package org.onlab.onos.store.trivial.impl;
 
-import static org.onlab.onos.net.intent.IntentState.FAILED;
-import static org.onlab.onos.net.intent.IntentState.INSTALLED;
-import static org.onlab.onos.net.intent.IntentState.SUBMITTED;
-import static org.onlab.onos.net.intent.IntentState.WITHDRAWN;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
+import com.google.common.collect.ImmutableSet;
 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.Service;
-import org.onlab.onos.net.intent.InstallableIntent;
 import org.onlab.onos.net.intent.Intent;
 import org.onlab.onos.net.intent.IntentEvent;
 import org.onlab.onos.net.intent.IntentId;
@@ -24,7 +14,12 @@
 import org.onlab.onos.store.AbstractStore;
 import org.slf4j.Logger;
 
-import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.onlab.onos.net.intent.IntentState.*;
+import static org.slf4j.LoggerFactory.getLogger;
 
 @Component(immediate = true)
 @Service
@@ -35,7 +30,7 @@
     private final Logger log = getLogger(getClass());
     private final Map<IntentId, Intent> intents = new ConcurrentHashMap<>();
     private final Map<IntentId, IntentState> states = new ConcurrentHashMap<>();
-    private final Map<IntentId, List<InstallableIntent>> installable =
+    private final Map<IntentId, List<Intent>> installable =
             new ConcurrentHashMap<>();
 
     @Activate
@@ -96,12 +91,12 @@
     }
 
     @Override
-    public void addInstallableIntents(IntentId intentId, List<InstallableIntent> result) {
+    public void addInstallableIntents(IntentId intentId, List<Intent> result) {
         installable.put(intentId, result);
     }
 
     @Override
-    public List<InstallableIntent> getInstallableIntents(IntentId intentId) {
+    public List<Intent> getInstallableIntents(IntentId intentId) {
         return installable.get(intentId);
     }