Initial implementation of CORRUPT state (ONOS-1060)

- Added CORRUPT state to state machine and event type
- Simplified phases using new request field
- Improved null-safety by using Optionals

Change-Id: I1d576b719765b5664aef73477ee04593e8acc4fd
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentData.java b/core/api/src/main/java/org/onosproject/net/intent/IntentData.java
index b70e7cc..6a9c9ae 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentData.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentData.java
@@ -22,16 +22,12 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.net.intent.IntentState.FAILED;
-import static org.onosproject.net.intent.IntentState.INSTALLED;
-import static org.onosproject.net.intent.IntentState.INSTALLING;
-import static org.onosproject.net.intent.IntentState.PURGE_REQ;
-import static org.onosproject.net.intent.IntentState.WITHDRAWING;
-import static org.onosproject.net.intent.IntentState.WITHDRAWN;
+import static org.onosproject.net.intent.IntentState.*;
 
 /**
  * A wrapper class that contains an intents, its state, and other metadata for
@@ -44,6 +40,7 @@
 
     private final Intent intent;
 
+    private final IntentState request; //TODO perhaps we want a full fledged object for requests
     private IntentState state;
     private Timestamp version;
     private NodeId origin;
@@ -60,6 +57,7 @@
     public IntentData(Intent intent, IntentState state, Timestamp version) {
         this.intent = intent;
         this.state = state;
+        this.request = state;
         this.version = version;
     }
 
@@ -73,6 +71,7 @@
 
         intent = intentData.intent;
         state = intentData.state;
+        request = intentData.request;
         version = intentData.version;
         origin = intentData.origin;
         installables = intentData.installables;
@@ -81,6 +80,7 @@
     // kryo constructor
     protected IntentData() {
         intent = null;
+        request = null;
     }
 
     /**
@@ -101,6 +101,10 @@
         return state;
     }
 
+    public IntentState request() {
+        return request;
+    }
+
     /**
      * Returns the intent key.
      *
@@ -175,7 +179,7 @@
      * @return list of installable intents
      */
     public List<Intent> installables() {
-        return installables;
+        return installables != null ? installables : Collections.emptyList();
     }
 
     /**
@@ -240,6 +244,12 @@
             }
             return true;
 
+        case CORRUPT:
+            if (currentState == CORRUPT) {
+                return false;
+            }
+            return true;
+
         case PURGE_REQ:
             return true;
 
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java b/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java
index f73cee5..369636a 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentEvent.java
@@ -34,7 +34,8 @@
         INSTALLED,
 
         /**
-         * Signifies that an intent has failed compilation or installation.
+         * Signifies that an intent has failed compilation and that it cannot
+         * be satisfied by the network at this time.
          */
         FAILED,
 
@@ -49,6 +50,13 @@
         WITHDRAWN,
 
         /**
+         * Signifies that an intent has failed installation or withdrawal, but
+         * still hold some or all of its resources.
+         * (e.g. link reservations, flow rules on the data plane, etc.)
+         */
+        CORRUPT,
+
+        /**
          * Signifies that an intent has been purged from the system.
          */
         PURGED
@@ -115,6 +123,9 @@
             case FAILED:
                 type = Type.FAILED;
                 break;
+            case CORRUPT:
+                type = Type.CORRUPT;
+                break;
             case PURGE_REQ:
                 type = Type.PURGED;
                 break;
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentState.java b/core/api/src/main/java/org/onosproject/net/intent/IntentState.java
index 3b3d391..e36bf4c 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentState.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentState.java
@@ -89,10 +89,19 @@
     WITHDRAWN,
 
     /**
-     * Signifies that the intent has failed compiling, installing or
-     * recompiling states.
+     * Signifies that the intent has failed to be installed and cannot be
+     * satisfied given current network conditions. But, the framework will
+     * reattempt to install it when network conditions change until it is
+     * withdrawn by an application.
      */
-    FAILED, //TODO consider renaming to UNSAT.
+    FAILED, //TODO consider renaming to UNSATISFIABLE
+
+    /**
+     * Signifies that an intent has failed either installation or withdrawal,
+     * and still hold some or all of its resources.
+     * (e.g. link reservations, flow rules on the data plane, etc.)
+     */
+    CORRUPT, //TODO consider renaming to ERROR
 
     /**
      * Indicates that the intent should be purged from the database.