Add TAPI object resolver and DCS-dependent data provider ( to update cache )

- refactor TapiInstanceBuilder and add some util method
- add skeleton code for tapi-common get RPCs

Change-Id: I548623ad29f9b72b425713720c5081d790b42bd2
diff --git a/apps/odtn/api/BUCK b/apps/odtn/api/BUCK
index c3cdf13..0c5811f 100644
--- a/apps/odtn/api/BUCK
+++ b/apps/odtn/api/BUCK
@@ -6,6 +6,7 @@
     '//models/tapi:onos-models-tapi',
     '//models/openconfig:onos-models-openconfig',
     '//apps/yang:onos-apps-yang',
+    '//apps/config:onos-apps-config',
 ]
 
 TEST_DEPS = [
diff --git a/apps/odtn/api/pom.xml b/apps/odtn/api/pom.xml
index 1d971fc..19b5101 100644
--- a/apps/odtn/api/pom.xml
+++ b/apps/odtn/api/pom.xml
@@ -76,6 +76,11 @@
             <scope>test</scope>
             <classifier>tests</classifier>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-apps-config</artifactId>
+            <version>${project.version}</version>
+        </dependency>
 
     </dependencies>
 
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
index aa8e553..12df8cb 100644
--- 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
@@ -16,12 +16,18 @@
 
 package org.onosproject.odtn.utils.tapi;
 
-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.Node;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.Topology;
 
-public class DcsBasedTapiNepRef extends TapiNepRef {
+public final class DcsBasedTapiNepRef extends TapiNepRef {
 
-    public DcsBasedTapiNepRef(Uuid topologyId, Uuid nodeId, Uuid nepId) {
-        super(topologyId.toString(), nodeId.toString(), nepId.toString());
+    private DcsBasedTapiNepRef(Topology topology, Node node, OwnedNodeEdgePoint nep) {
+        super(topology.uuid().toString(), node.uuid().toString(), nep.uuid().toString());
+    }
+
+    public static DcsBasedTapiNepRef create(Topology topology, Node node, OwnedNodeEdgePoint nep) {
+        return new DcsBasedTapiNepRef(topology, node, nep);
     }
 
 }
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
index 5e3c79b..cfc38e2 100644
--- 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
@@ -16,11 +16,16 @@
 
 package org.onosproject.odtn.utils.tapi;
 
-import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.Uuid;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.Node;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.Topology;
 
-public class DcsBasedTapiNodeRef extends TapiNodeRef {
+public final class DcsBasedTapiNodeRef extends TapiNodeRef {
 
-    public DcsBasedTapiNodeRef(Uuid topologyId, Uuid nodeId) {
-        super(topologyId.toString(), nodeId.toString());
+    private DcsBasedTapiNodeRef(Topology topology, Node node) {
+        super(topology.uuid().toString(), node.uuid().toString());
+    }
+
+    public static DcsBasedTapiNodeRef create(Topology topology, Node node) {
+        return new DcsBasedTapiNodeRef(topology, node);
     }
 }
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
index 2d24dc4..720d436 100644
--- 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
@@ -18,8 +18,6 @@
 
 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;
 
 /**
@@ -38,13 +36,13 @@
     }
 
     @Override
-    public ModelObjectData build() {
-        ModelObjectId objId = ModelObjectId.builder().build();
-        return getModelObjectData(context, objId);
+    public ModelObjectId getModelObjectId() {
+        return ModelObjectId.builder().build();
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultContext getModelObject() {
         return context;
     }
 
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
index 834c927..2af7fed 100644
--- 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
@@ -91,7 +91,7 @@
      * @param kvs key-value map
      * @param <T> type of ModelObject
      */
-    public static <T extends ModelObject> void setNameList(T obj, Map<String, String> kvs) {
+    public static <T extends ModelObject> void addNameList(T obj, Map<String, String> kvs) {
 
         @SuppressWarnings("unchecked")
         Class<T> cls = (Class<T>) obj.getClass();
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
index fa4a903..dc4fd10 100644
--- 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
@@ -16,11 +16,26 @@
 
 package org.onosproject.odtn.utils.tapi;
 
+import java.util.List;
+import org.onlab.util.XmlString;
+import org.onosproject.config.DynamicConfigService;
 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.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 builder class for TAPI modelobject creation with DCS.
@@ -33,29 +48,80 @@
 
     public static final String ODTN_PORT_TYPE = "odtn-port-type";
 
+    private final Logger log = getLogger(getClass());
+
+    private ModelConverter modelConverter;
+    private DynamicConfigService dcs;
+
     /**
      * Generate DCS modelObjectData.
-     * @return ModelObjectData to be built
+     *
+     * @return ModelObjectId of build target
      */
-    public abstract ModelObjectData build();
+    public abstract ModelObjectId getModelObjectId();
 
     /**
      * Get modelObject instance.
+     *
+     * @param <T> build target class
      * @return ModelObject of build target
      */
-    public abstract ModelObject getModelObject();
+    public abstract <T extends ModelObject> T getModelObject();
 
     /**
      * Get modelObject uuid.
+     *
      * @return Uuid of build target
      */
     public abstract Uuid getUuid();
 
+    /**
+     * Get modelObjectData instance.
+     *
+     * @return ModelObjectData of build target
+     */
+    public ModelObjectData getModelObjectData() {
+        ModelObject obj = getModelObject();
+        ModelObjectId objId = getModelObjectId();
 
-    ModelObjectData getModelObjectData(ModelObject obj, ModelObjectId objId) {
         return DefaultModelObjectData.builder()
                 .addModelObject(obj)
                 .identifier(objId)
                 .build();
     }
+
+    /**
+     * Add built modelObject to Dcs store.
+     */
+    public void build() {
+        dcs = getService(DynamicConfigService.class);
+        modelConverter = getService(ModelConverter.class);
+        addModelObjectDataToDcs(getModelObjectData());
+    }
+
+    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);
+        }
+    }
+
 }
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
index 93fbe5b..31107ae 100644
--- 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
@@ -22,8 +22,6 @@
 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;
@@ -49,7 +47,7 @@
         return this;
     }
 
-    public TapiLinkBuilder setNep(TapiNepRef nepRef) {
+    public TapiLinkBuilder addNep(TapiNepRef nepRef) {
         DefaultNodeEdgePoint nep = new DefaultNodeEdgePoint();
         nep.topologyId(nepRef.getTopologyId());
         nep.nodeId(nepRef.getNodeId());
@@ -59,19 +57,19 @@
     }
 
     @Override
-    public ModelObjectData build() {
+    public ModelObjectId getModelObjectId() {
 
         TopologyKeys topologyKey = new TopologyKeys();
         topologyKey.uuid(topologyUuid);
-        ModelObjectId objId = ModelObjectId.builder()
+        return ModelObjectId.builder()
                 .addChild(DefaultContext.class)
                 .addChild(DefaultTopology.class, topologyKey)
                 .build();
-        return getModelObjectData(link, objId);
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultLink getModelObject() {
         return link;
     }
 
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
index 3524d63..1148511 100644
--- 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
@@ -19,9 +19,8 @@
 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.addNameList;
 import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
 
 import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
@@ -32,8 +31,6 @@
 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;
 
 /**
@@ -65,18 +62,13 @@
         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());
+        addNameList(nep, kvs);
         return this;
     }
 
-    public TapiNepBuilder setSip(Uuid sipUuid) {
+    public TapiNepBuilder addSip(Uuid sipUuid) {
         DefaultMappedServiceInterfacePoint mappedSip = new DefaultMappedServiceInterfacePoint();
         mappedSip.serviceInterfacePointId(sipUuid);
         nep.addToMappedServiceInterfacePoint(mappedSip);
@@ -88,7 +80,8 @@
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultOwnedNodeEdgePoint getModelObject() {
         return nep;
     }
 
@@ -98,21 +91,18 @@
     }
 
     @Override
-    public ModelObjectData build() {
-        setNameList(nep, kvs);
-
+    public ModelObjectId getModelObjectId() {
         TopologyKeys topologyKey = new TopologyKeys();
         topologyKey.uuid(topologyUuid);
 
         NodeKeys nodeKey = new NodeKeys();
         nodeKey.uuid(nodeUuid);
 
-        ModelObjectId objId = ModelObjectId.builder()
+        return 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
index a28d53d..d837362 100644
--- 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
@@ -16,6 +16,7 @@
 
 package org.onosproject.odtn.utils.tapi;
 
+import java.util.Optional;
 import java.util.UUID;
 import org.onosproject.net.ConnectPoint;
 
@@ -28,8 +29,18 @@
     private final UUID topologyId;
     private final UUID nodeId;
     private final UUID nepId;
-    private UUID sipId;
-    private ConnectPoint cp;
+    private UUID sipId = null;
+    private ConnectPoint cp = null;
+
+    TapiNepRef(String topologyId, String nodeId, String nepId) {
+        this.topologyId = UUID.fromString(topologyId);
+        this.nodeId = UUID.fromString(nodeId);
+        this.nepId = UUID.fromString(nepId);
+    }
+
+    public static TapiNepRef create(String topologyId, String nodeId, String nepId) {
+        return new TapiNepRef(topologyId, nodeId, nepId);
+    }
 
     public String getTopologyId() {
         return topologyId.toString();
@@ -44,7 +55,9 @@
     }
 
     public String getSipId() {
-        return sipId.toString();
+        return Optional.ofNullable(sipId)
+                .map(UUID::toString)
+                .orElse(null);
     }
 
     public ConnectPoint getConnectPoint() {
@@ -61,12 +74,6 @@
         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)
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
index 868df72..21e812c 100644
--- 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
@@ -18,7 +18,7 @@
 
 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.addNameList;
 import static org.onosproject.odtn.utils.tapi.TapiGlobalClassUtil.setUuid;
 
 import org.onosproject.net.DeviceId;
@@ -28,8 +28,6 @@
 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;
 
 /**
@@ -39,7 +37,6 @@
 
     private Uuid topologyUuid;
     private DefaultNode node = new DefaultNode();
-    private Map<String, String> kvs = new HashMap<>();
 
     private TapiNodeBuilder() {
         setUuid(node);
@@ -54,18 +51,21 @@
         return this;
     }
 
-    public TapiNodeBuilder setNep(OwnedNodeEdgePoint nep) {
+    public TapiNodeBuilder addNep(OwnedNodeEdgePoint nep) {
         node.addToOwnedNodeEdgePoint(nep);
         return this;
     }
 
     public TapiNodeBuilder setDeviceId(DeviceId deviceId) {
+        Map<String, String> kvs = new HashMap<>();
         kvs.put(DEVICE_ID, deviceId.toString());
+        addNameList(node, kvs);
         return this;
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultNode getModelObject() {
         return node;
     }
 
@@ -75,16 +75,13 @@
     }
 
     @Override
-    public ModelObjectData build() {
-        setNameList(node, kvs);
-
+    public ModelObjectId getModelObjectId() {
         TopologyKeys topologyKey = new TopologyKeys();
         topologyKey.uuid(topologyUuid);
-        ModelObjectId objId = ModelObjectId.builder()
+        return 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
index 0fd762b..ae2a968 100644
--- 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
@@ -29,6 +29,15 @@
     private final UUID nodeId;
     private DeviceId deviceId;
 
+    TapiNodeRef(String topologyId, String nodeId) {
+        this.topologyId = UUID.fromString(topologyId);
+        this.nodeId = UUID.fromString(nodeId);
+    }
+
+    public static TapiNodeRef create(String topologyId, String nodeId) {
+        return new TapiNodeRef(topologyId, nodeId);
+    }
+
     public String getNodeId() {
         return nodeId.toString();
     }
@@ -37,13 +46,9 @@
         return deviceId;
     }
 
-    public void setDeviceId(DeviceId deviceId) {
+    public TapiNodeRef setDeviceId(DeviceId deviceId) {
         this.deviceId = deviceId;
-    }
-
-    public TapiNodeRef(String topologyId, String nodeId) {
-        this.topologyId = UUID.fromString(topologyId);
-        this.nodeId = UUID.fromString(nodeId);
+        return this;
     }
 
     public String toString() {
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
deleted file mode 100644
index 6ec62ff..0000000
--- a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiResolver.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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
index a12a425..5e24b33 100644
--- 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
@@ -19,18 +19,15 @@
 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.addNameList;
 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;
 
 /**
@@ -39,7 +36,6 @@
 public final class TapiSipBuilder extends TapiInstanceBuilder {
 
     private DefaultServiceInterfacePoint sip = new DefaultServiceInterfacePoint();
-    private Map<String, String> kvs = new HashMap<>();
 
     private TapiSipBuilder() {
         setUuid(sip);
@@ -51,36 +47,35 @@
 
     /**
      * Check this builder dealing with port for SIP or not.
-     * @param port onos port
+     * @param cp onos connectPoint
      * @return Is this builder for SIP or not
      */
-    public static boolean isSip(Port port) {
+    public static boolean isSip(ConnectPoint cp) {
         // 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)) {
+    public TapiSipBuilder setConnectPoint(ConnectPoint cp) {
+        if (!isSip(cp)) {
             throw new IllegalStateException("Not allowed to use this port as SIP.");
         }
-        ConnectPoint cp = new ConnectPoint(port.element().id(), port.number());
+        Map<String, String> kvs = new HashMap<>();
         kvs.put(ONOS_CP, cp.toString());
+        addNameList(sip, kvs);
         sip.addToLayerProtocolName(LayerProtocolName.of(DSR));
         return this;
     }
 
     @Override
-    public ModelObjectData build() {
-        setNameList(sip, kvs);
-        ModelObjectId objId = ModelObjectId.builder()
+    public ModelObjectId getModelObjectId() {
+        return ModelObjectId.builder()
                 .addChild(DefaultContext.class)
                 .build();
-        return getModelObjectData(sip, objId);
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultServiceInterfacePoint getModelObject() {
         return sip;
     }
 
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
index 82e83d7..4c96133 100644
--- 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
@@ -22,8 +22,6 @@
 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;
 
 /**
@@ -44,17 +42,17 @@
 
 
     @Override
-    public ModelObjectData build() {
+    public ModelObjectId getModelObjectId() {
 
         DefaultAugmentedTapiCommonContext topologyContext = new DefaultAugmentedTapiCommonContext();
         topologyContext.addToTopology(topology);
 
-        ModelObjectId objId = ModelObjectId.builder().addChild(DefaultContext.class).build();
-        return getModelObjectData(topologyContext, objId);
+        return ModelObjectId.builder().addChild(DefaultContext.class).build();
     }
 
     @Override
-    public ModelObject getModelObject() {
+    @SuppressWarnings("unchecked")
+    public DefaultTopology getModelObject() {
         return topology;
     }
 
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 60cc41a..2a92137 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,6 +27,11 @@
 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.DynamicConfigEvent;
+import org.onosproject.config.DynamicConfigListener;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.FailedException;
+import org.onosproject.config.Filter;
 import org.onosproject.net.Link;
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.net.device.DeviceEvent;
@@ -35,7 +40,14 @@
 import org.onosproject.net.link.LinkEvent;
 import org.onosproject.net.link.LinkListener;
 import org.onosproject.net.link.LinkService;
+import org.onosproject.odtn.internal.DcsBasedTapiDataProducer;
+import org.onosproject.odtn.internal.TapiDataProducer;
+import org.onosproject.odtn.internal.TapiResolver;
 import org.onosproject.odtn.internal.TapiTopologyManager;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.TapiCommonService;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.getserviceinterfacepointlist.DefaultGetServiceInterfacePointListOutput;
+import org.onosproject.yang.model.NodeKey;
+import org.onosproject.yang.model.SchemaId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -67,6 +79,10 @@
 import org.onosproject.yang.model.SchemaContextProvider;
 import org.onosproject.yang.runtime.YangRuntimeService;
 
+import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
+import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
+import static org.onosproject.odtn.utils.YangToolUtil.toDataNode;
+
 /**
  * OSGi Component for ODTN Service application.
  */
@@ -75,8 +91,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;
@@ -102,35 +118,44 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected TapiTopologyManager tapiTopologyManager;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TapiResolver resolver;
+
     // 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();
+    private TapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
 
     // Rpc Service for TAPI Connectivity
     private final RpcService rpcTapiConnectivity =
             new TapiConnectivityRpc();
 
+    private final RpcService rpcTapiCommon =
+            new TapiCommonRpc();
+
 
     @Activate
     protected void activate() {
         log.info("Started");
-//        dynConfigService.addListener(dynamicConfigServiceListener);
+        dynConfigService.addListener(dynamicConfigServiceListener);
         deviceService.addListener(deviceListener);
         linkService.addListener(linkListener);
         rpcRegistry.registerRpcService(rpcTapiConnectivity);
+        rpcRegistry.registerRpcService(rpcTapiCommon);
     }
 
 
     @Deactivate
     protected void deactivate() {
         log.info("Stopped");
+        rpcRegistry.unregisterRpcService(rpcTapiCommon);
         rpcRegistry.unregisterRpcService(rpcTapiConnectivity);
         linkService.removeListener(linkListener);
         deviceService.removeListener(deviceListener);
-//        dynConfigService.removeListener(dynamicConfigServiceListener);
+        dynConfigService.removeListener(dynamicConfigServiceListener);
     }
 
 
@@ -196,100 +221,103 @@
         }
     }
 
-//    /**
-//     * 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();
+    /**
+     * 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) {
+            resolver.makeDirty();
+
+            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();
+
+            // Consolidate events
 //            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 {
@@ -409,4 +437,51 @@
 
 
     }
+
+
+    private class TapiCommonRpc implements TapiCommonService {
+
+        /**
+         * Service interface of getServiceInterfacePointDetails.
+         *
+         * @param rpcInput input of service interface getServiceInterfacePointDetails
+         * @return rpcOutput output of service interface getServiceInterfacePointDetails
+         */
+        @Override
+        public RpcOutput getServiceInterfacePointDetails(RpcInput rpcInput) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+        }
+
+        /**
+         * Service interface of getServiceInterfacePointList.
+         *
+         * @param rpcInput input of service interface getServiceInterfacePointList
+         * @return rpcOutput output of service interface getServiceInterfacePointList
+         */
+        @Override
+        public RpcOutput getServiceInterfacePointList(RpcInput rpcInput) {
+
+            DataNode data = rpcInput.data();
+            ResourceId rid = rpcInput.id();
+
+            log.info("RpcInput Data {}", data);
+            log.info("RpcInput ResourceId {}", rid);
+
+            DefaultGetServiceInterfacePointListOutput node = new DefaultGetServiceInterfacePointListOutput();
+            DataNode dnode = toDataNode(node);
+
+            return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dnode);
+        }
+
+        /**
+         * Service interface of updateServiceInterfacePoint.
+q         *
+         * @param rpcInput input of service interface updateServiceInterfacePoint
+         * @return rpcOutput output of service interface updateServiceInterfacePoint
+         */
+        @Override
+        public RpcOutput updateServiceInterfacePoint(RpcInput rpcInput) {
+            return new RpcOutput(RpcOutput.Status.RPC_FAILURE, null);
+        }
+    }
 }
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducer.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducer.java
new file mode 100644
index 0000000..5f6b96c
--- /dev/null
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducer.java
@@ -0,0 +1,162 @@
+/*
+ * 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.internal;
+import com.google.common.annotations.VisibleForTesting;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.onosproject.config.DynamicConfigService;
+
+import org.onosproject.config.Filter;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.odtn.utils.tapi.DcsBasedTapiNepRef;
+import org.onosproject.odtn.utils.tapi.DcsBasedTapiNodeRef;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
+import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.globalclass.Name;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.context.DefaultAugmentedTapiCommonContext;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.Topology;
+import org.onosproject.yang.model.Augmentable;
+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 org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+
+import static org.onlab.osgi.DefaultServiceDirectory.getService;
+import static org.onosproject.odtn.utils.tapi.TapiInstanceBuilder.DEVICE_ID;
+import static org.onosproject.odtn.utils.tapi.TapiInstanceBuilder.ONOS_CP;
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class DcsBasedTapiDataProducer implements TapiDataProducer {
+
+    private final Logger log = getLogger(getClass());
+    protected DynamicConfigService dcs;
+    protected ModelConverter modelConverter;
+
+    @Override
+    public void init() {
+        dcs = getService(DynamicConfigService.class);
+        modelConverter = getService(ModelConverter.class);
+    }
+
+    @Override
+    public void updateCacheRequest(DefaultTapiResolver resolver) {
+        ModelObject context = readContextModelObject();
+        updateCache(resolver, context);
+    }
+
+    @VisibleForTesting
+    protected void updateCache(DefaultTapiResolver resolver, ModelObject context) {
+        updateNodes(resolver, getNodes(context));
+        updateNeps(resolver, getNeps(context));
+    }
+
+    private ModelObject readContextModelObject() {
+        // read DataNode from DCS
+        ModelObjectId mid = ModelObjectId.builder().addChild(DefaultContext.class).build();
+        DataNode node = dcs.readNode(getResourceId(mid), Filter.builder().build());
+
+        // convert to ModelObject
+        ResourceData data = DefaultResourceData.builder().addDataNode(node)
+                .resourceId(ResourceId.builder().build()).build();
+        ModelObjectData modelData = modelConverter.createModel(data);
+        ModelObject context = modelData.modelObjects().get(0);
+
+        return context;
+    }
+
+    private List<TapiNodeRef> getNodes(ModelObject context) {
+        Augmentable augmentedContext = (Augmentable) context;
+        DefaultAugmentedTapiCommonContext topologyContext
+                = augmentedContext.augmentation(DefaultAugmentedTapiCommonContext.class);
+        Topology topology = topologyContext.topology().get(0);
+
+        if (topology.node() == null) {
+            return Collections.emptyList();
+        }
+        return topology.node().stream()
+                .map(node -> {
+                    String deviceId = node.name().stream()
+                            .filter(kv -> kv.valueName().equals(DEVICE_ID))
+                            .findFirst().map(Name::value).get();
+                    return DcsBasedTapiNodeRef.create(topology, node)
+                            .setDeviceId(DeviceId.deviceId(deviceId));
+                })
+                .collect(Collectors.toList());
+    }
+
+    private List<TapiNepRef> getNeps(ModelObject context) {
+        Augmentable augmentedContext = (Augmentable) context;
+        DefaultAugmentedTapiCommonContext topologyContext
+                = augmentedContext.augmentation(DefaultAugmentedTapiCommonContext.class);
+        Topology topology = topologyContext.topology().get(0);
+
+        if (topology.node() == null) {
+            return Collections.emptyList();
+        }
+        List<TapiNepRef> ret = topology.node().stream()
+                .flatMap(node -> {
+                    if (node.ownedNodeEdgePoint() == null) {
+                        return null;
+                    }
+                    return node.ownedNodeEdgePoint().stream()
+                                    .map(nep -> {
+                                        String onosConnectPoint = nep.name().stream()
+                                                .filter(kv -> kv.valueName().equals(ONOS_CP))
+                                                .findFirst().map(Name::value).get();
+                                        TapiNepRef nepRef = DcsBasedTapiNepRef.create(topology, node, nep)
+                                                .setConnectPoint(ConnectPoint.fromString(onosConnectPoint));
+                                        if (nep.mappedServiceInterfacePoint() != null) {
+                                            nep.mappedServiceInterfacePoint().stream()
+                                                    .forEach(sip -> {
+                                                        nepRef.setSipId(sip.serviceInterfacePointId().toString());
+                                                    });
+                                        }
+                                        return nepRef;
+                                    });
+                        }
+                ).collect(Collectors.toList());
+        return ret;
+    }
+
+    private void updateNodes(DefaultTapiResolver resolver, List<TapiNodeRef> nodes) {
+        resolver.addNodeRefList(nodes);
+    }
+
+    private void updateNeps(DefaultTapiResolver resolver, List<TapiNepRef> neps) {
+        resolver.addNepRefList(neps);
+    }
+
+
+
+    private ResourceId getResourceId(ModelObjectId modelId) {
+        ModelObjectData data = DefaultModelObjectData.builder()
+                .identifier(modelId)
+                .build();
+        ResourceData rnode = modelConverter.createDataNode(data);
+        return rnode.resourceId();
+    }
+
+}
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 6da8cbf..1ab7f12 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,14 +16,12 @@
 
 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;
@@ -38,14 +36,9 @@
 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;
@@ -57,9 +50,6 @@
 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;
@@ -79,11 +69,12 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ModelConverter modelConverter;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TapiResolver tapiResolver;
+
     private DefaultContext context = new DefaultContext();
     private DefaultTopology topology = new DefaultTopology();
 
-    private TapiResolver tapiResolver = new TapiResolver();
-
     @Activate
     public void activate() {
         initDcsIfRootNotExist();
@@ -104,14 +95,9 @@
         if (tapiResolver.hasNodeRef(deviceId)) {
             return;
         }
-        TapiNodeBuilder builder = 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);
+                .setDeviceId(deviceId).build();
     }
 
     @Override
@@ -123,21 +109,16 @@
     public void addLink(Link link) {
         log.info("Add link: {}", link);
 
-        // validation check
-
-        // src nep
-        addNep(link.src());
-        addNep(link.dst());
+        // TODO: existence check
 
         // link
         TapiNepRef srcNepRef = tapiResolver.getNepRef(link.src());
         TapiNepRef dstNepRef = tapiResolver.getNepRef(link.dst());
 
-        TapiLinkBuilder linkBuilder = TapiLinkBuilder.builder()
+        TapiLinkBuilder.builder()
                 .setTopologyUuid(topology.uuid())
-                .setNep(srcNepRef)
-                .setNep(dstNepRef);
-        addModelObjectDataToDcs(linkBuilder.build());
+                .addNep(srcNepRef)
+                .addNep(dstNepRef).build();
     }
 
     @Override
@@ -148,7 +129,9 @@
     @Override
     public void addPort(Port port) {
         log.info("Add port: {}", port);
-        if (tapiResolver.hasNepRef(new ConnectPoint(port.element().id(), port.number()))) {
+
+        ConnectPoint cp = new ConnectPoint(port.element().id(), port.number());
+        if (tapiResolver.hasNepRef(cp)) {
             return;
         }
 
@@ -157,24 +140,18 @@
 
         // nep
         TapiNepBuilder nepBuilder = TapiNepBuilder.builder()
-                .setPort(port)
+                .setConnectPoint(cp)
                 .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());
+        if (TapiSipBuilder.isSip(cp)) {
 
-            addModelObjectDataToDcs(sipBuilder.build());
+            TapiSipBuilder sipBuilder = TapiSipBuilder.builder().setConnectPoint(cp);
+            nepBuilder.addSip(sipBuilder.getUuid());
+            sipBuilder.build();
         }
-
-        addModelObjectDataToDcs(nepBuilder.build());
-        tapiResolver.addNepRef(nepRef);
+        nepBuilder.build();
     }
 
     @Override
@@ -182,60 +159,16 @@
         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());
+        TapiContextBuilder.builder(context).build();
     }
 
     private void initDcsTapiTopology() {
-        TapiTopologyBuilder builder = TapiTopologyBuilder.builder(topology);
-        addModelObjectDataToDcs(builder.build());
+        TapiTopologyBuilder.builder(topology).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() {
 
         log.info("read root:");
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DefaultTapiResolver.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DefaultTapiResolver.java
new file mode 100644
index 0000000..f5a9bc6
--- /dev/null
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DefaultTapiResolver.java
@@ -0,0 +1,195 @@
+/*
+ * 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.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.CopyOnWriteArrayList;
+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.Service;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.ElementId;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+@Component(immediate = true)
+@Service
+public class DefaultTapiResolver implements TapiResolver {
+
+    private final Logger log = getLogger(getClass());
+
+    protected TapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
+
+    private List<TapiNodeRef> tapiNodeRefList = new CopyOnWriteArrayList<>();
+    private List<TapiNepRef> tapiNepRefList = new CopyOnWriteArrayList<>();
+
+    /**
+     * When source (e.g. DCS) is updated, set true
+     * When cache update completed successfully, set false
+     *
+     * This flag takes effect when cache update failed with exception,
+     * this remains to be true so the cache update process conducts again
+     */
+    private Boolean isDirty = false;
+
+    /**
+     * When source (e.g. DCS) is updated, set true
+     * When cache update started, set false
+     *
+     * This flag takes effect when source updated during cache updating
+     * this forces cache update again at the next request
+     */
+    private Boolean sourceUpdated = false;
+
+    @Activate
+    public void activate() {
+        log.info("Started");
+        dataProvider.init();
+    }
+
+    @Deactivate
+    public void deactivate() {
+        log.info("Stopped");
+    }
+
+    @Override
+    public boolean hasNodeRef(ElementId deviceId) {
+        updateCache();
+        return tapiNodeRefList.stream()
+                .anyMatch(node -> node.getDeviceId().equals(deviceId));
+    }
+
+    @Override
+    public boolean hasNepRef(ConnectPoint cp) {
+        updateCache();
+        return tapiNepRefList.stream()
+                .anyMatch(nep -> nep.getConnectPoint().equals(cp));
+    }
+
+    @Override
+    public boolean hasNepRef(String sipId) {
+        updateCache();
+        return tapiNepRefList.stream()
+                .anyMatch(nep -> nep.getSipId().equals(sipId));
+    }
+
+    @Override
+    public TapiNodeRef getNodeRef(ElementId deviceId) throws NoSuchElementException {
+        updateCache();
+        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;
+    }
+
+    @Override
+    public List<TapiNodeRef> getNodeRefs() {
+        updateCache();
+        return new ArrayList<>(tapiNodeRefList);
+    }
+
+    @Override
+    public TapiNepRef getNepRef(ConnectPoint cp) throws NoSuchElementException {
+        updateCache();
+        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;
+    }
+
+    @Override
+    public TapiNepRef getNepRef(String sipId) throws NoSuchElementException {
+        updateCache();
+        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;
+    }
+
+    @Override
+    public List<TapiNepRef> getNepRefs() {
+        updateCache();
+        return new ArrayList<>(tapiNepRefList);
+    }
+
+    @Override
+    public void makeDirty() {
+        sourceUpdated = true;
+        isDirty = true;
+    }
+
+    protected void addNodeRef(TapiNodeRef nodeRef) {
+        tapiNodeRefList.add(nodeRef);
+        log.info("Nodes: {}", tapiNodeRefList);
+    }
+
+    protected void addNepRef(TapiNepRef nepRef) {
+        tapiNepRefList.add(nepRef);
+        log.info("Neps: {}", tapiNepRefList);
+    }
+
+    protected void addNodeRefList(List<TapiNodeRef> nodes) {
+        tapiNodeRefList = nodes;
+        log.info("Nodes: {}", tapiNodeRefList);
+    }
+
+    protected void addNepRefList(List<TapiNepRef> neps) {
+        tapiNepRefList = neps;
+        log.info("Neps: {}", tapiNepRefList);
+    }
+
+    private void updateCache() {
+        log.info("Dirty: {}, Source updated: {}", isDirty, sourceUpdated);
+        if (isDirty || sourceUpdated) {
+            sourceUpdated = false;
+            clearCache();
+            dataProvider.updateCacheRequest(this);
+            log.info("Update completed: {}", tapiNodeRefList);
+            isDirty = false;
+        }
+    }
+
+    private void clearCache() {
+        tapiNodeRefList.clear();
+        tapiNepRefList.clear();
+    }
+}
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiDataProducer.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiDataProducer.java
new file mode 100644
index 0000000..8d0c2d5
--- /dev/null
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiDataProducer.java
@@ -0,0 +1,32 @@
+/*
+ * 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.internal;
+
+/**
+ * ODTN Tapi data reader/provider for TapiResolver cache update.
+ */
+public interface TapiDataProducer {
+
+    void init();
+
+    /**
+     * Update TapiResolver cache with latest modelObject in DCS.
+     * @param resolver update target itself
+     */
+    void updateCacheRequest(DefaultTapiResolver resolver);
+
+}
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiResolver.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiResolver.java
new file mode 100644
index 0000000..5311cd9
--- /dev/null
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/TapiResolver.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.internal;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.ElementId;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
+
+/**
+ * TAPI Yang object resolver.
+ * <p>
+ * This service works as TAPI Yang object cache, and provide
+ * TAPI object resolve service, e.g. TAPI Node/NodeEdgePoint/Link.
+ * This is independent with DCS and uses not DCS ModelObject directly
+ * but DCS-independent object like TapiNodeRef/TapiNepRef.
+ * This should work together with TapiDataProducer, which acts as
+ * data producer by reading TAPI modelObjects from DCS and convert them
+ * to DCS-independent objects.
+ */
+public interface TapiResolver {
+
+    /**
+     * Check existence of TAPI node associated with deviceId.
+     *
+     * @param deviceId search key
+     * @return boolean
+     */
+    boolean hasNodeRef(ElementId deviceId);
+
+    /**
+     * Check existence of TAPI nep associated with ConnectPoint.
+     *
+     * @param cp search key
+     * @return TapiNepRef
+     */
+    boolean hasNepRef(ConnectPoint cp);
+
+    /**
+     * Check existence of TAPI nep associated with TAPI sipId.
+     *
+     * @param sipId search key
+     * @return TapiNepRef
+     */
+    boolean hasNepRef(String sipId);
+
+    /**
+     * Resolve TAPI node associated with deviceId.
+     *
+     * @param deviceId search key
+     * @return TapiNodeRef
+     * @throws NoSuchElementException if target not found
+     */
+    TapiNodeRef getNodeRef(ElementId deviceId);
+
+    /**
+     * Get all NodeRefs.
+     *
+     * @return List&lt;TapiNodeRef&gt;
+     */
+    List<TapiNodeRef> getNodeRefs();
+
+    /**
+     * Resolve TAPI nep associated with ConnectPoint.
+     *
+     * @param cp search key
+     * @return TapiNepRef
+     * @throws NoSuchElementException if target not found
+     */
+    TapiNepRef getNepRef(ConnectPoint cp);
+
+    /**
+     * Resolve TAPI nep associated with TAPI sipId.
+     *
+     * @param sipId search key
+     * @return TapiNepRef
+     * @throws NoSuchElementException if target not found
+     */
+    TapiNepRef getNepRef(String sipId);
+
+    /**
+     * Get all NepRefs.
+     *
+     * @return List&lt;TapiNepRef&gt;
+     */
+    List<TapiNepRef> getNepRefs();
+
+    /**
+     * Inform the cache is already got dirty and let it update cache.
+     * The cache update process is conducted when next resolve request
+     * (hasXXX or getXXX) comes.
+     */
+    void makeDirty();
+
+}
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 0f02c63..1be4ed5 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
@@ -21,7 +21,7 @@
 import org.onosproject.net.Port;
 
 /**
- * ODTN Tapi manager application interface.
+ * ODTN Tapi topology manager application interface.
  */
 public interface TapiTopologyManager {
 
diff --git a/apps/odtn/service/src/test/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducerTest.java b/apps/odtn/service/src/test/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducerTest.java
new file mode 100644
index 0000000..b259235
--- /dev/null
+++ b/apps/odtn/service/src/test/java/org/onosproject/odtn/internal/DcsBasedTapiDataProducerTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.odtn.utils.tapi.DcsBasedTapiNepRef;
+import org.onosproject.odtn.utils.tapi.DcsBasedTapiNodeRef;
+import org.onosproject.odtn.utils.tapi.TapiNepBuilder;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeBuilder;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
+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.tapicontext.DefaultServiceInterfacePoint;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.context.DefaultAugmentedTapiCommonContext;
+import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.node.DefaultOwnedNodeEdgePoint;
+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.model.Augmentable;
+
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
+public class DcsBasedTapiDataProducerTest {
+
+    private DefaultContext context;
+    private DefaultTopology topology;
+    private DefaultNode node1, node2;
+    private DefaultServiceInterfacePoint sip11, sip21;
+    private DefaultOwnedNodeEdgePoint nep11, nep12, nep21, nep22;
+
+    private DeviceId did1, did2;
+    private ConnectPoint cp11, cp12, cp21, cp22;
+
+    @Before
+    public void setUp() {
+        makeTestData();
+    }
+
+    private void makeTestData() {
+
+        did1 = DeviceId.deviceId("netconf:127.0.0.1:11001");
+        did2 = DeviceId.deviceId("netconf:127.0.0.1:11002");
+
+        cp11 = new ConnectPoint(did1, PortNumber.portNumber(1, "TRANSCEIVER"));
+        cp12 = new ConnectPoint(did1, PortNumber.portNumber(2, "TRANSCEIVER"));
+        cp21 = new ConnectPoint(did2, PortNumber.portNumber(1, "TRANSCEIVER"));
+        cp22 = new ConnectPoint(did2, PortNumber.portNumber(2, "TRANSCEIVER"));
+
+        context = new DefaultContext();
+
+        topology = TapiTopologyBuilder.builder(new DefaultTopology()).getModelObject();
+        DefaultAugmentedTapiCommonContext topologyContext = new DefaultAugmentedTapiCommonContext();
+        topologyContext.addToTopology(topology);
+        Augmentable augmentableContext = context;
+        augmentableContext.addAugmentation(topologyContext);
+
+        node1 = TapiNodeBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setDeviceId(did1)
+                .getModelObject();
+
+        node2 = TapiNodeBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setDeviceId(did2)
+                .getModelObject();
+
+        sip11 = TapiSipBuilder.builder()
+                .setConnectPoint(cp11).getModelObject();
+
+        sip21 = TapiSipBuilder.builder()
+                .setConnectPoint(cp21).getModelObject();
+
+        nep11 = TapiNepBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(node1.uuid())
+                .setConnectPoint(cp11)
+                .addSip(sip11.uuid())
+                .getModelObject();
+
+        nep12 = TapiNepBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(node1.uuid())
+                .setConnectPoint(cp12)
+                .getModelObject();
+
+        nep21 = TapiNepBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(node2.uuid())
+                .setConnectPoint(cp21)
+                .addSip(sip21.uuid())
+                .getModelObject();
+
+        nep22 = TapiNepBuilder.builder()
+                .setTopologyUuid(topology.uuid())
+                .setNodeUuid(node2.uuid())
+                .setConnectPoint(cp22)
+                .getModelObject();
+
+    }
+
+    @Test
+    public void testUpdateCache() {
+
+        DcsBasedTapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
+        DefaultTapiResolver mockResolver = EasyMock.createMock(DefaultTapiResolver.class);
+
+        topology.addToNode(node1);
+        topology.addToNode(node2);
+        context.addToServiceInterfacePoint(sip11);
+        context.addToServiceInterfacePoint(sip21);
+        node1.addToOwnedNodeEdgePoint(nep11);
+        node1.addToOwnedNodeEdgePoint(nep12);
+        node2.addToOwnedNodeEdgePoint(nep21);
+        node2.addToOwnedNodeEdgePoint(nep22);
+
+        List<TapiNodeRef> expectNodes = Arrays.asList(
+                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+        );
+        List<TapiNepRef> expectNeps = Arrays.asList(
+                DcsBasedTapiNepRef.create(topology, node1, nep11).setConnectPoint(cp11)
+                        .setSipId(sip11.uuid().toString()),
+                DcsBasedTapiNepRef.create(topology, node1, nep12).setConnectPoint(cp12),
+                DcsBasedTapiNepRef.create(topology, node2, nep21).setConnectPoint(cp21)
+                        .setSipId(sip21.uuid().toString()),
+                DcsBasedTapiNepRef.create(topology, node2, nep22).setConnectPoint(cp22)
+        );
+
+        mockResolver.addNodeRefList(expectNodes);
+        expectLastCall().once();
+        mockResolver.addNepRefList(expectNeps);
+        expectLastCall().once();
+        replay(mockResolver);
+
+        dataProvider.updateCache(mockResolver, context);
+        verify(mockResolver);
+    }
+
+    @Test
+    public void testUpdateCacheWithoutSip() {
+
+        DcsBasedTapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
+        DefaultTapiResolver mockResolver = EasyMock.createMock(DefaultTapiResolver.class);
+
+        topology.addToNode(node1);
+        topology.addToNode(node2);
+        node1.addToOwnedNodeEdgePoint(nep11);
+        node2.addToOwnedNodeEdgePoint(nep21);
+        node2.addToOwnedNodeEdgePoint(nep22);
+
+        List<TapiNodeRef> expectNodes = Arrays.asList(
+                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+        );
+        List<TapiNepRef> expectNeps = Arrays.asList(
+                DcsBasedTapiNepRef.create(topology, node1, nep11).setConnectPoint(cp11),
+                DcsBasedTapiNepRef.create(topology, node2, nep21).setConnectPoint(cp21),
+                DcsBasedTapiNepRef.create(topology, node2, nep22).setConnectPoint(cp22)
+        );
+
+        mockResolver.addNodeRefList(expectNodes);
+        expectLastCall().once();
+        mockResolver.addNepRefList(expectNeps);
+        expectLastCall().once();
+        replay(mockResolver);
+
+        dataProvider.updateCache(mockResolver, context);
+        verify(mockResolver);
+    }
+
+    @Test
+    public void testUpdateCacheWithoutNep() {
+
+        DcsBasedTapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
+        DefaultTapiResolver mockResolver = EasyMock.createMock(DefaultTapiResolver.class);
+
+        topology.addToNode(node1);
+        topology.addToNode(node2);
+
+        List<TapiNodeRef> expectNodes = Arrays.asList(
+                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+        );
+        List<TapiNepRef> expectNeps = Collections.emptyList();
+
+        mockResolver.addNodeRefList(expectNodes);
+        expectLastCall().once();
+        mockResolver.addNepRefList(expectNeps);
+        expectLastCall().once();
+        replay(mockResolver);
+
+        dataProvider.updateCache(mockResolver, context);
+        verify(mockResolver);
+    }
+
+    @Test
+    public void testUpdateCacheWithoutNode() {
+
+        DcsBasedTapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
+        DefaultTapiResolver mockResolver = EasyMock.createMock(DefaultTapiResolver.class);
+
+        List<TapiNodeRef> expectNodes = Collections.emptyList();
+        List<TapiNepRef> expectNeps = Collections.emptyList();
+
+        mockResolver.addNodeRefList(expectNodes);
+        expectLastCall().once();
+        mockResolver.addNepRefList(expectNeps);
+        expectLastCall().once();
+        replay(mockResolver);
+
+        dataProvider.updateCache(mockResolver, context);
+        verify(mockResolver);
+    }
+
+
+}
\ 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/service/src/test/java/org/onosproject/odtn/internal/DefaultTapiResolverTest.java
similarity index 75%
rename from apps/odtn/api/src/test/java/org/onosproject/odtn/utils/tapi/TapiResolverTest.java
rename to apps/odtn/service/src/test/java/org/onosproject/odtn/internal/DefaultTapiResolverTest.java
index 0d420d8..9696f50 100644
--- a/apps/odtn/api/src/test/java/org/onosproject/odtn/utils/tapi/TapiResolverTest.java
+++ b/apps/odtn/service/src/test/java/org/onosproject/odtn/internal/DefaultTapiResolverTest.java
@@ -14,21 +14,25 @@
  * limitations under the License.
  */
 
-package org.onosproject.odtn.utils.tapi;
+package org.onosproject.odtn.internal;
 
 import java.util.NoSuchElementException;
+import org.easymock.EasyMock;
 import org.junit.Before;
 import org.junit.Test;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+import org.onosproject.odtn.utils.tapi.TapiNodeRef;
 
+import static org.easymock.EasyMock.replay;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.*;
 
-public class TapiResolverTest {
+public class DefaultTapiResolverTest {
 
-    private TapiResolver tapiResolver;
+    private DefaultTapiResolver tapiResolver;
 
     private TapiNodeRef nodeRef;
     private TapiNepRef nepRef;
@@ -41,13 +45,14 @@
     private ConnectPoint dummyCp;
     private String dummySipId;
 
+    private TapiDataProducer mockTapiDataProducer;
 
     @Before
     public void setUp() {
-        nodeRef = new TapiNodeRef(
+        nodeRef = TapiNodeRef.create(
                 "49e2ac46-3975-44b4-b84f-8fab28222a39",
                 "5638e8e6-ac17-40d9-86e4-7c1febab6f1a");
-        nepRef = new TapiNepRef(
+        nepRef = TapiNepRef.create(
                 "59e2ac46-3975-44b4-b84f-8fab28222a39",
                 "6638e8e6-ac17-40d9-86e4-7c1febab6f1a",
                 "cd673055-e2b2-4f67-88c8-adfae96385bc");
@@ -62,22 +67,31 @@
         dummyCp = new ConnectPoint(dummyDeviceId, PortNumber.portNumber(dummyPort));
         dummySipId = "00000000-0000-0000-0000-000000000000";
 
-        tapiResolver = new TapiResolver();
+        tapiResolver = new DefaultTapiResolver();
+
+        mockTapiDataProducer = EasyMock.createMock(TapiDataProducer.class);
+        mockTapiDataProducer.updateCacheRequest(tapiResolver);
+        replay(mockTapiDataProducer);
+
+        tapiResolver.dataProvider = mockTapiDataProducer;
     }
 
     @Test
     public void testGetNodeRef() {
-        assertThat(nodeRef, is(tapiResolver.addNodeRef(nodeRef).getNodeRef(deviceId)));
+        tapiResolver.addNodeRef(nodeRef);
+        assertThat(nodeRef, is(tapiResolver.getNodeRef(deviceId)));
     }
 
     @Test
     public void testGetNepRefWithConnectPoint() {
-        assertThat(nepRef, is(tapiResolver.addNepRef(nepRef).getNepRef(cp)));
+        tapiResolver.addNepRef(nepRef);
+        assertThat(nepRef, is(tapiResolver.getNepRef(cp)));
     }
 
     @Test
     public void testGetNepRefWithSipId() {
-        assertThat(nepRef, is(tapiResolver.addNepRef(nepRef).getNepRef(sipId)));
+        tapiResolver.addNepRef(nepRef);
+        assertThat(nepRef, is(tapiResolver.getNepRef(sipId)));
     }
 
     @Test(expected = NoSuchElementException.class)