Sketching out what link-state addition would look like; quite easy until we get to the distributed store.
Added unit tests to provide durable-nondurable transitions.
FIxed issue where link could be accidentally activated.
Renamed parameter.

Change-Id: I8aa19a6583ec50dbf28769995f0a8ea9be9a4daa
diff --git a/core/api/src/main/java/org/onlab/onos/net/AnnotationKeys.java b/core/api/src/main/java/org/onlab/onos/net/AnnotationKeys.java
index af74043..de18fc0 100644
--- a/core/api/src/main/java/org/onlab/onos/net/AnnotationKeys.java
+++ b/core/api/src/main/java/org/onlab/onos/net/AnnotationKeys.java
@@ -25,6 +25,17 @@
     private AnnotationKeys() {}
 
     /**
+     * Annotation key for durable links.
+     */
+    public static final String DURABLE = "durable";
+
+    /**
+     * Annotation key for active/inactive links. Links are implicitly
+     * considered active unless explicitly marked otherwise.
+     */
+    public static final String INACTIVE = "inactive";
+
+    /**
      * Annotation key for latency.
      */
     public static final String LATENCY = "latency";
diff --git a/core/api/src/main/java/org/onlab/onos/net/DefaultLink.java b/core/api/src/main/java/org/onlab/onos/net/DefaultLink.java
index a63de3b..6ebd52d 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DefaultLink.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DefaultLink.java
@@ -20,6 +20,7 @@
 import java.util.Objects;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
+import static org.onlab.onos.net.Link.State.ACTIVE;
 
 /**
  * Default infrastructure link model implementation.
@@ -29,22 +30,45 @@
     private final ConnectPoint src;
     private final ConnectPoint dst;
     private final Type type;
+    private final State state;
+    private final boolean isDurable;
 
     /**
-     * Creates an infrastructure link using the supplied information.
+     * Creates an active infrastructure link using the supplied information.
      *
-     * @param providerId provider identity
-     * @param src        link source
-     * @param dst        link destination
-     * @param type       link type
+     * @param providerId  provider identity
+     * @param src         link source
+     * @param dst         link destination
+     * @param type        link type
      * @param annotations optional key/value annotations
      */
     public DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
                        Type type, Annotations... annotations) {
+        this(providerId, src, dst, type, ACTIVE, false, annotations);
+    }
+
+    /**
+     * Creates an infrastructure link using the supplied information.
+     * Links marked as durable will remain in the inventory when a vanish
+     * message is received and instead will be marked as inactive.
+     *
+     * @param providerId  provider identity
+     * @param src         link source
+     * @param dst         link destination
+     * @param type        link type
+     * @param state       link state
+     * @param isDurable   indicates if the link is to be considered durable
+     * @param annotations optional key/value annotations
+     */
+    public DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
+                       Type type, State state,
+                       boolean isDurable, Annotations... annotations) {
         super(providerId, annotations);
         this.src = src;
         this.dst = dst;
         this.type = type;
+        this.state = state;
+        this.isDurable = isDurable;
     }
 
     @Override
@@ -63,6 +87,18 @@
     }
 
     @Override
+    public State state() {
+        return state;
+    }
+
+    @Override
+    public boolean isDurable() {
+        return isDurable;
+    }
+
+    // Note: Durability & state are purposefully omitted form equality & hashCode.
+
+    @Override
     public int hashCode() {
         return Objects.hash(src, dst, type);
     }
@@ -87,6 +123,8 @@
                 .add("src", src)
                 .add("dst", dst)
                 .add("type", type)
+                .add("state", state)
+                .add("durable", isDurable)
                 .toString();
     }
 
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 cdd0f23..cce34fa 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
@@ -55,6 +55,23 @@
     }
 
     /**
+     * Representation of the link state, which applies primarily only to
+     * configured durable links, i.e. those that need to remain present,
+     * but instead be marked as inactive.
+     */
+    public enum State {
+        /**
+         * Signifies that a link is currently active.
+         */
+        ACTIVE,
+
+        /**
+         * Signifies that a link is currently active.
+         */
+        INACTIVE
+    }
+
+    /**
      * Returns the link source connection point.
      *
      * @return link source connection point
@@ -75,4 +92,16 @@
      */
     Type type();
 
