ONOS-7451 ODTN TAPI connectivity service.

(still JSON cannot be converted to DataNode)

Completed with RPC PoC for ONOS-7451

Fixed style errors (import Yang classes > 120)

Change-Id: Ie565576a604ee1ccf3d046e7e461c1d132234e8f
diff --git a/apps/odtn/BUCK b/apps/odtn/BUCK
index 15eb273..60c82cb 100644
--- a/apps/odtn/BUCK
+++ b/apps/odtn/BUCK
@@ -10,6 +10,7 @@
     'org.onosproject.drivers.netconf',
     'org.onosproject.netconf',
     'org.onosproject.configsync-netconf',
+    'org.onosproject.protocols.restconfserver'
 ]
 
 COMPILE_DEPS = [
@@ -19,6 +20,9 @@
     '//apps/config:onos-apps-config',
     '//models/tapi:onos-models-tapi',
     '//models/openconfig:onos-models-openconfig',
+    '//apps/yang:onos-apps-yang',
+    '//incubator/api:onos-incubator-api',
+    '//lib:COMPILE'
 ]
 
 TEST_DEPS = [
diff --git a/apps/odtn/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java b/apps/odtn/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
index 1facc0c..12b5e51 100644
--- a/apps/odtn/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
+++ b/apps/odtn/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
@@ -12,21 +12,65 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
+ *
+ *
+ * This work was partially supported by EC H2020 project METRO-HAUL (761727).
+ * Contact: Ramon Casellas <ramon.casellas@cttc.es>
  */
+
 package org.onosproject.odtn.impl;
 
+import java.util.List;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.config.DynamicConfigService;
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.yang.model.SchemaContextProvider;
 import org.onosproject.yang.runtime.YangRuntimeService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.onosproject.config.DynamicConfigListener;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.DynamicConfigEvent;
+import org.onosproject.config.Filter;
+import org.onosproject.config.FailedException;
+import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
+import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
+
+// import org.onosproject.yang.gen.v1.tapiconnectivity.rev20180216.TapiConnectivity;
+import org.onosproject.yang.gen.v1.tapiconnectivity.rev20180216.TapiConnectivityService;
+
+import org.onosproject.yang.gen.v1.tapiconnectivity.rev20180216.
+    tapiconnectivity.createconnectivityservice.CreateConnectivityServiceInput;
+
+import org.onosproject.yang.gen.v1.tapiconnectivity.rev20180216.
+    tapiconnectivity.createconnectivityservice.createconnectivityserviceinput.EndPoint;
+
+
+
+// onos-yang-tools
+import org.onosproject.yang.model.DataNode;
+
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.DefaultResourceData;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelConverter;
+
+import org.onosproject.yang.model.ResourceId;
+import org.onosproject.yang.model.SchemaId;
+
+import org.onosproject.yang.model.RpcRegistry;
+import org.onosproject.yang.model.RpcService;
+import org.onosproject.yang.model.RpcInput;
+import org.onosproject.yang.model.RpcOutput;
+
+
 /**
  * OSGi Component for ODTN Service application.
  */
@@ -47,14 +91,254 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected SchemaContextProvider schemaContextProvider;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected RpcRegistry rpcRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ModelConverter modelConverter;
+
+
+
+    // Listener for events from the DCS
+    private final DynamicConfigListener dynamicConfigServiceListener =
+        new InternalDynamicConfigListener();
+
+    // Rpc Service for TAPI Connectivity
+    private final RpcService rpcTapiConnectivity =
+        new TapiConnectivityRpc();
+
+
     @Activate
     protected void activate() {
         log.info("Started");
+        dynConfigService.addListener(dynamicConfigServiceListener);
+        rpcRegistry.registerRpcService(rpcTapiConnectivity);
     }
 
+
     @Deactivate
     protected void deactivate() {
         log.info("Stopped");
+        rpcRegistry.unregisterRpcService(rpcTapiConnectivity);
+        dynConfigService.removeListener(dynamicConfigServiceListener);
     }
 
+
+
+
+    /**
+     * Representation of internal listener, listening for dynamic config event.
+     */
+    private class InternalDynamicConfigListener implements DynamicConfigListener {
+
+        /**
+         * Check if the DCS event should be further processed.
+         *
+         * @param event config event
+         * @return true if event is supported; false otherwise
+         */
+        @Override
+        public boolean isRelevant(DynamicConfigEvent event) {
+            // Only care about add and delete
+            if ((event.type() != NODE_ADDED) &&
+                (event.type() != NODE_DELETED)) {
+                return false;
+            }
+            return true;
+        }
+
+
+
+
+        /**
+         * Process an Event from the Dynamic Configuration Store.
+         *
+         * @param event config event
+         */
+        @Override
+        public void event(DynamicConfigEvent event) {
+            ResourceId rsId = event.subject();
+            DataNode node;
+            try {
+                Filter filter = Filter.builder().addCriteria(rsId).build();
+                node = dynConfigService.readNode(rsId, filter);
+            } catch (FailedException e) {
+                node = null;
+            }
+            switch (event.type()) {
+                case NODE_ADDED:
+                    onDcsNodeAdded(rsId, node);
+                    break;
+
+                case NODE_DELETED:
+                    onDcsNodeDeleted(node);
+                    break;
+
+                default:
+                    log.warn("Unknown Event", event.type());
+                    break;
+            }
+        }
+
+
+
+        /**
+         * Process the event that a node has been added to the DCS.
+         *
+         * @param rsId ResourceId of the added node
+         * @param node added node. Access the key and value
+         */
+        private void onDcsNodeAdded(ResourceId rsId, DataNode node) {
+            switch (node.type()) {
+                case SINGLE_INSTANCE_NODE:
+                    break;
+                case MULTI_INSTANCE_NODE:
+                    break;
+                case SINGLE_INSTANCE_LEAF_VALUE_NODE:
+                    break;
+                case MULTI_INSTANCE_LEAF_VALUE_NODE:
+                    break;
+                default:
+                    break;
+            }
+
+            NodeKey dataNodeKey = node.key();
+            SchemaId schemaId = dataNodeKey.schemaId();
+            if (!schemaId.namespace().contains("tapi")) {
+                return;
+            }
+
+            // Consolidate events
+            log.info("namespace {}", schemaId.namespace());
+        }
+
+
+        /**
+         * Process the event that a node has been deleted from the DCS.
+         *
+         * @param dataNode data node
+         */
+        private void onDcsNodeDeleted(DataNode dataNode) {
+            // TODO: Implement release logic
+        }
+
+    }
+
+
+
+
+
+    private class TapiConnectivityRpc implements TapiConnectivityService {
+
+
+        /**
+         * Service interface of createConnectivityService.
+         *
+         * @param inputVar input of service interface createConnectivityService
+         * @return rpcOutput output of service interface createConnectivityService
+         */
+        public RpcOutput createConnectivityService(RpcInput inputVar) {
+            DataNode data = inputVar.data();
+            ResourceId rid = inputVar.id();
+
+            log.info("RpcInput Data {}", data);
+            log.info("RpcInput ResourceId {}", rid);
+
+            for (ModelObject mo : getModelObjects(data, rid)) {
+                if (mo instanceof CreateConnectivityServiceInput) {
+                    CreateConnectivityServiceInput i = (CreateConnectivityServiceInput) mo;
+                    log.info("i {}", i);
+                    List<EndPoint> epl = i.endPoint();
+                    for (EndPoint ep : epl) {
+                        log.info("ep {}", ep);
+                    }
+                }
+            }
+
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+        }
+
+
+
+        /**
+         * Service interface of deleteConnectivityService.
+         *
+         * @param inputVar input of service interface deleteConnectivityService
+         * @return rpcOutput output of service interface deleteConnectivityService
+         */
+        public RpcOutput deleteConnectivityService(RpcInput inputVar) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+        }
+
+
+
+        /**
+         * Service interface of getConnectionDetails.
+         *
+         * @param inputVar input of service interface getConnectionDetails
+         * @return rpcOutput output of service interface getConnectionDetails
+         */
+        public RpcOutput getConnectionDetails(RpcInput inputVar) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+
+        }
+
+        /**
+         * Service interface of getConnectivityServiceList.
+         *
+         * @param inputVar input of service interface getConnectivityServiceList
+         * @return rpcOutput output of service interface getConnectivityServiceList
+         */
+        public RpcOutput getConnectivityServiceList(RpcInput inputVar) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+
+        }
+
+        /**
+         * Service interface of getConnectivityServiceDetails.
+         *
+         * @param inputVar input of service interface getConnectivityServiceDetails
+         * @return rpcOutput output of service interface getConnectivityServiceDetails
+         */
+        public RpcOutput getConnectivityServiceDetails(RpcInput inputVar) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+
+        }
+
+
+        /**
+         * Service interface of updateConnectivityService.
+         *
+         * @param inputVar input of service interface updateConnectivityService
+         * @return rpcOutput output of service interface updateConnectivityService
+         */
+        public RpcOutput updateConnectivityService(RpcInput inputVar) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+
+        }
+
+
+        private ResourceData createResourceData(DataNode dataNode, ResourceId resId) {
+            return DefaultResourceData.builder()
+                .addDataNode(dataNode)
+                .resourceId(resId)
+                .build();
+        }
+
+        /**
+         * Returns model objects of the store.
+         *
+         * @param dataNode data node from store
+         * @param resId    parent resource id
+         * @return model objects
+         */
+        private List<ModelObject> getModelObjects(DataNode dataNode, ResourceId resId) {
+            ResourceData data = createResourceData(dataNode, resId);
+            ModelObjectData modelData = modelConverter.createModel(data);
+            return modelData.modelObjects();
+        }
+
+
+
+    }
 }
