Add device config change request using NetCfg

Change-Id: I01ae9caf298e606333ea31b2b480d744a2815c76
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/config/TerminalDeviceConfig.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/config/TerminalDeviceConfig.java
new file mode 100644
index 0000000..5cc5301
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/config/TerminalDeviceConfig.java
@@ -0,0 +1,112 @@
+/*
+ * 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.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.BaseConfig;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+
+import static org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery.OdtnPortType.CLIENT;
+import static org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery.OdtnPortType.LINE;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TerminalDeviceConfig extends BaseConfig<ConnectPoint> {
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * {@value #CONFIG_KEY} : a netcfg ConfigKey for {@link TerminalDeviceConfig}.
+     */
+    public static final String CONFIG_KEY = "odtn-terminal-device";
+
+    private static final String CLIENT_PORT = "client";
+    private static final String ENABLE = "enable";
+
+    /**
+     * Create a TerminalDeviceConfig for ODTN.
+     */
+    public TerminalDeviceConfig() {
+        super();
+    }
+
+    /**
+     * Create a TerminalDeviceConfig for ODTN.
+     *
+     * @param cp ConnectPoint
+     */
+    public TerminalDeviceConfig(ConnectPoint cp) {
+        ObjectMapper mapper = new ObjectMapper();
+        init(cp, CONFIG_KEY, mapper.createObjectNode(), mapper, null);
+    }
+
+    @Override
+    public boolean isValid() {
+        return isConnectPoint(CLIENT_PORT, FieldPresence.MANDATORY) &&
+                isBoolean(ENABLE, FieldPresence.MANDATORY);
+    }
+
+    public ConnectPoint clientCp() {
+        String cp = get(CLIENT_PORT, "");
+        return ConnectPoint.deviceConnectPoint(cp);
+    }
+
+    public TerminalDeviceConfig clientCp(ConnectPoint cp) {
+        String val = String.format("%s/%d", cp.deviceId(), cp.port().toLong());
+        setOrClear(CLIENT_PORT, val);
+        return this;
+    }
+
+    public Boolean isEnabled() {
+        return get(ENABLE, false);
+    }
+
+    public TerminalDeviceConfig enable() {
+        setOrClear(ENABLE, true);
+        return this;
+    }
+
+    public TerminalDeviceConfig disable() {
+        setOrClear(ENABLE, false);
+        return this;
+    }
+
+    /**
+     * Factory method in order to emit NetCfg event from onos inner call.
+     *
+     * @param line   side NodeEdgePoint of connection
+     * @param client side NodeEdgePoint of connection
+     * @return Config object for NetCfg
+     */
+    public static TerminalDeviceConfig create(TapiNepRef line, TapiNepRef client) {
+
+        if (line.getPortType() != LINE) {
+            throw new IllegalArgumentException("Argument line must be a LINE type.");
+        }
+        if (client.getPortType() != CLIENT) {
+            throw new IllegalArgumentException("Argument client must be a CLIENT type.");
+        }
+
+        TerminalDeviceConfig self = new TerminalDeviceConfig(line.getConnectPoint());
+        self.clientCp(client.getConnectPoint());
+        self.enable();
+        return self;
+    }
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/config/package-info.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/config/package-info.java
new file mode 100644
index 0000000..8db93f9
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/config/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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 to place ODTN NetCfg Config classes.
+ */
+package org.onosproject.odtn.config;
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
deleted file mode 100644
index e5fcf2d..0000000
--- a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNepRef.java
+++ /dev/null
@@ -1,36 +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 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;
-
-/**
- * TAPI Nep reference class which has a factory method using DCS modelObject.
- */
-public final class DcsBasedTapiNepRef extends TapiNepRef {
-
-    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
deleted file mode 100644
index b6260a7..0000000
--- a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiNodeRef.java
+++ /dev/null
@@ -1,34 +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 org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topology.Node;
-import org.onosproject.yang.gen.v1.tapitopology.rev20180307.tapitopology.topologycontext.Topology;
-
-/**
- * TAPI Node reference class which has a factory method using DCS modelObject.
- */
-public final class DcsBasedTapiNodeRef extends TapiNodeRef {
-
-    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/DcsBasedTapiObjectRefFactory.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiObjectRefFactory.java
new file mode 100644
index 0000000..e1d1889
--- /dev/null
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/DcsBasedTapiObjectRefFactory.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 org.onosproject.yang.gen.v1.tapiconnectivity.rev20180307.tapiconnectivity.connection.ConnectionEndPoint;
+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;
+
+/**
+ * Util class to create TapiXXXRef class instances using classes auto-generated by onos-yang-tool compiler.
+ */
+public final class DcsBasedTapiObjectRefFactory {
+
+    private DcsBasedTapiObjectRefFactory() {
+    }
+
+    /**
+     * Factory method to create {@link TapiNodeRef}.
+     *
+     * @param topology ModelObject context/topology
+     * @param node     ModelObject context/topology/node
+     * @return node reference instance
+     */
+    public static TapiNodeRef create(Topology topology, Node node) {
+        return TapiNodeRef.create(topology.uuid().toString(), node.uuid().toString());
+    }
+
+    /**
+     * Factory method to create {@link TapiNepRef}.
+     *
+     * @param topology ModelObject context/topology
+     * @param node     ModelObject context/topology/node
+     * @param nep      ModelObject context/topology/node/ownedNodeEdgePoint
+     * @return nep reference instance
+     */
+    public static TapiNepRef create(Topology topology, Node node, OwnedNodeEdgePoint nep) {
+        return TapiNepRef.create(topology.uuid().toString(), node.uuid().toString(), nep.uuid().toString());
+    }
+
+    /**
+     * Factory method to create {@link TapiCepRef}.
+     *
+     * @param cep ModelObject context/connection/connectionEndPoint
+     * @return cep reference instance
+     */
+    public static TapiCepRef create(ConnectionEndPoint cep) {
+        return TapiCepRef.create(cep.topologyId().toString(), cep.nodeId().toString(),
+                cep.ownedNodeEdgePointId().toString(), cep.connectionEndPointId().toString());
+    }
+
+}
diff --git a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiConnectionHandler.java b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiConnectionHandler.java
index b3d6f3e..6e3b729 100644
--- a/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiConnectionHandler.java
+++ b/apps/odtn/api/src/main/java/org/onosproject/odtn/utils/tapi/TapiConnectionHandler.java
@@ -100,6 +100,10 @@
         return this;
     }
 
+    public List<ConnectionEndPoint> getCeps() {
+        return obj.connectionEndPoint();
+    }
+
     public List<TapiConnectionHandler> getLowerConnections() {
 
         try {
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 af4d299..95b3e05 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
@@ -42,7 +42,7 @@
  * TAPI reference class should be used in ODTN ServiceApplication
  * in order to make independent ServiceApplication implementation from DCS.
  */
-public class TapiNepRef {
+public final class TapiNepRef {
 
     protected final Logger log = getLogger(getClass());
 
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 8db2005..71cd256 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
@@ -34,7 +34,7 @@
  * TAPI reference class should be used in ODTN ServiceApplication
  * in order to make independent ServiceApplication implementation from DCS.
  */
-public class TapiNodeRef {
+public final class TapiNodeRef {
 
     protected final Logger log = getLogger(getClass());
 
@@ -42,7 +42,7 @@
     private final UUID nodeId;
     private DeviceId deviceId;
 
-    TapiNodeRef(String topologyId, String nodeId) {
+    private TapiNodeRef(String topologyId, String nodeId) {
         this.topologyId = UUID.fromString(topologyId);
         this.nodeId = UUID.fromString(nodeId);
     }
diff --git a/apps/odtn/api/src/test/resources/odtn-terminal-device-config.json b/apps/odtn/api/src/test/resources/odtn-terminal-device-config.json
new file mode 100644
index 0000000..3a44751
--- /dev/null
+++ b/apps/odtn/api/src/test/resources/odtn-terminal-device-config.json
@@ -0,0 +1,17 @@
+{
+  "ports" : {
+    "netconf:127.0.0.1:11001/42" : {
+      "odtn-terminal-device" : {
+        "client" : "netconf:127.0.0.1:11001/41",
+        "enable" : true
+      }
+    },
+    "netconf:127.0.0.1:11002/42" : {
+      "odtn-terminal-device" : {
+        "client" : "netconf:127.0.0.1:11002/41",
+        "enable" : true
+      }
+    }
+  }
+}
+
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 48057c8..a663cc8 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
@@ -25,11 +25,13 @@
 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.ConnectPoint;
 import org.onosproject.net.Link;
+import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
 import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.NetworkConfigStoreDelegate;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
@@ -38,15 +40,14 @@
 import org.onosproject.net.link.LinkService;
 import org.onosproject.odtn.TapiResolver;
 import org.onosproject.odtn.TapiTopologyManager;
+import org.onosproject.odtn.config.TerminalDeviceConfig;
 import org.onosproject.odtn.internal.DcsBasedTapiCommonRpc;
 import org.onosproject.odtn.internal.DcsBasedTapiConnectivityRpc;
 import org.onosproject.odtn.internal.DcsBasedTapiDataProducer;
 import org.onosproject.odtn.internal.TapiDataProducer;
-import org.onosproject.store.AbstractStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 // DCS / onos-yang-tools
 import org.onosproject.config.DynamicConfigEvent;
 import org.onosproject.config.DynamicConfigListener;
@@ -55,6 +56,10 @@
 
 import static org.onosproject.config.DynamicConfigEvent.Type.NODE_ADDED;
 import static org.onosproject.config.DynamicConfigEvent.Type.NODE_DELETED;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_REMOVED;
+import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
+import static org.onosproject.net.config.basics.SubjectFactories.CONNECT_POINT_SUBJECT_FACTORY;
 
 /**
  * OSGi Component for ODTN Service application.
@@ -77,6 +82,9 @@
     protected NetworkConfigService netcfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigRegistry netcfgRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected RpcRegistry rpcRegistry;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -93,12 +101,21 @@
     private final LinkListener linkListener = new InternalLinkListener();
     private final NetworkConfigListener netcfgListener = new InternalNetCfgListener();
     private TapiDataProducer dataProvider = new DcsBasedTapiDataProducer();
-    private InternalNetCfgManager netcfgStore = new InternalNetCfgManager();
 
     // Rpc Service for TAPI Connectivity
     private final DcsBasedTapiConnectivityRpc rpcTapiConnectivity = new DcsBasedTapiConnectivityRpc();
     private final DcsBasedTapiCommonRpc rpcTapiCommon = new DcsBasedTapiCommonRpc();
 
+    // FIXME create factory and register for all behaviours
+    private final ConfigFactory<ConnectPoint, TerminalDeviceConfig> factory =
+            new ConfigFactory<ConnectPoint, TerminalDeviceConfig>(CONNECT_POINT_SUBJECT_FACTORY,
+                    TerminalDeviceConfig.class, TerminalDeviceConfig.CONFIG_KEY) {
+                @Override
+                public TerminalDeviceConfig createConfig() {
+                    return new TerminalDeviceConfig();
+                }
+            };
+
 
     @Activate
     protected void activate() {
@@ -107,8 +124,10 @@
         deviceService.addListener(deviceListener);
         linkService.addListener(linkListener);
         netcfgService.addListener(netcfgListener);
+        netcfgRegistry.registerConfigFactory(factory);
         rpcRegistry.registerRpcService(rpcTapiConnectivity);
         rpcRegistry.registerRpcService(rpcTapiCommon);
+
         rpcTapiConnectivity.init();
         rpcTapiCommon.init();
     }
@@ -119,6 +138,7 @@
         log.info("Stopped");
         rpcRegistry.unregisterRpcService(rpcTapiCommon);
         rpcRegistry.unregisterRpcService(rpcTapiConnectivity);
+        netcfgRegistry.unregisterConfigFactory(factory);
         netcfgService.removeListener(netcfgListener);
         linkService.removeListener(linkListener);
         deviceService.removeListener(deviceListener);
@@ -139,8 +159,8 @@
         @Override
         public void event(DeviceEvent event) {
 
-            netcfgStore.post(event);
-
+            log.info("Device event type: {}", event.type());
+            log.info("Device event subject: {}", event.subject());
             switch (event.type()) {
                 case DEVICE_ADDED:
                     tapiTopologyManager.addDevice(event.subject());
@@ -196,30 +216,40 @@
     private class InternalNetCfgListener implements NetworkConfigListener {
 
         /**
+         * Check if the netcfg event should be further processed.
+         *
+         * @param event config event
+         * @return true if event is supported; false otherwise
+         */
+        @Override
+        public boolean isRelevant(NetworkConfigEvent event) {
+
+            if (event.type() == CONFIG_ADDED || event.type() == CONFIG_UPDATED) {
+                if (event.config().orElse(null) instanceof TerminalDeviceConfig) {
+                    return true;
+                }
+            }
+            if (event.type() == CONFIG_REMOVED) {
+                if (event.prevConfig().orElse(null) instanceof TerminalDeviceConfig) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
          * Process an Event from the NetCfg Service.
          *
-         * @param event link event
+         * @param event event
          */
         @Override
         public void event(NetworkConfigEvent event) {
-//            Object config = event.subject();
-            log.info("config: {}", event.subject());
+
             log.info("type: {}", event.type());
+            log.info("subject: {}", event.subject());
         }
     }
 
-    private class InternalNetCfgManager
-        extends AbstractStore<NetworkConfigEvent, NetworkConfigStoreDelegate> {
-
-        public void post(Object obj) {
-            log.info("Post netcfg event : {}", obj);
-            NetworkConfigEvent.Type type = NetworkConfigEvent.Type.CONFIG_UPDATED;
-            notifyDelegate(new NetworkConfigEvent(type, obj, obj.getClass()));
-        }
-
-    }
-
-
     /**
      * Representation of internal listener, listening for dynamic config event.
      */
@@ -273,7 +303,6 @@
 //            }
         }
 
-
 //        /**
 //         * Process the event that a node has been added to the DCS.
 //         *
@@ -298,14 +327,13 @@
 //            NodeKey dataNodeKey = node.key();
 //            SchemaId schemaId = dataNodeKey.schemaId();
 
-            // Consolidate events
+        // Consolidate events
 //            if (!schemaId.namespace().contains("tapi")) {
 //                return;
 //            }
 //            log.info("namespace {}", schemaId.namespace());
 //        }
 
-
 //        /**
 //         * Process the event that a node has been deleted from the DCS.
 //         *
@@ -317,7 +345,4 @@
 
     }
 
-
-
-
 }
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiConnectionManager.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiConnectionManager.java
index 6ddb662..b585506 100644
--- a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiConnectionManager.java
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DcsBasedTapiConnectionManager.java
@@ -17,15 +17,22 @@
 package org.onosproject.odtn.internal;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import java.util.concurrent.atomic.AtomicReference;
 import org.onosproject.config.FailedException;
-import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.odtn.TapiResolver;
+import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;
+import org.onosproject.odtn.utils.tapi.DcsBasedTapiObjectRefFactory;
+import org.onosproject.odtn.utils.tapi.TapiCepPair;
 import org.onosproject.odtn.utils.tapi.TapiConnection;
 import org.onosproject.odtn.utils.tapi.TapiNepPair;
 import org.onosproject.odtn.utils.tapi.TapiCepRefHandler;
 import org.onosproject.odtn.utils.tapi.TapiConnectionHandler;
 
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
 import org.onosproject.odtn.utils.tapi.TapiRouteHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,13 +42,15 @@
 /**
  * DCS-dependent Tapi connection manager implementation.
  */
-public class DcsBasedTapiConnectionManager implements TapiConnectionManager {
+public final class DcsBasedTapiConnectionManager implements TapiConnectionManager {
 
     private final Logger log = LoggerFactory.getLogger(getClass());
     protected TapiPathComputer connectionController;
-    private DeviceService deviceService;
+    private TapiResolver resolver;
+    private NetworkConfigService netcfgService;
 
     private List<DcsBasedTapiConnectionManager> connectionManagerList = new ArrayList<>();
+    private TapiConnection connection = null;
     private TapiConnectionHandler connectionHandler = TapiConnectionHandler.create();
     private Operation op = null;
 
@@ -51,10 +60,14 @@
         DELETE
     }
 
+    private DcsBasedTapiConnectionManager() {
+    }
+
     public static DcsBasedTapiConnectionManager create() {
         DcsBasedTapiConnectionManager self = new DcsBasedTapiConnectionManager();
         self.connectionController = DefaultTapiPathComputer.create();
-        self.deviceService = getService(DeviceService.class);
+        self.resolver = getService(TapiResolver.class);
+        self.netcfgService = getService(NetworkConfigService.class);
         return self;
     }
 
@@ -72,22 +85,20 @@
     @Override
     public void deleteConnection(TapiConnectionHandler connectionHandler) {
 
-        // read target to be deleted
-        this.connectionHandler = connectionHandler;
-        this.connectionHandler.read();
-        log.info("model: {}", connectionHandler.getModelObject());
-
         deleteConnectionRecursively(connectionHandler);
     }
 
     @Override
     public void apply() {
         connectionManagerList.forEach(DcsBasedTapiConnectionManager::apply);
+
         switch (op) {
             case CREATE:
+                notifyDeviceConfigChange(true);
                 connectionHandler.add();
                 break;
             case DELETE:
+                notifyDeviceConfigChange(false);
                 connectionHandler.remove();
                 break;
             default:
@@ -96,6 +107,37 @@
     }
 
     /**
+     * Emit NetworkConfig event with parameters for device config,
+     * to notify configuration change to device drivers.
+     */
+    private void notifyDeviceConfigChange(boolean enable) {
+        if (!this.connection.getCeps().isSameNode()) {
+            return;
+        }
+
+        TapiNepRef left = this.connection.getCeps().left().getNepRef();
+        TapiNepRef right = this.connection.getCeps().right().getNepRef();
+
+        // update with latest data in DCS
+        left = resolver.getNepRef(left);
+        right = resolver.getNepRef(right);
+
+        AtomicReference<TapiNepRef> line = new AtomicReference<>();
+        AtomicReference<TapiNepRef> client = new AtomicReference<>();
+        Arrays.asList(left, right).forEach(nep -> {
+            if (nep.getPortType() == OdtnDeviceDescriptionDiscovery.OdtnPortType.LINE) {
+                line.set(nep);
+            }
+            if (nep.getPortType() == OdtnDeviceDescriptionDiscovery.OdtnPortType.CLIENT) {
+                client.set(nep);
+            }
+        });
+
+        DeviceConfigEventEmitter eventEmitter = DeviceConfigEventEmitter.create();
+        eventEmitter.emit(line.get(), client.get(), enable);
+    }
+
+    /**
      * Generate TAPI connection and its under connections recursively
      * and add them to creation queue.
      *
@@ -104,6 +146,7 @@
     private void createConnectionRecursively(TapiConnection connection) {
         op = Operation.CREATE;
         connectionManagerList.clear();
+        this.connection = connection;
 
         TapiRouteHandler routeBuilder = TapiRouteHandler.create();
 
@@ -136,6 +179,16 @@
         op = Operation.DELETE;
         connectionManagerList.clear();
 
+        // read target to be deleted
+        connectionHandler.read();
+        log.info("model: {}", connectionHandler.getModelObject());
+
+        this.connection = TapiConnection.create(
+                TapiCepPair.create(
+                        DcsBasedTapiObjectRefFactory.create(connectionHandler.getCeps().get(0)),
+                        DcsBasedTapiObjectRefFactory.create(connectionHandler.getCeps().get(1)))
+        );
+
         this.connectionHandler = connectionHandler;
         this.connectionHandler.getLowerConnections().forEach(lowerConnectionHandler -> {
             delegateConnectionDeletion(lowerConnectionHandler);
@@ -157,7 +210,7 @@
     /**
      * Delegate lower-connection deletion to other corresponding TapiConnectionManager of each Nodes.
      *
-     * @param connectionHandler  connectionHandler of connection to be deleted
+     * @param connectionHandler connectionHandler of connection to be deleted
      */
     private void delegateConnectionDeletion(TapiConnectionHandler connectionHandler) {
         log.info("model: {}", connectionHandler.getModelObject());
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
index 726d002..4adc3d2 100644
--- 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
@@ -27,8 +27,7 @@
 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.DcsBasedTapiObjectRefFactory;
 import org.onosproject.odtn.utils.tapi.TapiNepRef;
 import org.onosproject.odtn.utils.tapi.TapiNodeRef;
 import org.onosproject.yang.gen.v1.tapicommon.rev20180307.tapicommon.DefaultContext;
@@ -122,7 +121,7 @@
         }
         return topology.node().stream()
                 .map(node -> {
-                    DcsBasedTapiNodeRef nodeRef = DcsBasedTapiNodeRef.create(topology, node);
+                    TapiNodeRef nodeRef = DcsBasedTapiObjectRefFactory.create(topology, node);
                     if (node.name() != null) {
                         String deviceId = node.name().stream()
                                 .filter(kv -> kv.valueName().equals(DEVICE_ID))
@@ -155,7 +154,7 @@
                             }
                             return node.ownedNodeEdgePoint().stream()
                                     .map(nep -> {
-                                        TapiNepRef nepRef = DcsBasedTapiNepRef.create(topology, node, nep);
+                                        TapiNepRef nepRef = DcsBasedTapiObjectRefFactory.create(topology, node, nep);
                                         if (nep.name() != null) {
                                             Map<String, String> kvs = new HashMap<>();
                                             nep.name().forEach(kv -> kvs.put(kv.valueName(), kv.value()));
diff --git a/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DeviceConfigEventEmitter.java b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DeviceConfigEventEmitter.java
new file mode 100644
index 0000000..32121ae
--- /dev/null
+++ b/apps/odtn/service/src/main/java/org/onosproject/odtn/internal/DeviceConfigEventEmitter.java
@@ -0,0 +1,63 @@
+/*
+ * 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 org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.odtn.config.TerminalDeviceConfig;
+import org.onosproject.odtn.utils.tapi.TapiNepRef;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onlab.osgi.DefaultServiceDirectory.getService;
+
+public final class DeviceConfigEventEmitter {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    private NetworkConfigService netcfgService;
+
+    private DeviceConfigEventEmitter() {
+    }
+
+    public static DeviceConfigEventEmitter create() {
+        DeviceConfigEventEmitter self = new DeviceConfigEventEmitter();
+        self.netcfgService = getService(NetworkConfigService.class);
+        return self;
+    }
+
+    /**
+     * Emit NetworkConfig event with parameters for device config.
+     *
+     * @param line   side NodeEdgePoint of connection
+     * @param client side NodeEdgePoint of connection
+     * @param enable or disable
+     */
+    public void emit(TapiNepRef line, TapiNepRef client, boolean enable) {
+
+        // FIXME Config class should be implemented as behaviour to support
+        //       multi device types.
+        TerminalDeviceConfig cfg = TerminalDeviceConfig.create(line, client);
+        if (enable) {
+            cfg.enable();
+        } else {
+            cfg.disable();
+        }
+        netcfgService.applyConfig(line.getConnectPoint(), TerminalDeviceConfig.class, cfg.node());
+    }
+
+}
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
index e616b21..bfc45c7 100644
--- 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
@@ -25,8 +25,7 @@
 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.DcsBasedTapiObjectRefFactory;
 import org.onosproject.odtn.utils.tapi.TapiNepHandler;
 import org.onosproject.odtn.utils.tapi.TapiNepRef;
 import org.onosproject.odtn.utils.tapi.TapiNodeHandler;
@@ -139,16 +138,16 @@
         node2.addToOwnedNodeEdgePoint(nep22);
 
         List<TapiNodeRef> expectNodes = Arrays.asList(
-                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
-                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+                DcsBasedTapiObjectRefFactory.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiObjectRefFactory.create(topology, node2).setDeviceId(did2)
         );
         List<TapiNepRef> expectNeps = Arrays.asList(
-                DcsBasedTapiNepRef.create(topology, node1, nep11).setConnectPoint(cp11)
+                DcsBasedTapiObjectRefFactory.create(topology, node1, nep11).setConnectPoint(cp11)
                         .setSipId(sip11.uuid().toString()),
-                DcsBasedTapiNepRef.create(topology, node1, nep12).setConnectPoint(cp12),
-                DcsBasedTapiNepRef.create(topology, node2, nep21).setConnectPoint(cp21)
+                DcsBasedTapiObjectRefFactory.create(topology, node1, nep12).setConnectPoint(cp12),
+                DcsBasedTapiObjectRefFactory.create(topology, node2, nep21).setConnectPoint(cp21)
                         .setSipId(sip21.uuid().toString()),
-                DcsBasedTapiNepRef.create(topology, node2, nep22).setConnectPoint(cp22)
+                DcsBasedTapiObjectRefFactory.create(topology, node2, nep22).setConnectPoint(cp22)
         );
 
         mockResolver.addNodeRefList(expectNodes);
@@ -174,13 +173,13 @@
         node2.addToOwnedNodeEdgePoint(nep22);
 
         List<TapiNodeRef> expectNodes = Arrays.asList(
-                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
-                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+                DcsBasedTapiObjectRefFactory.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiObjectRefFactory.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)
+                DcsBasedTapiObjectRefFactory.create(topology, node1, nep11).setConnectPoint(cp11),
+                DcsBasedTapiObjectRefFactory.create(topology, node2, nep21).setConnectPoint(cp21),
+                DcsBasedTapiObjectRefFactory.create(topology, node2, nep22).setConnectPoint(cp22)
         );
 
         mockResolver.addNodeRefList(expectNodes);
@@ -203,8 +202,8 @@
         topology.addToNode(node2);
 
         List<TapiNodeRef> expectNodes = Arrays.asList(
-                DcsBasedTapiNodeRef.create(topology, node1).setDeviceId(did1),
-                DcsBasedTapiNodeRef.create(topology, node2).setDeviceId(did2)
+                DcsBasedTapiObjectRefFactory.create(topology, node1).setDeviceId(did1),
+                DcsBasedTapiObjectRefFactory.create(topology, node2).setDeviceId(did2)
         );
         List<TapiNepRef> expectNeps = Collections.emptyList();
 
@@ -237,5 +236,4 @@
         verify(mockResolver);
     }
 
-
 }
\ No newline at end of file