+    /**
+     * Returns the link state.
+     */
+    State state();
+
+    /**
+     * Indicates if the link is to be considered durable.
+     *
+     * @return link state
+     */
+    boolean isDurable();
+
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/link/DefaultLinkDescription.java b/core/api/src/main/java/org/onlab/onos/net/link/DefaultLinkDescription.java
index fc3f335..986eb0a 100644
--- a/core/api/src/main/java/org/onlab/onos/net/link/DefaultLinkDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/link/DefaultLinkDescription.java
@@ -34,9 +34,9 @@
     /**
      * Creates a link description using the supplied information.
      *
-     * @param src  link source
-     * @param dst  link destination
-     * @param type link type
+     * @param src         link source
+     * @param dst         link destination
+     * @param type        link type
      * @param annotations optional key/value annotations
      */
     public DefaultLinkDescription(ConnectPoint src, ConnectPoint dst,
@@ -64,9 +64,10 @@
 
     @Override
     public String toString() {
-        return MoreObjects.toStringHelper("Link").add("src", src())
-                                .add("dst", dst())
-                                .add("type", type()).toString();
+        return MoreObjects.toStringHelper(this)
+                .add("src", src())
+                .add("dst", dst())
+                .add("type", type()).toString();
     }
 
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java b/core/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java
index 3343451..3078243 100644
--- a/core/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java
+++ b/core/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java
@@ -45,6 +45,5 @@
      */
     Link.Type type();
 
-
     // Add further link attributes
 }
diff --git a/core/api/src/main/java/org/onlab/onos/net/link/LinkEvent.java b/core/api/src/main/java/org/onlab/onos/net/link/LinkEvent.java
index b164b9e..763e95e 100644
--- a/core/api/src/main/java/org/onlab/onos/net/link/LinkEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/link/LinkEvent.java
@@ -33,7 +33,7 @@
         LINK_ADDED,
 
         /**
-         * Signifies that a link has been updated.
+         * Signifies that a link has been updated or changed state.
          */
         LINK_UPDATED,
 
diff --git a/core/api/src/main/java/org/onlab/onos/net/link/LinkStore.java b/core/api/src/main/java/org/onlab/onos/net/link/LinkStore.java
index 95962e7..3af4f9f 100644
--- a/core/api/src/main/java/org/onlab/onos/net/link/LinkStore.java
+++ b/core/api/src/main/java/org/onlab/onos/net/link/LinkStore.java
@@ -95,6 +95,16 @@
                                         LinkDescription linkDescription);
 
     /**
+     * Removes the link, or marks it as inactive if the link is durable,
+     * based on the specified information.
+     *
+     * @param src link source
+     * @param dst link destination
+     * @return remove or update link event, or null if no change resulted
+     */
+    LinkEvent removeOrDownLink(ConnectPoint src, ConnectPoint dst);
+
+    /**
      * Removes the link based on the specified information.
      *
      * @param src link source
@@ -103,4 +113,5 @@
      */
     LinkEvent removeLink(ConnectPoint src, ConnectPoint dst);
 
+
 }
diff --git a/core/api/src/test/java/org/onlab/onos/net/link/LinkServiceAdapter.java b/core/api/src/test/java/org/onlab/onos/net/link/LinkServiceAdapter.java
index 17a570a..0e25e2a 100644
--- a/core/api/src/test/java/org/onlab/onos/net/link/LinkServiceAdapter.java
+++ b/core/api/src/test/java/org/onlab/onos/net/link/LinkServiceAdapter.java
@@ -78,5 +78,4 @@
     public void removeListener(LinkListener listener) {
     }
 
-
 }