[ODTN] Add read/create/delete ConnectivityService RPC

- RPC: get service interface point
- RPC: get connectivity service list
- RPC: get connectivity service detail
- RPC: create connectivity service
- RPC: delete connectivity service

- Filter method of TAPI resolver for both Node / NEP
- Change condition for sip to odtn-port-type
- Use odtn-port-type in path-computation mock
- Create CEP at topology discovery

- Add sample path calculator
- Add connection-id based path selection

Change-Id: I2f08aacb3dd14b6b3c59a64a349e50abb495f70b
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java
new file mode 100644
index 0000000..05cbc57
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiObjectHandler.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * 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.
+ */
+
+package org.onosproject.odtn.utils.tapi;
+
+import java.util.List;
+import java.util.UUID;
+import org.apache.commons.lang.NotImplementedException;
+import org.onlab.util.XmlString;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.Filter;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.DefaultResourceData;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+import org.onosproject.yang.model.ResourceData;
+
+import static org.onlab.osgi.DefaultServiceDirectory.getService;
+import static org.onosproject.odtn.utils.YangToolUtil.toCharSequence;
+import static org.onosproject.odtn.utils.YangToolUtil.toCompositeData;
+import static org.onosproject.odtn.utils.YangToolUtil.toXmlCompositeStream;
+
+import org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Utility abstract class to deal with TAPI ModelObject with DCS.
+ *
+ * @param <T> modelObject to be dealt with
+ */
+public abstract class TapiObjectHandler<T extends ModelObject> {
+
+    public static final String ONOS_CP = "onos-cp";
+    public static final String DEVICE_ID = "device-id";
+    public static final String ODTN_PORT_TYPE = "odtn-port-type";
+
+    protected final Logger log = getLogger(getClass());
+
+    protected ModelConverter modelConverter;
+    protected DynamicConfigService dcs;
+
+    protected T obj;
+
+    /**
+     * Get modelObject uuid.
+     *
+     * @return Uuid
+     */
+    public Uuid getId() {
+        return getIdDetail();
+    }
+
+    /**
+     * Generate and set modelObject uuid.
+     */
+    public void setId() {
+        Uuid uuid = Uuid.of(UUID.randomUUID().toString());
+        setIdDetail(uuid);
+    }
+
+    /**
+     * Set modelObject uuid.
+     *
+     * @param uuid Uuid
+     */
+    public void setId(Uuid uuid) {
+        setIdDetail(uuid);
+    }
+
+    /**
+     * Get modelObject uuid, to be implemented in sub classes.
+     *
+     * @return Uuid
+     */
+    protected abstract Uuid getIdDetail();
+
+    /**
+     * Set modelObject uuid, to be implemented in sub classes.
+     *
+     * @param uuid Uuid
+     */
+    protected abstract void setIdDetail(Uuid uuid);
+
+    /**
+     * Generate DCS modelObjectId for parent node.
+     *
+     * @return ModelObjectId of parent node
+     */
+    public abstract ModelObjectId getParentModelObjectId();
+
+    /**
+     * Get modelObject instance.
+     *
+     * @return ModelObject of target node
+     */
+    public T getModelObject() {
+        return obj;
+    }
+
+    /**
+     * Set modelObject instance.
+     *
+     * @param newObj ModelObject to be set
+     */
+    public void setModelObject(T newObj) {
+        obj = newObj;
+    }
+
+    /**
+     * Get modelObjectData instance.
+     *
+     * @return ModelObjectData of target node
+     */
+    public ModelObjectData getModelObjectData() {
+        ModelObject obj = getModelObject();
+        ModelObjectId objId = getParentModelObjectId();
+
+        return DefaultModelObjectData.builder()
+                .addModelObject(obj)
+                .identifier(objId)
+                .build();
+    }
+
+    /**
+     * Get modelObjectData instance for child node.
+     * <p>
+     * This modelObjectData is needed for read / update / delete operation
+     * to extract ResourceId of this modelObject itself.
+     * It's just workaround, fix in DCS needed.
+     *
+     * @return ModelObjectData of build target
+     */
+    public ModelObjectData getChildModelObjectData() {
+        throw new NotImplementedException();
+    }
+
+    /**
+     * Get DataNode instance.
+     *
+     * @return DataNode of target node
+     */
+    public DataNode getDataNode() {
+        ResourceData rData = toResourceData(getModelObjectData());
+        if (rData.dataNodes().size() > 1) {
+            throw new RuntimeException("Multiple dataNode found.");
+        }
+        return rData.dataNodes().get(0);
+    }
+
+    /**
+     * Read modelObject from Dcs store.
+     *
+     * @return ModelObject
+     */
+    public T read() {
+        return readOnDcs();
+    }
+
+    /**
+     * Add modelObject to Dcs store.
+     */
+    public void add() {
+        createOnDcs();
+    }
+
+    /**
+     * Delete modelObject from Dcs store.
+     */
+    public void remove() {
+        deleteOnDcs();
+    }
+
+    private void dcsSetup() {
+        dcs = getService(DynamicConfigService.class);
+        modelConverter = getService(ModelConverter.class);
+    }
+
+    @SuppressWarnings("unchecked")
+    private T readOnDcs() {
+        dcsSetup();
+        ResourceData rData1 = toResourceData(getChildModelObjectData());
+        ResourceData rData2 = toResourceData(getModelObjectData());
+        DataNode rNode = dcs.readNode(rData1.resourceId(), Filter.builder().build());
+        obj = toModelObject(rNode, rData2.resourceId());
+        return obj;
+    }
+
+    private void createOnDcs() {
+        dcsSetup();
+        ResourceData rData = toResourceData(getModelObjectData());
+        addResourceDataToDcs(rData, rData.resourceId());
+    }
+
+    private void deleteOnDcs() {
+        dcsSetup();
+        ResourceData rData = toResourceData(getChildModelObjectData());
+        dcs.deleteNode(rData.resourceId());
+    }
+
+    private void addResourceDataToDcs(ResourceData input, ResourceId rid) {
+        if (input == null || input.dataNodes() == null) {
+            return;
+        }
+        List<DataNode> dataNodes = input.dataNodes();
+        for (DataNode node : dataNodes) {
+            dcs.createNode(rid, node);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected T toModelObject(DataNode rNode, ResourceId rId) {
+        dcsSetup();
+        ResourceData rData = toResourceData(rNode, rId);
+        ModelObjectData modelObjectData = modelConverter.createModel(rData);
+        if (modelObjectData.modelObjects().size() > 1) {
+            throw new RuntimeException("Multiple modelObject found.");
+        }
+        return (T) modelObjectData.modelObjects().get(0);
+    }
+
+    private ResourceData toResourceData(DataNode rNode, ResourceId rId) {
+        return DefaultResourceData.builder()
+                .addDataNode(rNode)
+                .resourceId(rId)
+                .build();
+    }
+
+    private ResourceData toResourceData(ModelObjectData data) {
+        dcsSetup();
+        ResourceData rData = modelConverter.createDataNode(data);
+
+        // for debug
+        CharSequence strNode = toCharSequence(toXmlCompositeStream(toCompositeData(rData)));
+        log.info("XML:\n{}", XmlString.prettifyXml(strNode));
+
+        return rData;
+    }
+
+}