diff --git a/apps/odtn/src/test/resources/create-connectivity.json b/apps/odtn/src/test/resources/create-connectivity.json
new file mode 100644
index 0000000..ce3cf20
--- /dev/null
+++ b/apps/odtn/src/test/resources/create-connectivity.json
@@ -0,0 +1,52 @@
+{
+    "tapi-connectivity:input":
+    {
+        "end-point" : [
+            {
+                "layer-protocol-name" : "OTSiA",
+                "service-interface-point": "00000000-0000-4200-0001-110000000000",
+                "capacity" : {
+                },
+                "direction" : "BIDIRECTIONAL",
+                "role" : "UNKNOWN",
+                "protection-role" : "WORK",
+                "local-id": "00000000-0000-4100-0001-110000000000",
+                "name" : [
+                        {
+                            "value-name" : "main",
+                            "value" : "sep11"
+                        }
+                ],
+                "administrative-state" : "UNLOCKED",
+                "operational-state" : "ENABLED",
+                "lifecycle-state" : "INSTALLED"
+            }
+            ,
+            {
+                "layer-protocol-name" : "OTSiA",
+                "service-interface-point": "00000000-0000-4200-0001-210000000000",
+                "capacity" : {
+                },
+                "direction" : "BIDIRECTIONAL",
+                "role" : "UNKNOWN",
+                "protection-role" : "WORK",
+                "local-id": "00000000-0000-4100-0001-210000000000",
+                "name" : [
+                        {
+                            "value-name" : "main",
+                            "value" : "sep21"
+                        }
+                ],
+                "administrative-state" : "UNLOCKED",
+                "operational-state" : "ENABLED",
+                "lifecycle-state" : "INSTALLED"
+            }
+        ],
+
+        "conn-constraint" : {},
+        "topo-constraint" : {},
+        "resilience-constraint" : [ ],
+        "state" : "operational-state"
+    }
+}
+
diff --git a/apps/odtn/src/test/resources/nbi-tapi-sample.json b/apps/odtn/src/test/resources/nbi-tapi-sample.json
new file mode 100644
index 0000000..e0bd960
--- /dev/null
+++ b/apps/odtn/src/test/resources/nbi-tapi-sample.json
@@ -0,0 +1,51 @@
+{
+  "tapi-common:context": {
+    "service-interface-point": [
+      {
+        "uuid": "9F759964-2410-44AF-8522-4FCE2C3ED464",
+        "layer-protocol-name": ["DSR"],
+        "name": [
+          {
+            "value-name": "port",
+            "value": "1"
+          },
+          {
+            "value-name": "transponder",
+            "value": "TRPN_A"
+          }
+        ]
+      },
+      {
+        "uuid": "FBDDC006-8913-4509-BA71-485CFAC89567",
+        "layer-protocol-name": ["DSR"],
+        "name": [
+          {
+            "value-name": "port",
+            "value": "1"
+          },
+          {
+            "value-name": "transponder",
+            "value": "TRPN_B"
+          }
+        ]
+      }
+    ],
+    "tapi-connectivity:connectivity-service": [
+      {
+        "uuid" : "D0BF25C8-B20C-49C3-9030-1C5AEC993E44",
+        "end-point": [
+          {
+            "local-id" : "TRPN_A-1",
+            "layer-protocol-name": "DSR",
+            "service-interface-point": "9F759964-2410-44AF-8522-4FCE2C3ED464"
+          },
+          {
+            "local-id" : "TRPN_B-1",
+            "layer-protocol-name": "DSR",
+            "service-interface-point": "FBDDC006-8913-4509-BA71-485CFAC89567"
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/apps/odtn/src/test/resources/post-nbi-tapi-rpc b/apps/odtn/src/test/resources/post-nbi-tapi-rpc
new file mode 100644
index 0000000..45bdb17
--- /dev/null
+++ b/apps/odtn/src/test/resources/post-nbi-tapi-rpc
@@ -0,0 +1 @@
+curl -X POST http://localhost:8181/onos/restconf/operations/tapi-connectivity:create-connectivity-service -H 'cache-control: no-cache' -H 'content-type: application/json' -d @create-connectivity.json
diff --git a/apps/odtn/src/test/resources/post-nbi-tapi-sample b/apps/odtn/src/test/resources/post-nbi-tapi-sample
new file mode 100644
index 0000000..ffdd3d9
--- /dev/null
+++ b/apps/odtn/src/test/resources/post-nbi-tapi-sample
@@ -0,0 +1,2 @@
+curl -X POST http://localhost:8181/onos/restconf/data -H 'cache-control: no-cache' -H 'content-type: application/json' -d @nbi-tapi-sample.json
+
diff --git a/models/tapi/src/main/yang/tapi-connectivity@2018-02-16.yang b/models/tapi/src/main/yang/tapi-connectivity@2018-02-16.yang
index 45f89de..f5bc637 100644
--- a/models/tapi/src/main/yang/tapi-connectivity@2018-02-16.yang
+++ b/models/tapi/src/main/yang/tapi-connectivity@2018-02-16.yang
@@ -676,6 +676,7 @@
             description "none";

             input {

                 list end-point {

+                    key 'local-id';
                     min-elements 2;

                     uses connectivity-service-end-point;

                     description "none";