Add Tapi Context/Topology/Node/Link builders and utility class

ONOS-7679

Change-Id: I85f856b11a5e272460b38c16ca46212fb4a0a082
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNepRef.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNepRef.java
new file mode 100644
index 0000000..aa8e553
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNepRef.java
@@ -0,0 +1,27 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+
+public class DcsBasedTapiNepRef extends TapiNepRef {
+
+    public DcsBasedTapiNepRef(Uuid topologyId, Uuid nodeId, Uuid nepId) {
+        super(topologyId.toString(), nodeId.toString(), nepId.toString());
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNodeRef.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNodeRef.java
new file mode 100644
index 0000000..5e3c79b
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNodeRef.java
@@ -0,0 +1,26 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+
+public class DcsBasedTapiNodeRef extends TapiNodeRef {
+
+    public DcsBasedTapiNodeRef(Uuid topologyId, Uuid nodeId) {
+        super(topologyId.toString(), nodeId.toString());
+    }
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiContextBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiContextBuilder.java
new file mode 100644
index 0000000..2d24dc4
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiContextBuilder.java
@@ -0,0 +1,55 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI context creation with DCS.
+ */
+public final class TapiContextBuilder extends TapiInstanceBuilder {
+
+    private DefaultContext context;
+
+    private TapiContextBuilder(DefaultContext context) {
+        this.context = context;
+    }
+
+    public static TapiContextBuilder builder(DefaultContext context) {
+        return new TapiContextBuilder(context);
+    }
+
+    @Override
+    public ModelObjectData build() {
+        ModelObjectId objId = ModelObjectId.builder().build();
+        return getModelObjectData(context, objId);
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return context;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return null;
+    }
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiGlobalClassUtil.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiGlobalClassUtil.java
new file mode 100644
index 0000000..834c927
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiGlobalClassUtil.java
@@ -0,0 +1,111 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.globalclass.DefaultName;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.globalclass.Name;
+import org.onosproject.yang.model.ModelObject;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Utility methods dealing with TAPI modelObject which includes global class grouping.
+ *
+ * <p> tapi-common@2018-03-07.yang
+ * grouping global-class {
+ *   leaf uuid {
+ *     type uuid;
+ *   }
+ *   list name {
+ *     key 'value-name';
+ *     uses name-and-value;
+ *   }
+ * }
+ *
+ * grouping name-and-value {
+ *   leaf value-name {
+ *     type string;
+ *     description "The name of the value. The value need not have a name.";
+ *   }
+ *   leaf value {
+ *     type string;
+ *     description "The value";
+ *   }
+ *   description "A scoped name-value pair";
+ * }
+ * </p>
+ */
+public final class TapiGlobalClassUtil {
+
+    private static final Logger log = getLogger(TapiGlobalClassUtil.class);
+
+    private TapiGlobalClassUtil() {
+    }
+
+    /**
+     * Generate and set Uuid for the ModelObject.
+     * @param obj ModelObject
+     * @param <T> type of ModelObject
+     * @return generated uuid
+     */
+    public static <T extends ModelObject> Uuid setUuid(T obj) {
+        Uuid uuid = Uuid.of(UUID.randomUUID().toString());
+
+        @SuppressWarnings("unchecked")
+        Class<T> cls = (Class<T>) obj.getClass();
+        try {
+            Method method = cls.getMethod("uuid", Uuid.class);
+            method.invoke(obj, uuid);
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            log.error("Exception thrown", e);
+        }
+
+        return uuid;
+    }
+
+    /**
+     * Add key-value to the ModelObject as "name-and-value" list.
+     * @param obj ModelObject
+     * @param kvs key-value map
+     * @param <T> type of ModelObject
+     */
+    public static <T extends ModelObject> void setNameList(T obj, Map<String, String> kvs) {
+
+        @SuppressWarnings("unchecked")
+        Class<T> cls = (Class<T>) obj.getClass();
+        try {
+            Method method = cls.getMethod("addToName", Name.class);
+
+            for (Entry<String, String> kv : kvs.entrySet()) {
+                DefaultName prop = new DefaultName();
+                prop.valueName(kv.getKey());
+                prop.value(kv.getValue());
+                method.invoke(obj, prop);
+            }
+        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+            log.error("Exception thrown", e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiInstanceBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiInstanceBuilder.java
new file mode 100644
index 0000000..ecb07f1
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiInstanceBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.model.DefaultModelObjectData;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI modelobject creation with DCS.
+ */
+public abstract class TapiInstanceBuilder {
+
+    public static final String ONOS_CP = "onos-cp";
+
+    public static final String DEVICE_ID = "device_id";
+
+    /**
+     * Generate DCS modelObjectData.
+     * @return ModelObjectData to be built
+     */
+    public abstract ModelObjectData build();
+
+    /**
+     * Get modelObject instance.
+     * @return ModelObject of build target
+     */
+    public abstract ModelObject getModelObject();
+
+    /**
+     * Get modelObject uuid.
+     * @return Uuid of build target
+     */
+    public abstract Uuid getUuid();
+
+
+    ModelObjectData getModelObjectData(ModelObject obj, ModelObjectId objId) {
+        return DefaultModelObjectData.builder()
+                .addModelObject(obj)
+                .identifier(objId)
+                .build();
+    }
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiLinkBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiLinkBuilder.java
new file mode 100644
index 0000000..93fbe5b
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiLinkBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * 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 org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.link.DefaultNodeEdgePoint;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.DefaultLink;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.DefaultTopology;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.TopologyKeys;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
+
+/**
+ * Utility builder class for TAPI link creation with DCS.
+ */
+public final class TapiLinkBuilder extends TapiInstanceBuilder {
+
+    private Uuid topologyUuid;
+    private DefaultLink link = new DefaultLink();
+
+    private TapiLinkBuilder() {
+        setUuid(link);
+    }
+
+    public static TapiLinkBuilder builder() {
+        return new TapiLinkBuilder();
+    }
+
+    public TapiLinkBuilder setTopologyUuid(Uuid topologyUuid) {
+        this.topologyUuid = topologyUuid;
+        return this;
+    }
+
+    public TapiLinkBuilder setNep(TapiNepRef nepRef) {
+        DefaultNodeEdgePoint nep = new DefaultNodeEdgePoint();
+        nep.topologyId(nepRef.getTopologyId());
+        nep.nodeId(nepRef.getNodeId());
+        nep.ownedNodeEdgePointId(nepRef.getNepId());
+        link.addToNodeEdgePoint(nep);
+        return this;
+    }
+
+    @Override
+    public ModelObjectData build() {
+
+        TopologyKeys topologyKey = new TopologyKeys();
+        topologyKey.uuid(topologyUuid);
+        ModelObjectId objId = ModelObjectId.builder()
+                .addChild(DefaultContext.class)
+                .addChild(DefaultTopology.class, topologyKey)
+                .build();
+        return getModelObjectData(link, objId);
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return link;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return link.uuid();
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepBuilder.java
new file mode 100644
index 0000000..3524d63
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepBuilder.java
@@ -0,0 +1,118 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setNameList;
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
+
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.node.DefaultOwnedNodeEdgePoint;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.nodeedgepoint.DefaultMappedServiceInterfacePoint;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.DefaultNode;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.NodeKeys;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.DefaultTopology;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.TopologyKeys;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI nep creation with DCS.
+ */
+public final class TapiNepBuilder extends TapiInstanceBuilder {
+
+    private Uuid topologyUuid;
+    private Uuid nodeUuid;
+    private DefaultOwnedNodeEdgePoint nep = new DefaultOwnedNodeEdgePoint();
+    private ConnectPoint cp;
+    private Map<String, String> kvs = new HashMap<>();
+
+    private TapiNepBuilder() {
+        setUuid(nep);
+    }
+
+    public static TapiNepBuilder builder() {
+        return new TapiNepBuilder();
+    }
+
+    public TapiNepBuilder setTopologyUuid(Uuid topologyUuid) {
+        this.topologyUuid = topologyUuid;
+        return this;
+    }
+
+    public TapiNepBuilder setNodeUuid(Uuid nodeUuid) {
+        this.nodeUuid = nodeUuid;
+        return this;
+    }
+
+    public TapiNepBuilder setPort(Port port) {
+        cp = new ConnectPoint(port.element().id(), port.number());
+        kvs.put(ONOS_CP, cp.toString());
+        return this;
+    }
+
+    public TapiNepBuilder setConnectPoint(ConnectPoint cp) {
+        kvs.put(ONOS_CP, cp.toString());
+        return this;
+    }
+
+    public TapiNepBuilder setSip(Uuid sipUuid) {
+        DefaultMappedServiceInterfacePoint mappedSip = new DefaultMappedServiceInterfacePoint();
+        mappedSip.serviceInterfacePointId(sipUuid);
+        nep.addToMappedServiceInterfacePoint(mappedSip);
+        return this;
+    }
+
+    public ConnectPoint getConnectPoint() {
+        return cp;
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return nep;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return nep.uuid();
+    }
+
+    @Override
+    public ModelObjectData build() {
+        setNameList(nep, kvs);
+
+        TopologyKeys topologyKey = new TopologyKeys();
+        topologyKey.uuid(topologyUuid);
+
+        NodeKeys nodeKey = new NodeKeys();
+        nodeKey.uuid(nodeUuid);
+
+        ModelObjectId objId = ModelObjectId.builder()
+                .addChild(DefaultContext.class)
+                .addChild(DefaultTopology.class, topologyKey)
+                .addChild(DefaultNode.class, nodeKey)
+                .build();
+        return getModelObjectData(nep, objId);
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepRef.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepRef.java
new file mode 100644
index 0000000..a28d53d
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNepRef.java
@@ -0,0 +1,99 @@
+/*
+ * 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.UUID;
+import org.onosproject.net.ConnectPoint;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Objects.equal;
+import static java.util.Objects.hash;
+
+public class TapiNepRef {
+
+    private final UUID topologyId;
+    private final UUID nodeId;
+    private final UUID nepId;
+    private UUID sipId;
+    private ConnectPoint cp;
+
+    public String getTopologyId() {
+        return topologyId.toString();
+    }
+
+    public String getNodeId() {
+        return nodeId.toString();
+    }
+
+    public String getNepId() {
+        return nepId.toString();
+    }
+
+    public String getSipId() {
+        return sipId.toString();
+    }
+
+    public ConnectPoint getConnectPoint() {
+        return cp;
+    }
+
+    public TapiNepRef setSipId(String sipId) {
+        this.sipId = UUID.fromString(sipId);
+        return this;
+    }
+
+    public TapiNepRef setConnectPoint(ConnectPoint cp) {
+        this.cp = cp;
+        return this;
+    }
+
+    public TapiNepRef(String topologyId, String nodeId, String nepId) {
+        this.topologyId = UUID.fromString(topologyId);
+        this.nodeId = UUID.fromString(nodeId);
+        this.nepId = UUID.fromString(nepId);
+    }
+
+    public String toString() {
+        return toStringHelper(getClass())
+//                .add("topologyId", topologyId)
+                .add("nodeId", nodeId)
+                .add("nepId", nepId)
+                .add("sipId", sipId)
+                .add("connectPoint", cp)
+                .toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof TapiNepRef)) {
+            return false;
+        }
+        TapiNepRef that = (TapiNepRef) o;
+        return equal(topologyId, that.topologyId) &&
+                equal(nodeId, that.nodeId) &&
+                equal(nepId, that.nepId);
+    }
+
+    @Override
+    public int hashCode() {
+        return hash(topologyId, nodeId, nepId);
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeBuilder.java
new file mode 100644
index 0000000..868df72
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeBuilder.java
@@ -0,0 +1,90 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setNameList;
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.node.OwnedNodeEdgePoint;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.DefaultNode;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.DefaultTopology;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.TopologyKeys;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI node creation with DCS.
+ */
+public final class TapiNodeBuilder extends TapiInstanceBuilder {
+
+    private Uuid topologyUuid;
+    private DefaultNode node = new DefaultNode();
+    private Map<String, String> kvs = new HashMap<>();
+
+    private TapiNodeBuilder() {
+        setUuid(node);
+    }
+
+    public static TapiNodeBuilder builder() {
+        return new TapiNodeBuilder();
+    }
+
+    public TapiNodeBuilder setTopologyUuid(Uuid topologyUuid) {
+        this.topologyUuid = topologyUuid;
+        return this;
+    }
+
+    public TapiNodeBuilder setNep(OwnedNodeEdgePoint nep) {
+        node.addToOwnedNodeEdgePoint(nep);
+        return this;
+    }
+
+    public TapiNodeBuilder setDeviceId(DeviceId deviceId) {
+        kvs.put(DEVICE_ID, deviceId.toString());
+        return this;
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return node;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return node.uuid();
+    }
+
+    @Override
+    public ModelObjectData build() {
+        setNameList(node, kvs);
+
+        TopologyKeys topologyKey = new TopologyKeys();
+        topologyKey.uuid(topologyUuid);
+        ModelObjectId objId = ModelObjectId.builder()
+                .addChild(DefaultContext.class)
+                .addChild(DefaultTopology.class, topologyKey)
+                .build();
+        return getModelObjectData(node, objId);
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeRef.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeRef.java
new file mode 100644
index 0000000..0fd762b
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiNodeRef.java
@@ -0,0 +1,75 @@
+/*
+ * 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.UUID;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Objects.equal;
+import static java.util.Objects.hash;
+
+public class TapiNodeRef {
+
+    private final UUID topologyId;
+    private final UUID nodeId;
+    private DeviceId deviceId;
+
+    public String getNodeId() {
+        return nodeId.toString();
+    }
+
+    public DeviceId getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(DeviceId deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    public TapiNodeRef(String topologyId, String nodeId) {
+        this.topologyId = UUID.fromString(topologyId);
+        this.nodeId = UUID.fromString(nodeId);
+    }
+
+    public String toString() {
+        return toStringHelper(getClass())
+//                .add("topologyId", topologyId)
+                .add("nodeId", nodeId)
+                .add("deviceId", deviceId)
+                .toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof TapiNodeRef)) {
+            return false;
+        }
+        TapiNodeRef nodeRef = (TapiNodeRef) o;
+        return equal(topologyId, nodeRef.topologyId) &&
+                equal(nodeId, nodeRef.nodeId);
+    }
+
+    @Override
+    public int hashCode() {
+        return hash(topologyId, nodeId);
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiResolver.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiResolver.java
new file mode 100644
index 0000000..6ec62ff
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiResolver.java
@@ -0,0 +1,136 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.ElementId;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+/**
+ * TAPI instance resolver.
+ * FIXME: This resolver should provide DCS read cache
+ */
+public class TapiResolver {
+
+    private final Logger log = getLogger(getClass());
+
+    private List<TapiNodeRef> tapiNodeRefList = new ArrayList<>();
+    private List<TapiNepRef> tapiNepRefList = new ArrayList<>();
+
+
+    /**
+     * Check existence of TAPI node associated with deviceId.
+     * @param deviceId search key
+     * @return boolean
+     */
+    public boolean hasNodeRef(ElementId deviceId) {
+        return tapiNodeRefList.stream()
+                .anyMatch(node -> node.getDeviceId().equals(deviceId));
+    }
+
+    /**
+     * Check existence of TAPI nep associated with ConnectPoint.
+     * @param cp search key
+     * @return TapiNepRef
+     */
+    public boolean hasNepRef(ConnectPoint cp) {
+        return tapiNepRefList.stream()
+                .anyMatch(nep -> nep.getConnectPoint().equals(cp));
+    }
+
+    /**
+     * Check existence of TAPI nep associated with TAPI sipId.
+     * @param sipId search key
+     * @return TapiNepRef
+     */
+    public boolean hasNepRef(String sipId) {
+        return tapiNepRefList.stream()
+                .anyMatch(nep -> nep.getSipId().equals(sipId));
+    }
+
+    /**
+     * Resolve TAPI node associated with deviceId.
+     * @param deviceId search key
+     * @return TapiNodeRef
+     */
+    public TapiNodeRef getNodeRef(ElementId deviceId) {
+        TapiNodeRef ret = null;
+        try {
+            ret = tapiNodeRefList.stream()
+                    .filter(node -> node.getDeviceId().equals(deviceId))
+                    .findFirst().get();
+        } catch (NoSuchElementException e) {
+            log.error("Node not found associated with {}", deviceId);
+            throw e;
+        }
+        return ret;
+    }
+
+    /**
+     * Resolve TAPI nep associated with ConnectPoint.
+     * @param cp search key
+     * @return TapiNepRef
+     */
+    public TapiNepRef getNepRef(ConnectPoint cp) {
+        TapiNepRef ret = null;
+        try {
+            ret = tapiNepRefList.stream()
+                    .filter(nep -> nep.getConnectPoint().equals(cp))
+                    .findFirst().get();
+        } catch (NoSuchElementException e) {
+            log.error("Nep not found associated with {}", cp);
+            throw e;
+        }
+        return ret;
+    }
+
+    /**
+     * Resolve TAPI nep associated with TAPI sipId.
+     * @param sipId search key
+     * @return TapiNepRef
+     */
+    public TapiNepRef getNepRef(String sipId) {
+        TapiNepRef ret = null;
+        try {
+            ret = tapiNepRefList.stream()
+                    .filter(nep -> nep.getSipId().equals(sipId))
+                    .findFirst().get();
+        } catch (NoSuchElementException e) {
+            log.error("Nep not found associated with {}", sipId);
+            throw e;
+        }
+        return ret;
+    }
+
+    public TapiResolver addNodeRef(TapiNodeRef nodeRef) {
+        tapiNodeRefList.add(nodeRef);
+        log.info("Nodes: {}", tapiNodeRefList);
+        return this;
+    }
+
+    public TapiResolver addNepRef(TapiNepRef nepRef) {
+        tapiNepRefList.add(nepRef);
+        log.info("Neps: {}", tapiNepRefList);
+        return this;
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiSipBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiSipBuilder.java
new file mode 100644
index 0000000..a12a425
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiSipBuilder.java
@@ -0,0 +1,91 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Port;
+
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.LayerProtocolName;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setNameList;
+import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
+import static org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.layerprotocolname.LayerProtocolNameEnum.DSR;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.tapicontext.DefaultServiceInterfacePoint;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI sip creation with DCS.
+ */
+public final class TapiSipBuilder extends TapiInstanceBuilder {
+
+    private DefaultServiceInterfacePoint sip = new DefaultServiceInterfacePoint();
+    private Map<String, String> kvs = new HashMap<>();
+
+    private TapiSipBuilder() {
+        setUuid(sip);
+    }
+
+    public static TapiSipBuilder builder() {
+        return new TapiSipBuilder();
+    }
+
+    /**
+     * Check this builder dealing with port for SIP or not.
+     * @param port onos port
+     * @return Is this builder for SIP or not
+     */
+    public static boolean isSip(Port port) {
+        // FIXME modify this method to appropriate way
+        ConnectPoint cp = new ConnectPoint(port.element().id(), port.number());
+        return cp.toString().contains("TRANSCEIVER");
+    }
+
+    public TapiSipBuilder setPort(Port port) {
+        if (!isSip(port)) {
+            throw new IllegalStateException("Not allowed to use this port as SIP.");
+        }
+        ConnectPoint cp = new ConnectPoint(port.element().id(), port.number());
+        kvs.put(ONOS_CP, cp.toString());
+        sip.addToLayerProtocolName(LayerProtocolName.of(DSR));
+        return this;
+    }
+
+    @Override
+    public ModelObjectData build() {
+        setNameList(sip, kvs);
+        ModelObjectId objId = ModelObjectId.builder()
+                .addChild(DefaultContext.class)
+                .build();
+        return getModelObjectData(sip, objId);
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return sip;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return sip.uuid();
+    }
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiTopologyBuilder.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiTopologyBuilder.java
new file mode 100644
index 0000000..82e83d7
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiTopologyBuilder.java
@@ -0,0 +1,66 @@
+/*
+ * 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 static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
+
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.context.DefaultAugmentedTapiCommonContext;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.DefaultTopology;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ModelObjectId;
+
+/**
+ * Utility builder class for TAPI topology creation with DCS.
+ */
+public final class TapiTopologyBuilder extends TapiInstanceBuilder {
+
+    private DefaultTopology topology;
+
+    private TapiTopologyBuilder(DefaultTopology topology) {
+        this.topology = topology;
+        setUuid(this.topology);
+    }
+
+    public static TapiTopologyBuilder builder(DefaultTopology topology) {
+        return new TapiTopologyBuilder(topology);
+    }
+
+
+    @Override
+    public ModelObjectData build() {
+
+        DefaultAugmentedTapiCommonContext topologyContext = new DefaultAugmentedTapiCommonContext();
+        topologyContext.addToTopology(topology);
+
+        ModelObjectId objId = ModelObjectId.builder().addChild(DefaultContext.class).build();
+        return getModelObjectData(topologyContext, objId);
+    }
+
+    @Override
+    public ModelObject getModelObject() {
+        return topology;
+    }
+
+    @Override
+    public Uuid getUuid() {
+        return topology.uuid();
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/package-info.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/package-info.java
new file mode 100644
index 0000000..8d71ec1
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Utilities to deal with onos-yang-tools TAPI objects.
+ */
+package org.onosproject.odtn.utils.tapi;
\ No newline at end of file
diff --git a/apps/odtn/api/src/test/java/org/onosproject/odtn/utils/tapi/TapiResolverTest.java b/apps/odtn/api/src/test/java/org/onosproject/odtn/utils/tapi/TapiResolverTest.java
new file mode 100644
index 0000000..0d420d8
--- /dev/null
+++ b/apps/odtn/api/src/test/java/org/onosproject/odtn/utils/tapi/TapiResolverTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.NoSuchElementException;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.*;
+
+public class TapiResolverTest {
+
+    private TapiResolver tapiResolver;
+
+    private TapiNodeRef nodeRef;
+    private TapiNepRef nepRef;
+    private DeviceId deviceId;
+    private ConnectPoint cp;
+    private String sipId;
+
+    private DeviceId dummyDeviceId;
+    private Integer dummyPort;
+    private ConnectPoint dummyCp;
+    private String dummySipId;
+
+
+    @Before
+    public void setUp() {
+        nodeRef = new TapiNodeRef(
+                "49e2ac46-3975-44b4-b84f-8fab28222a39",
+                "5638e8e6-ac17-40d9-86e4-7c1febab6f1a");
+        nepRef = new TapiNepRef(
+                "59e2ac46-3975-44b4-b84f-8fab28222a39",
+                "6638e8e6-ac17-40d9-86e4-7c1febab6f1a",
+                "cd673055-e2b2-4f67-88c8-adfae96385bc");
+        deviceId = DeviceId.deviceId("netconf:172.24.3.5:11011");
+        cp = new ConnectPoint(deviceId, PortNumber.portNumber("42"));
+        sipId = "01c39723-7c0d-4754-8d64-fd9ff412404c";
+        nodeRef.setDeviceId(deviceId);
+        nepRef.setConnectPoint(cp).setSipId(sipId);
+
+        dummyDeviceId = DeviceId.deviceId("dummy");
+        dummyPort = 4;
+        dummyCp = new ConnectPoint(dummyDeviceId, PortNumber.portNumber(dummyPort));
+        dummySipId = "00000000-0000-0000-0000-000000000000";
+
+        tapiResolver = new TapiResolver();
+    }
+
+    @Test
+    public void testGetNodeRef() {
+        assertThat(nodeRef, is(tapiResolver.addNodeRef(nodeRef).getNodeRef(deviceId)));
+    }
+
+    @Test
+    public void testGetNepRefWithConnectPoint() {
+        assertThat(nepRef, is(tapiResolver.addNepRef(nepRef).getNepRef(cp)));
+    }
+
+    @Test
+    public void testGetNepRefWithSipId() {
+        assertThat(nepRef, is(tapiResolver.addNepRef(nepRef).getNepRef(sipId)));
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNodeRefWhenEmpty() {
+        tapiResolver.getNodeRef(deviceId);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNepRefWithConnectPointWhenEmpty() {
+        tapiResolver.getNepRef(cp);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNepRefWithSipIdWhenEmpty() {
+        tapiResolver.getNepRef(cp);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNodeRefNotExist() {
+        tapiResolver.addNodeRef(nodeRef);
+        tapiResolver.getNodeRef(dummyDeviceId);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNepRefWithConnectPointNotExist() {
+        tapiResolver.addNepRef(nepRef);
+        tapiResolver.getNepRef(dummyCp);
+    }
+
+    @Test(expected = NoSuchElementException.class)
+    public void testGetNepRefWithSipIdNotExist() {
+        tapiResolver.addNepRef(nepRef);
+        tapiResolver.getNepRef(dummySipId);
+    }
+
+}
\ No newline at end of file
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
index b52afbf..60cc41a 100644
--- a/apps/odtn/service/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/impl/ServiceApplicationComponent.java
@@ -27,7 +27,6 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onosproject.net.Device;
 import org.onosproject.net.Link;
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.net.device.DeviceEvent;
@@ -40,15 +39,6 @@
 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.rev20180307.TapiConnectivityService;
 
 import org.onosproject.yang.gen.v1.tapiconnectivity.rev20180307.
@@ -62,7 +52,6 @@
 // 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;
@@ -70,7 +59,6 @@
 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;
@@ -87,8 +75,8 @@
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DynamicConfigService dynConfigService;
+//    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+//    protected DynamicConfigService dynConfigService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
@@ -115,8 +103,8 @@
     protected TapiTopologyManager tapiTopologyManager;
 
     // Listener for events from the DCS
-    private final DynamicConfigListener dynamicConfigServiceListener =
-            new InternalDynamicConfigListener();
+//    private final DynamicConfigListener dynamicConfigServiceListener =
+//            new InternalDynamicConfigListener();
 
     private DeviceListener deviceListener = new InternalDeviceListener();
     private final LinkListener linkListener = new InternalLinkListener();
@@ -129,7 +117,7 @@
     @Activate
     protected void activate() {
         log.info("Started");
-        dynConfigService.addListener(dynamicConfigServiceListener);
+//        dynConfigService.addListener(dynamicConfigServiceListener);
         deviceService.addListener(deviceListener);
         linkService.addListener(linkListener);
         rpcRegistry.registerRpcService(rpcTapiConnectivity);
@@ -140,9 +128,9 @@
     protected void deactivate() {
         log.info("Stopped");
         rpcRegistry.unregisterRpcService(rpcTapiConnectivity);
-        deviceService.removeListener(deviceListener);
         linkService.removeListener(linkListener);
-        dynConfigService.removeListener(dynamicConfigServiceListener);
+        deviceService.removeListener(deviceListener);
+//        dynConfigService.removeListener(dynamicConfigServiceListener);
     }
 
 
@@ -158,20 +146,19 @@
          */
         @Override
         public void event(DeviceEvent event) {
-            Device device = event.subject();
 
             switch (event.type()) {
                 case DEVICE_ADDED:
-                    tapiTopologyManager.addDevice(device);
+                    tapiTopologyManager.addDevice(event.subject());
                     break;
                 case DEVICE_REMOVED:
-                    tapiTopologyManager.removeDevice(device);
+                    tapiTopologyManager.removeDevice(event.subject());
                     break;
                 case PORT_ADDED:
-                    tapiTopologyManager.addPort(device);
+                    tapiTopologyManager.addPort(event.port());
                     break;
                 case PORT_REMOVED:
-                    tapiTopologyManager.removePort(device);
+                    tapiTopologyManager.removePort(event.port());
                     break;
                 default:
                     log.warn("Unknown Event", event.type());
@@ -209,100 +196,100 @@
         }
     }
 
-    /**
-     * 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
+//    /**
+//     * 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
-        }
-
-    }
+//        }
+//
+//
+//        /**
+//         * 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 {
@@ -316,6 +303,7 @@
          */
         @Override
         public RpcOutput createConnectivityService(RpcInput inputVar) {
+
             DataNode data = inputVar.data();
             ResourceId rid = inputVar.id();
 
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiTopologyManager.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiTopologyManager.java
index 272319c..6da8cbf 100644
--- a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiTopologyManager.java
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiTopologyManager.java
@@ -16,24 +16,52 @@
 
 package org.onosproject.odtn.internal;
 
+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.apache.felix.scr.annotations.Service;
+import org.onlab.util.XmlString;
 import org.onosproject.config.DynamicConfigService;
 import org.onosproject.config.FailedException;
 import org.onosproject.config.Filter;
 import org.onosproject.d.config.DeviceResourceIds;
-import org.onosproject.d.config.ResourceIds;
-import org.onosproject.net.Device;
-import org.onosproject.net.Link;
-import org.onosproject.yang.model.DataNode;
-import org.onosproject.yang.model.InnerNode;
-import org.slf4j.Logger;
 
 import static org.onosproject.d.config.DeviceResourceIds.DCS_NAMESPACE;
+
+import org.onosproject.d.config.ResourceIds;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.Port;
+
+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.odtn.utils.tapi.TapiLinkBuilder;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
+import org.onosproject.odtn.utils.tapi.TapiResolver;
+import org.onosproject.odtn.utils.tapi.TapiContextBuilder;
+import org.onosproject.odtn.utils.tapi.TapiNepBuilder;
+import org.onosproject.odtn.utils.tapi.TapiNodeBuilder;
+import org.onosproject.odtn.utils.tapi.TapiSipBuilder;
+import org.onosproject.odtn.utils.tapi.TapiTopologyBuilder;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.DefaultTopology;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerNode;
+import org.onosproject.yang.model.ModelConverter;
+import org.onosproject.yang.model.ModelObjectData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -48,9 +76,19 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DynamicConfigService dcs;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ModelConverter modelConverter;
+
+    private DefaultContext context = new DefaultContext();
+    private DefaultTopology topology = new DefaultTopology();
+
+    private TapiResolver tapiResolver = new TapiResolver();
+
     @Activate
     public void activate() {
         initDcsIfRootNotExist();
+        initDcsTapiContext();
+        initDcsTapiTopology();
         log.info("Started");
     }
 
@@ -62,6 +100,18 @@
     @Override
     public void addDevice(Device device) {
         log.info("Add device: {}", device);
+        DeviceId deviceId = device.id();
+        if (tapiResolver.hasNodeRef(deviceId)) {
+            return;
+        }
+        TapiNodeBuilder builder = TapiNodeBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setDeviceId(deviceId);
+        addModelObjectDataToDcs(builder.build());
+
+        TapiNodeRef nodeRef = new TapiNodeRef(topology.uuid().toString(), builder.getUuid().toString());
+        nodeRef.setDeviceId(deviceId);
+        tapiResolver.addNodeRef(nodeRef);
     }
 
     @Override
@@ -72,6 +122,22 @@
     @Override
     public void addLink(Link link) {
         log.info("Add link: {}", link);
+
+        // validation check
+
+        // src nep
+        addNep(link.src());
+        addNep(link.dst());
+
+        // link
+        TapiNepRef srcNepRef = tapiResolver.getNepRef(link.src());
+        TapiNepRef dstNepRef = tapiResolver.getNepRef(link.dst());
+
+        TapiLinkBuilder linkBuilder = TapiLinkBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setNep(srcNepRef)
+                .setNep(dstNepRef);
+        addModelObjectDataToDcs(linkBuilder.build());
     }
 
     @Override
@@ -80,13 +146,94 @@
     }
 
     @Override
-    public void addPort(Device device) {
-        log.info("Add port: {}", device);
+    public void addPort(Port port) {
+        log.info("Add port: {}", port);
+        if (tapiResolver.hasNepRef(new ConnectPoint(port.element().id(), port.number()))) {
+            return;
+        }
+
+        TapiNodeRef nodeRef = tapiResolver.getNodeRef(port.element().id());
+        String nodeId = nodeRef.getNodeId();
+
+        // nep
+        TapiNepBuilder nepBuilder = TapiNepBuilder.builder()
+                .setPort(port)
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(Uuid.fromString(nodeId));
+
+        TapiNepRef nepRef = new TapiNepRef(topology.uuid().toString(), nodeId, nepBuilder.getUuid().toString());
+        nepRef.setConnectPoint(nepBuilder.getConnectPoint());
+
+        // sip
+        if (TapiSipBuilder.isSip(port)) {
+            TapiSipBuilder sipBuilder = TapiSipBuilder.builder().setPort(port);
+            nepBuilder.setSip(sipBuilder.getUuid());
+            nepRef.setSipId(sipBuilder.getUuid().toString());
+
+            addModelObjectDataToDcs(sipBuilder.build());
+        }
+
+        addModelObjectDataToDcs(nepBuilder.build());
+        tapiResolver.addNepRef(nepRef);
     }
 
     @Override
-    public void removePort(Device device) {
-        log.info("Remove port: {}", device);
+    public void removePort(Port port) {
+        log.info("Remove port: {}", port);
+    }
+
+    private void addNep(ConnectPoint cp) {
+
+        log.info("device Id: {}", cp.deviceId());
+        TapiNodeRef nodeRef = tapiResolver.getNodeRef(cp.deviceId());
+        String nodeId = nodeRef.getNodeId();
+
+        TapiNepBuilder nepBuilder = TapiNepBuilder.builder()
+                .setConnectPoint(cp)
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(Uuid.fromString(nodeId));
+        TapiNepRef nepRef = new TapiNepRef(topology.uuid().toString(), nodeId, nepBuilder.getUuid().toString());
+        nepRef.setConnectPoint(cp);
+
+        addModelObjectDataToDcs(nepBuilder.build());
+        tapiResolver.addNepRef(nepRef);
+    }
+
+    private void initDcsTapiContext() {
+        TapiContextBuilder builder = TapiContextBuilder.builder(context);
+        addModelObjectDataToDcs(builder.build());
+    }
+
+    private void initDcsTapiTopology() {
+        TapiTopologyBuilder builder = TapiTopologyBuilder.builder(topology);
+        addModelObjectDataToDcs(builder.build());
+    }
+
+    // FIXME: move DCS-related methods to DCS
+
+    private void addModelObjectDataToDcs(ModelObjectData input) {
+
+        ResourceData rnode = modelConverter.createDataNode(input);
+
+        // for debug
+        CharSequence strNode = toCharSequence(toXmlCompositeStream(toCompositeData(rnode)));
+        log.info("XML:\n{}", XmlString.prettifyXml(strNode));
+
+        addResourceDataToDcs(rnode);
+    }
+
+    private void addResourceDataToDcs(ResourceData input) {
+        addResourceDataToDcs(input, input.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);
+        }
     }
 
     private void initDcsIfRootNotExist() {
@@ -116,4 +263,5 @@
             log.info("'root' was created without error, but still not there. WTF!");
         }
     }
+
 }
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiTopologyManager.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiTopologyManager.java
index d997b45..0f02c63 100644
--- a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiTopologyManager.java
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiTopologyManager.java
@@ -18,18 +18,46 @@
 
 import org.onosproject.net.Device;
 import org.onosproject.net.Link;
+import org.onosproject.net.Port;
 
+/**
+ * ODTN Tapi manager application interface.
+ */
 public interface TapiTopologyManager {
 
+    /**
+     * DEVICE_ADDED event handler.
+     * @param device device to be added
+     */
     void addDevice(Device device);
 
+    /**
+     * DEVICE_REMOVED event handler.
+     * @param device device to be removed
+     */
     void removeDevice(Device device);
 
+    /**
+     * LINK_ADDED event handler.
+     * @param link link to be added
+     */
     void addLink(Link link);
 
+    /**
+     * LINK_REMOVED event handler.
+     * @param link link to be removed
+     */
     void removeLink(Link link);
 
-    void addPort(Device device);
+    /**
+     * PORT_ADDED event handler.
+     * @param port port to be added
+     */
+    void addPort(Port port);
 
-    void removePort(Device device);
+    /**
+     * PORT_REMOVED event handler.
+     * @param port port to be removed
+     */
+    void removePort(Port port);
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/OpenConfigDeviceDiscovery.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/OpenConfigDeviceDiscovery.java
index 1c2e599..ba98641 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/OpenConfigDeviceDiscovery.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/OpenConfigDeviceDiscovery.java
@@ -174,6 +174,16 @@
 
         switch (type) {
         case "oc-platform-types:PORT":
+        case "oc-opt-types:OPTICAL_CHANNEL":
+            // TODO assign appropriate port type & annotations at some point
+            // for now we just need a Port with annotations
+            builder.type(Type.OCH);
+
+            // Just a heuristics to deal with simple transponder
+            // if the device declare odtn-connection-id, just use them
+            // if not assign same value to relevant ports types
+            props.putIfAbsent(CONNECTION_ID, "the-only-one");
+            break;
         case "oc-platform-types:TRANSCEIVER":
         //case "oc-opt-types:OPTICAL_CHANNEL":
             // TODO assign appropriate port type & annotations at some point