Modulation consolidation

Change-Id: I1d7b48ec36250a135afa8624fa8351e3b3fa441e
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java
deleted file mode 100644
index 0149566..0000000
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationConfig.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright 2019-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.
- *
- * This Work is contributed by Sterlite Technologies
- */
-
-package org.onosproject.drivers.odtn;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.commons.configuration.HierarchicalConfiguration;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onosproject.drivers.odtn.util.NetconfSessionUtility;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Direction;
-import org.onosproject.net.ModulationScheme;
-import org.onosproject.net.OchSignal;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ModulationConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.netconf.NetconfController;
-import org.onosproject.netconf.NetconfSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.Optional;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/*
- * Driver Implementation of the ModulationConfig for OpenConfig terminal devices.
- */
-public class CassiniModulationConfig<T> extends AbstractHandlerBehaviour implements ModulationConfig<T> {
-
-
-    private static final String RPC_TAG_NETCONF_BASE =
-            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
-
-    private static final String RPC_CLOSE_TAG = "</rpc>";
-
-    private static final Logger log = LoggerFactory.getLogger(CassiniModulationConfig.class);
-
-    private ComponentType state = ComponentType.DIRECTION;
-
-    private static final double OSNR_THRESHOLD_VALUE = 13.0;
-
-
-    enum BitRate {
-        GBPS_200(200),      // 200 Gbps
-        GBPS_100(100),        // 100 Gbps
-        GBPS_40(40),          // 40 Gbps
-        GBPS_10(10);          // 10 Gbps
-
-        private final long value;
-
-        public long getValue() {
-            return value;
-        }
-
-        BitRate(long value) {
-            this.value = value;
-        }
-    }
-
-    private NetconfController getController() {
-        return handler().get(NetconfController.class);
-    }
-
-    /*
-     *
-     * Get the deviceId for which the methods apply.
-     *
-     * @return The deviceId as contained in the handler data
-     */
-
-
-    private DeviceId getDeviceId() {
-        return handler().data().deviceId();
-    }
-
-
-    /**
-     * Get the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @return ModulationScheme as per bitRate value
-     **/
-    @Override
-    public Optional<ModulationScheme> getModulationScheme(PortNumber port, T component) {
-        checkType(component);
-        return state.getModulationScheme(port, component);
-    }
-
-    /**
-     * Set the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @param bitRate   bit rate in bps
-     **/
-    @Override
-    public void setModulationScheme(PortNumber port, T component, long bitRate) {
-        checkType(component);
-        state.setModulationScheme(port, component, bitRate);
-    }
-
-    /*
-     *
-     * Set the ComponentType to invoke proper methods for different template T.
-     * @param component the component.
-     */
-    void checkType(Object component) {
-        String clsName = component.getClass().getName();
-
-        if (component instanceof Direction) {
-            state = CassiniModulationConfig.ComponentType.DIRECTION;
-        } else if (component instanceof OchSignal) {
-            state = CassiniModulationConfig.ComponentType.OCHSIGNAL;
-        } else {
-            log.error("Cannot parse the component type {}.", clsName);
-        }
-
-
-        state.cassini = this;
-    }
-
-    /*
-     *
-     * Component type.
-     */
-
-
-    enum ComponentType {
-
-        /*
-         *
-         * Direction.
-         */
-
-
-        DIRECTION() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                super.setModulationScheme(port, component, bitRate);
-            }
-        },
-
-        /**
-         * OchSignal.
-         */
-
-
-        OCHSIGNAL() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                super.setModulationScheme(port, component, bitRate);
-            }
-        };
-
-
-        CassiniModulationConfig cassini;
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @return target modulation
-         */
-        Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-            NetconfSession session = NetconfSessionUtility
-                    .getNetconfSession(cassini.getDeviceId(), cassini.getController());
-            checkNotNull(session);
-            String filter = createModulationFilter(cassini, port);
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<get>")
-                    .append("<filter>")
-                    .append(filter)
-                    .append("</filter>")
-                    .append("</get>")
-                    .append(RPC_CLOSE_TAG);
-            log.debug("RPC Call for Getting Modulation : \n {}", rpcReq.toString());
-            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("components/component/optical-channel/config");
-
-                String modulationScheme = String.valueOf(config.getString("modulation"));
-
-                return Optional.of(ModulationScheme.valueOf(modulationScheme));
-            } catch (IllegalArgumentException e) {
-                return Optional.empty();
-            }
-        }
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @param power target value
-         */
-        void setModulationScheme(PortNumber port, Object component, long bitRate) {
-
-            ModulationScheme modulation = null;
-            String editConfig = null;
-            double osnr = 0.0;
-            boolean rpcResponse = false;
-            boolean receiver = false;
-
-            // TODO OSNR is valid only for receiver so need to modify
-            /*if(component.toString().equals(Direction.INGRESS.toString())){
-                receiver=true;
-            }*/
-
-            //check if bitrate is less than equal to 100 Gig
-            if (bitRate <= BitRate.GBPS_100.value) {
-                modulation = ModulationScheme.DP_QPSK;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                rpcResponse = setModulationRpc(port, component, editConfig);
-                if (rpcResponse) {
-                    // TODO OSNR is valid only for receiver so need to modify
-                    osnr = fetchDeviceSnr(cassini, port);
-                    if (osnr <= OSNR_THRESHOLD_VALUE) {
-                        log.error("Channel not possible for this OSNR Value : {}", osnr);
-                    }
-                }
-            } else { // check if bitrate is greater than 100 Gig
-                modulation = ModulationScheme.DP_16QAM;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                rpcResponse = setModulationRpc(port, component, editConfig);
-                if (rpcResponse) {
-                    //TODO OSNR is valid only for receiver so need to modify
-                    osnr = fetchDeviceSnr(cassini, port);
-                    if (osnr <= OSNR_THRESHOLD_VALUE) {
-                        modulation = ModulationScheme.DP_8QAM;
-                        editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                        //setting the modulation by calling rpc
-                        rpcResponse = setModulationRpc(port, component, editConfig);
-                        if (rpcResponse) {
-                            // TODO OSNR is valid only for receiver so need to modify
-                            osnr = fetchDeviceSnr(cassini, port);
-                            if (osnr <= OSNR_THRESHOLD_VALUE) {
-                                log.warn("Channel not possible for this OSNR Value : {}." +
-                                        " Please reduce the channel bitrate.", osnr);
-                            }
-                        }
-                    }
-                }
-            }
-
-
-        }
-
-
-        /*
-         * Get filtered content under <optical-channel><state>.
-         * @param pc power config instance
-         * @param port the port number
-         * @param underState the filter condition
-         * @return RPC reply
-         */
-
-        //RPC call for OSNR still not finalised, need to update Rpc once validated
-        private static XMLConfiguration getTerminalDeviceSnr(CassiniModulationConfig config, PortNumber port) {
-            NetconfSession session = NetconfSessionUtility
-                    .getNetconfSession(config.getDeviceId(), config.getController());
-            checkNotNull(session);
-            String name = ocName(config, port);
-            StringBuilder rpcReq = new StringBuilder(RPC_TAG_NETCONF_BASE);
-            rpcReq.append("<get><filter>")
-                    .append("<osnr xmlns=\"http://openconfig.net/yang/terminal-device\">")
-                    .append("<instant/>")
-                    .append("</osnr></filter></get>")
-                    .append(RPC_CLOSE_TAG);
-            log.info("RPC Call for Fetching OSNR :\n\n {}", rpcReq.toString());
-            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
-            return xconf;
-        }
-
-        private static String createModulationFilter(CassiniModulationConfig modulationConfig, PortNumber portNumber) {
-            String name = ocName(modulationConfig, portNumber);
-            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
-            sb.append("<component>").append("<name>").append(name).append("</name>");
-            sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">");
-            sb.append("<config><modulation/></config>");
-            sb.append("</optical-channel>");
-            sb.append("</component>").append("</components>");
-            return sb.toString();
-        }
-
-        /**
-         * Extract component name from portNumber's annotations.
-         *
-         * @param pc         modulation config instance
-         * @param portNumber the port number
-         * @return the component name
-         */
-
-
-        private static String ocName(CassiniModulationConfig pc, PortNumber portNumber) {
-            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
-            DeviceId deviceId = pc.handler().data().deviceId();
-            return deviceService.getPort(deviceId, portNumber).annotations().value("oc-name");
-        }
-
-        private static String channelSpacing(CassiniModulationConfig modulationConfig, PortNumber portNumber) {
-            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
-            DeviceId deviceId = modulationConfig.handler().data().deviceId();
-            String lambda = deviceService.getPort(deviceId, portNumber).annotations().value("lambda");
-
-            ObjectMapper mapper = new ObjectMapper();
-            String channelSpacing = "";
-            try {
-                JsonNode actualObj = mapper.readTree(lambda);
-                JsonNode csNode = actualObj.get("channelSpacing");
-                channelSpacing = csNode.asText();
-                log.info("Channel_Spacing : " + channelSpacing);
-
-            } catch (IOException e) {
-                log.error("Error while parsing Json");
-            }
-            return channelSpacing;
-
-        }
-
-        private double fetchDeviceSnr(CassiniModulationConfig modulationConfig, PortNumber portNumber) {
-            double osnr = 0.0;
-            XMLConfiguration xconf = getTerminalDeviceSnr(cassini, portNumber);
-            if (xconf == null) {
-                return osnr;
-            }
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/state/osnr");
-                osnr = Float.valueOf(config.getString("snr")).doubleValue();
-                return osnr;
-            } catch (IllegalArgumentException e) {
-                return osnr;
-            }
-        }
-        /*
-         *
-         * Parse filtering string from port and component.
-         * @param portNumber Port Number
-         * @param component port component (optical-channel)
-         * @param bitRate bitRate in bps
-         * @return filtering string in xml format
-
-         */
-
-        private String modulationEditConfig(CassiniModulationConfig modulationConfig, PortNumber portNumber,
-                                            Object component, long bitRate, String modulation) {
-            if (component != null) {
-                String portName = ocName(modulationConfig, portNumber);
-                //String channelSpacing = channelSpacing(modulationConfig,portNumber);
-                //ChannelSpacing cs= ChannelSpacing.valueOf(channelSpacing);
-                //double csValue= cs.frequency().asGHz();
-
-                StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
-                sb.append("<component>").append("<name>").append(portName).append("</name>");
-                if (modulation != null) {
-                    // This is an edit-config operation.
-                    sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
-                            .append("<config>")
-                            .append("<modulation>")
-                            .append(modulation)
-                            .append("</modulation>")
-                            .append("</config>")
-                            .append("</optical-channel>");
-                }
-                sb.append("</component>").append("</components>");
-                return sb.toString();
-            } else {
-                log.error("Cannot process the component {}.", component.getClass());
-                return null;
-            }
-        }
-
-        private boolean setModulationRpc(PortNumber port, Object component, String editConfig) {
-            NetconfSession session = NetconfSessionUtility
-                    .getNetconfSession(cassini.getDeviceId(), cassini.getController());
-            checkNotNull(session);
-            boolean response = true;
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<edit-config>")
-                    .append("<target><running/></target>")
-                    .append("<config>")
-                    .append(editConfig)
-                    .append("</config>")
-                    .append("</edit-config>")
-                    .append(RPC_CLOSE_TAG);
-            log.info("RPC call for Setting Modulation : {}", rpcReq.toString());
-            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
-            if (xconf == null) {
-                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
-                        port.toString(), component.toString());
-            } else if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
-                    // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
-                response = false;
-                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
-                        port.toString(), component.toString());
-            }
-            return response;
-        }
-    }
-
-
-}
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
index 53b56db..fb9c090 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOcNos.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2018-present Open Networking Foundation
+ * Copyright 2019-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.
@@ -17,143 +17,77 @@
  */
 package org.onosproject.drivers.odtn;
 
-import org.apache.commons.configuration.HierarchicalConfiguration;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onosproject.drivers.utilities.XmlConfigParser;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.ModulationScheme;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ModulationConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.netconf.NetconfController;
-import org.onosproject.netconf.NetconfDevice;
-import org.onosproject.netconf.NetconfException;
-import org.onosproject.netconf.NetconfSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 /*
  * Driver Implementation of the ModulationConfig for OcNos based terminal devices.
  */
-public class CassiniModulationOcNos<T> extends AbstractHandlerBehaviour implements ModulationConfig<T> {
+public class CassiniModulationOcNos<T> extends TerminalDeviceModulationConfig<T> {
 
 
-    private static final String RPC_TAG_NETCONF_BASE =
-            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
-
-    private static final String RPC_CLOSE_TAG = "</rpc>";
-
-    private static final Logger log = LoggerFactory.getLogger(CassiniModulationOcNos.class);
-
-    private ComponentType state = ComponentType.DIRECTION;
+    private static Logger log = LoggerFactory.getLogger(CassiniModulationOcNos.class);
 
 
-    enum BitRate {
-        GBPS_200(200),      // 200 Gbps
-        GBPS_100(100),        // 100 Gbps
-        GBPS_40(40),          // 40 Gbps
-        GBPS_10(10);          // 10 Gbps
-
-        private final long value;
-
-        public long getValue() {
-            return value;
-        }
-
-        BitRate(long value) {
-            this.value = value;
-        }
-    }
 
     /**
-     * Returns the NetconfSession with the device for which the method was called.
+     * Construct a rpc target power message.
      *
-     * @param deviceId device indetifier
-     * @return The netconf session or null
+     * @param name for optical channel name
+     * @return RPC payload
      */
+    @Override
+    public StringBuilder createModulationFilterRequestRpc(String name) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<name>").append(name).append("</name>");
+        return rpc;
+    }
 
+    @Override
+    public void setModulationSchemeProcessor(PortNumber port, Object component, long bitRate) {
+        String modulation = null;
+        String editConfig = null;
+        if (bitRate <= TerminalDeviceModulationConfig.BitRate.GBPS_100.value) {
+            modulation = "dp_qpsk";
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation);
+            //setting the modulation by calling rpc
+            state.setModulationRpc(port, component, editConfig);
+        } else { // check if bitrate is greater than 100 Gig
+            modulation = "dp_16qam";
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation);
+            //setting the modulation by calling rpc
+            state.setModulationRpc(port, component, editConfig);
+        }
 
-    private NetconfSession getNetconfSession(DeviceId deviceId) {
-        log.info("Inside getNetconfSession () method for device : {}", deviceId);
-        NetconfController controller = handler().get(NetconfController.class);
-        NetconfDevice ncdev = controller.getDevicesMap().get(deviceId);
-        if (ncdev == null) {
-            log.trace("No netconf device, returning null session");
+    }
+
+    @Override
+    public String modulationEditConfigRequestRpc(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber,
+                                                 Object component, long bitRate, String modulation) {
+        if (component != null) {
+            String portName = state.ocName(modulationConfig, portNumber); //oc1/1
+            String slotName = portName.split("/")[0]; //get oc1
+            String slotIndex = slotName.substring(slotName.length() - 1); //then just 1
+            String netIndex = portName.split("/")[1]; //get 1 after the /
+            StringBuilder sb = new StringBuilder("<cmmOpticalControllerTable " +
+                                                         "xmlns=\"http://www.ipinfusion.com/CMLSchema/zebos\">");
+            sb.append("<slotIndex>").append(slotIndex).append("</slotIndex>");
+            if (modulation != null) {
+                // This is an edit-config operation.
+                sb.append("<cmmOpticalChannelInterfaceTable>")
+                        .append("<netIndex>").append(netIndex).append("<netIndex>")
+                        .append("<modulationFormat>")
+                        .append(modulation)
+                        .append("</modulationFormat>")
+                        .append("</cmmOpticalNetworkInterfaceTable>");
+            }
+            sb.append("</cmmOpticalControllerTable>");
+            return sb.toString();
+        } else {
+            log.error("Cannot process the component {}.", component.getClass());
             return null;
         }
-        return ncdev.getSession();
-    }
-
-    /*
-     *
-     * Get the deviceId for which the methods apply.
-     *
-     * @return The deviceId as contained in the handler data
-     */
-
-
-    private DeviceId did() {
-        return handler().data().deviceId();
-    }
-
-    /**
-     * Execute RPC request.
-     *
-     * @param session Netconf session
-     * @param message Netconf message in XML format
-     * @return XMLConfiguration object
-     */
-
-    private XMLConfiguration executeRpc(NetconfSession session, String message) {
-        try {
-            CompletableFuture<String> fut = session.rpc(message);
-            String rpcReply = fut.get();
-            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
-            xconf.setExpressionEngine(new XPathExpressionEngine());
-            return xconf;
-        } catch (NetconfException ne) {
-            log.error("Exception on Netconf protocol: {}.", ne);
-        } catch (InterruptedException ie) {
-            log.error("Interrupted Exception: {}.", ie);
-        } catch (ExecutionException ee) {
-            log.error("Concurrent Exception while executing Netconf operation: {}.", ee);
-        }
-        return null;
-    }
-
-    /**
-     * Get the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @return ModulationScheme as per bitRate value
-     **/
-    @Override
-    public Optional<ModulationScheme> getModulationScheme(PortNumber port, T component) {
-        checkState(component);
-        return state.getModulationScheme(port, component);
-    }
-
-    /**
-     * Set the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @param bitRate   bit rate in bps
-     **/
-    @Override
-    public void setModulationScheme(PortNumber port, T component, long bitRate) {
-        checkState(component);
-        state.setModulationScheme(port, component, bitRate);
     }
 
     /*
@@ -165,10 +99,10 @@
         String clsName = component.getClass().getName();
         switch (clsName) {
             case "org.onosproject.net.Direction":
-                state = CassiniModulationOcNos.ComponentType.DIRECTION;
+                state = ComponentType.DIRECTION;
                 break;
             case "org.onosproject.net.OchSignal":
-                state = CassiniModulationOcNos.ComponentType.OCHSIGNAL;
+                state = ComponentType.OCHSIGNAL;
                 break;
             default:
                 log.error("Cannot parse the component type {}.", clsName);
@@ -179,216 +113,5 @@
         log.info("Setting the state with clsName :{} ", clsName);
     }
 
-    /*
-     *
-     * Component type.
-     */
-
-
-    enum ComponentType {
-
-        /*
-         *
-         * Direction.
-         */
-
-
-        DIRECTION() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                log.info("Inside the enum setModulationScheme()");
-                super.setModulationScheme(port, component, bitRate);
-            }
-        },
-
-        /**
-         * OchSignal.
-         */
-
-
-        OCHSIGNAL() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                super.setModulationScheme(port, component, bitRate);
-            }
-        };
-
-
-        CassiniModulationOcNos cassini;
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @return target modulation
-         */
-        Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-            NetconfSession session = cassini.getNetconfSession(cassini.did());
-            checkNotNull(session);
-            String filter = createModulationFilter(cassini, port);
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<get>")
-                    .append("<filter type='subtree'>")
-                    .append(filter)
-                    .append("</filter>")
-                    .append("</get>")
-                    .append(RPC_CLOSE_TAG);
-            log.info("RPC Call for Getting Modulation : \n {}", rpcReq.toString());
-            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/config");
-
-                String modulationScheme = String.valueOf(config.getString("modulation"));
-                /*Used for Internal Testing */
-                //String modulationScheme="DP16QAM";
-                ModulationScheme modulation = ModulationScheme.valueOf(modulationScheme);
-                return Optional.of(modulation);
-            } catch (IllegalArgumentException e) {
-                return Optional.empty();
-            }
-        }
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @param power target value
-         */
-        void setModulationScheme(PortNumber port, Object component, long bitRate) {
-
-            ModulationScheme modulation = null;
-            String editConfig = null;
-
-            //check if bitrate is less than equal to 100 Gig
-            if (bitRate <= BitRate.GBPS_100.value) {
-                modulation = ModulationScheme.DP_QPSK;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                setModulationRpc(port, component, editConfig);
-            } else { // check if bitrate is greater than 100 Gig
-                modulation = ModulationScheme.DP_16QAM;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                setModulationRpc(port, component, editConfig);
-            }
-
-
-        }
-
-        private static String createModulationFilter(CassiniModulationOcNos modulationConfig, PortNumber portNumber) {
-            String name = ocName(modulationConfig, portNumber);
-            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
-            sb.append("<component>").append("<name>").append(name).append("</name>");
-            sb.append("</component>").append("</components>");
-            return sb.toString();
-        }
-
-        /**
-         * Extract component name from portNumber's annotations.
-         *
-         * @param pc         modulation config instance
-         * @param portNumber the port number
-         * @return the component name
-         */
-
-
-        private static String ocName(CassiniModulationOcNos pc, PortNumber portNumber) {
-            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
-            DeviceId deviceId = pc.handler().data().deviceId();
-            return deviceService.getPort(deviceId, portNumber).annotations().value("oc-name");
-        }
-
-        /*
-         *
-         * Parse filtering string from port and component.
-         * @param portNumber Port Number
-         * @param component port component (optical-channel)
-         * @param bitRate bitRate in bps
-         * @return filtering string in xml format
-
-         */
-        private String modulationEditConfig(CassiniModulationOcNos modulationConfig, PortNumber portNumber,
-                                            Object component, long bitRate, String modulation) {
-            /*
-            <cmmOpticalControllerTable xmlns="http://www.ipinfusion.com/CMLSchema/zebos">
-                <slotIndex>1</slotIndex>   ==============>> optical-module-slot
-                <cmmOpticalChannelInterfaceTable>
-                    <netIndex>0</netIndex>    =============>> optical-channel-number (Reference to line-port)
-                    <modulationFormat>dp-qpsk</modulationFormat>
-                 </cmmOpticalNetworkInterfaceTable>
-            </cmmOpticalControllerTable>
-             */
-            String modulationOcNos = convertToOcNosModulation(modulation);
-            if (component != null) {
-                String portName = ocName(modulationConfig, portNumber); //oc1/1
-                String slotName = portName.split("/")[0]; //get oc1
-                String slotIndex = slotName.substring(slotName.length() - 1); //then just 1
-                String netIndex = portName.split("/")[1]; //get 1 after the /
-                StringBuilder sb = new StringBuilder("<cmmOpticalControllerTable " +
-                        "xmlns=\"http://www.ipinfusion.com/CMLSchema/zebos\">");
-                sb.append("<slotIndex>").append(slotIndex).append("</slotIndex>");
-                if (modulation != null) {
-                    // This is an edit-config operation.
-                    sb.append("<cmmOpticalChannelInterfaceTable>")
-                            .append("<netIndex>").append(netIndex).append("<netIndex>")
-                            .append("<modulationFormat>")
-                            .append(modulationOcNos)
-                            .append("</modulationFormat>")
-                            .append("</cmmOpticalNetworkInterfaceTable>");
-                }
-                sb.append("</cmmOpticalControllerTable>");
-                return sb.toString();
-            } else {
-                log.error("Cannot process the component {}.", component.getClass());
-                return null;
-            }
-        }
-
-        private String convertToOcNosModulation(String modulation) {
-            if (modulation.equals(ModulationScheme.DP_QPSK.name())) {
-                return "dp_qpsk";
-            } else {
-                return "dp_16qam";
-            }
-        }
-
-        private boolean setModulationRpc(PortNumber port, Object component, String editConfig) {
-            NetconfSession session = cassini.getNetconfSession(cassini.did());
-            checkNotNull(session);
-            boolean response = true;
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<edit-config>")
-                    .append("<target><running/></target>")
-                    .append("<config>")
-                    .append(editConfig)
-                    .append("</config>")
-                    .append("</edit-config>")
-                    .append(RPC_CLOSE_TAG);
-            log.info("RPC call for Setting Modulation : {}", rpcReq.toString());
-            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
-
-            // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
-            if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
-                response = false;
-                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
-                        port.toString(), component.toString());
-            }
-            return response;
-        }
-    }
-
 
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
index d848379..bb82685 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/CassiniModulationOpenConfig.java
@@ -17,168 +17,132 @@
  */
 package org.onosproject.drivers.odtn;
 
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.commons.configuration.HierarchicalConfiguration;
-import org.apache.commons.configuration.XMLConfiguration;
-import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
-import org.onlab.osgi.DefaultServiceDirectory;
-import org.onosproject.drivers.utilities.XmlConfigParser;
-import org.onosproject.net.DeviceId;
+
 import org.onosproject.net.ModulationScheme;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.behaviour.ModulationConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.netconf.DatastoreId;
-import org.onosproject.netconf.NetconfController;
-import org.onosproject.netconf.NetconfDevice;
-import org.onosproject.netconf.NetconfException;
-import org.onosproject.netconf.NetconfSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import java.io.StringWriter;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 /*
  * Driver Implementation of the ModulationConfig for OcNos standard open config based terminal devices.
  */
-public class CassiniModulationOpenConfig<T> extends AbstractHandlerBehaviour implements ModulationConfig<T> {
+public class CassiniModulationOpenConfig<T> extends TerminalDeviceModulationConfig<T> {
 
+    public static Logger log = LoggerFactory.getLogger(CassiniModulationOpenConfig.class);
 
-    private static final String RPC_TAG_NETCONF_BASE =
-            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
-
-    private static final String RPC_CLOSE_TAG = "</rpc>";
-
-    private static final Logger log = LoggerFactory.getLogger(CassiniModulationOpenConfig.class);
-
-    private ComponentType state = ComponentType.DIRECTION;
-
-
-    enum BitRate {
-        GBPS_200(200),      // 200 Gbps
-        GBPS_100(100),        // 100 Gbps
-        GBPS_40(40),          // 40 Gbps
-        GBPS_10(10);          // 10 Gbps
-
-        private final long value;
-
-        public long getValue() {
-            return value;
-        }
-
-        BitRate(long value) {
-            this.value = value;
-        }
+    /**
+     * Construct a rpc target power message.
+     *
+     * @param filter to build rpc
+     * @return RPC payload
+     */
+    @Override
+    public StringBuilder getModulationSchemeRequestRpc(String filter) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<get-config>")
+                .append("<source>")
+                .append("<" + DatastoreId.RUNNING + "/>")
+                .append("</source>")
+                .append("<filter type='subtree'>")
+                .append(filter)
+                .append("</filter>")
+                .append("</get-config>");
+        return rpc;
     }
 
     /**
-     * Returns the NetconfSession with the device for which the method was called.
+     * Construct a rpc target power message.
      *
-     * @param deviceId device indetifier
-     * @return The netconf session or null
+     * @return RPC payload
      */
+    @Override
+    public DatastoreId getDataStoreId() {
+        return DatastoreId.CANDIDATE;
+    }
 
-
-    private NetconfSession getNetconfSession(DeviceId deviceId) {
-        NetconfController controller = handler().get(NetconfController.class);
-        NetconfDevice ncdev = controller.getDevicesMap().get(deviceId);
-        if (ncdev == null) {
-            log.trace("No netconf device, returning null session");
-            return null;
-        }
-        return ncdev.getSession();
+    /**
+     * Construct a rpc target power message.
+     *
+     * @param name for optical channel name
+     * @return RPC payload
+     */
+    @Override
+    public StringBuilder createModulationFilterRequestRpc(String name) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<name>").append(name).append("</name>");
+        return rpc;
     }
 
     /*
      *
-     * Get the deviceId for which the methods apply.
-     *
-     * @return The deviceId as contained in the handler data
+     * Parse filtering string from port and component.
+     * @param portNumber Port Number
+     * @param component port component (optical-channel)
+     * @param bitRate bitRate in bps
+     * @return filtering string in xml format
+
      */
-
-
-    private DeviceId did() {
-        return handler().data().deviceId();
-    }
-
-    /**
-     * Execute RPC request.
-     *
-     * @param session Netconf session
-     * @param message Netconf message in XML format
-     * @return XMLConfiguration object
-     */
-
-    private XMLConfiguration executeRpc(NetconfSession session, String message) {
-        try {
-            if (log.isDebugEnabled()) {
-                try {
-                    StringWriter stringWriter = new StringWriter();
-                    XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(message);
-                    xconf.setExpressionEngine(new XPathExpressionEngine());
-                    xconf.save(stringWriter);
-                    log.debug("Request {}", stringWriter.toString());
-                } catch (ConfigurationException e) {
-                    log.error("XML Config Exception ", e);
-                }
-            }
-            CompletableFuture<String> fut = session.rpc(message);
-            String rpcReply = fut.get();
-            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
-            xconf.setExpressionEngine(new XPathExpressionEngine());
-            if (log.isDebugEnabled()) {
-                try {
-                    StringWriter stringWriter = new StringWriter();
-                    xconf.save(stringWriter);
-                    log.debug("Response {}", stringWriter.toString());
-                } catch (ConfigurationException e) {
-                    log.error("XML Config Exception ", e);
-                }
-            }
-            return xconf;
-        } catch (NetconfException ne) {
-            log.error("Exception on Netconf protocol: {}.", ne);
-        } catch (InterruptedException ie) {
-            log.error("Interrupted Exception: {}.", ie);
-        } catch (ExecutionException ee) {
-            log.error("Concurrent Exception while executing Netconf operation: {}.", ee);
+    @Override
+    public String modulationEditConfigRequestRpc(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber,
+                                                 Object component, long bitRate, String modulation) {
+        if (component != null) {
+            // This is an edit-config operation.
+            String portName = state.ocName(modulationConfig, portNumber); //oc1/0
+            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
+            sb.append("<component>");
+            sb.append("<name>").append(portName).append("</name>");
+            sb.append("<config>");
+            sb.append("<name>").append(portName).append("</name>");
+            sb.append("</config>");
+            sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
+                    .append("<config>")
+                    .append("<modulation-format>")
+                    .append(modulation)
+                    .append("</modulation-format>")
+                    .append("</config>")
+                    .append("</optical-channel>");
+            sb.append("</component>");
+            sb.append("</components>");
+            return sb.toString();
+        } else {
+            log.error("Cannot process the component {}.", component.getClass());
+            return null;
         }
-        return null;
     }
 
-    /**
-     * Get the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @return ModulationScheme as per bitRate value
-     **/
     @Override
-    public Optional<ModulationScheme> getModulationScheme(PortNumber port, T component) {
-        checkState(component);
-        return state.getModulationScheme(port, component);
+    public void setModulationSchemeProcessor(PortNumber port, Object component, long bitRate) {
+        String modulation = null;
+        String editConfig = null;
+        if (bitRate <= BitRate.GBPS_100.value) {
+            modulation = "dp_qpsk";
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation);
+            //setting the modulation by calling rpc
+            state.setModulationRpc(port, component, editConfig);
+        } else { // check if bitrate is greater than 100 Gig
+            modulation = "dp_16qam";
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation);
+            //setting the modulation by calling rpc
+            state.setModulationRpc(port, component, editConfig);
+        }
+
     }
 
-    /**
-     * Set the target Modulation Scheme on the component.
-     *
-     * @param port      the port
-     * @param component the port component
-     * @param bitRate   bit rate in bps
-     **/
     @Override
-    public void setModulationScheme(PortNumber port, T component, long bitRate) {
-        checkState(component);
-        state.setModulationScheme(port, component, bitRate);
+    public ModulationScheme modulationSchemeType(String modulationScheme) {
+        /*Used for Internal Testing */
+        //String modulationScheme="DP16QAM";
+        ModulationScheme modulation;
+        if (modulationScheme.equalsIgnoreCase("dp-16-qam")) {
+            modulation = ModulationScheme.DP_16QAM;
+        } else if (modulationScheme.equalsIgnoreCase("dp-8-qam")) {
+            modulation = ModulationScheme.DP_8QAM;
+        } else {
+            modulation = ModulationScheme.DP_QPSK;
+        }
+        return modulation;
     }
 
-
     /*
      *
      * Set the ComponentType to invoke proper methods for different template T.
@@ -188,10 +152,10 @@
         String clsName = component.getClass().getName();
         switch (clsName) {
             case "org.onosproject.net.Direction":
-                state = CassiniModulationOpenConfig.ComponentType.DIRECTION;
+                state = ComponentType.DIRECTION;
                 break;
             case "org.onosproject.net.OchSignal":
-                state = CassiniModulationOpenConfig.ComponentType.OCHSIGNAL;
+                state = ComponentType.OCHSIGNAL;
                 break;
             default:
                 log.error("Cannot parse the component type {}.", clsName);
@@ -200,244 +164,4 @@
 
         state.cassini = this;
     }
-
-    /*
-     *
-     * Component type.
-     */
-
-
-    enum ComponentType {
-
-        /*
-         *
-         * Direction.
-         */
-
-
-        DIRECTION() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                log.info("Inside the enum setModulationScheme()");
-                super.setModulationScheme(port, component, bitRate);
-            }
-        },
-
-        /**
-         * OchSignal.
-         */
-
-
-        OCHSIGNAL() {
-            @Override
-            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-                return super.getModulationScheme(port, component);
-            }
-
-            @Override
-            void setModulationScheme(PortNumber port, Object component, long bitRate) {
-                super.setModulationScheme(port, component, bitRate);
-            }
-        };
-
-
-        CassiniModulationOpenConfig cassini;
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @return target modulation
-         */
-        Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
-            NetconfSession session = cassini.getNetconfSession(cassini.did());
-            checkNotNull(session);
-            String filter = createModulationFilter(cassini, port);
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<get-config>")
-                    .append("<source>")
-                    .append("<" + DatastoreId.RUNNING + "/>")
-                    .append("</source>")
-                    .append("<filter type='subtree'>")
-                    .append(filter)
-                    .append("</filter>")
-                    .append("</get-config>")
-                    .append(RPC_CLOSE_TAG);
-            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
-            if (xconf == null) {
-                log.error("Error in executingRpc");
-                return Optional.empty();
-            }
-            try {
-                HierarchicalConfiguration config =
-                        xconf.configurationAt("data/components/component/optical-channel/config");
-
-                String modulationScheme = String.valueOf(config.getString("modulation-format"));
-                /*Used for Internal Testing */
-                //String modulationScheme="DP16QAM";
-                ModulationScheme modulation;
-                if (modulationScheme.equalsIgnoreCase("dp-16-qam")) {
-                    modulation = ModulationScheme.DP_16QAM;
-                } else if (modulationScheme.equalsIgnoreCase("dp-8-qam")) {
-                    modulation = ModulationScheme.DP_8QAM;
-                } else {
-                    modulation = ModulationScheme.DP_QPSK;
-                }
-                return Optional.of(modulation);
-            } catch (IllegalArgumentException e) {
-                log.error("Error in parsing config", e);
-                return Optional.empty();
-            }
-        }
-
-        /*
-         * mirror method in the internal class.
-         * @param port port
-         * @param component component
-         * @param power target value
-         */
-        void setModulationScheme(PortNumber port, Object component, long bitRate) {
-
-            ModulationScheme modulation = null;
-            String editConfig = null;
-
-            //check if bitrate is less than equal to 100 Gig
-            if (bitRate <= BitRate.GBPS_100.value) {
-                modulation = ModulationScheme.DP_QPSK;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                setModulationRpc(port, component, editConfig);
-            } else { // check if bitrate is greater than 100 Gig
-                modulation = ModulationScheme.DP_16QAM;
-                editConfig = modulationEditConfig(cassini, port, component, bitRate, modulation.name());
-                //setting the modulation by calling rpc
-                setModulationRpc(port, component, editConfig);
-            }
-
-
-        }
-
-        private static String createModulationFilter(CassiniModulationOpenConfig modulationConfig,
-                                                     PortNumber portNumber) {
-            String name = ocName(modulationConfig, portNumber);
-            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
-            sb.append("<component>").append("<name>").append(name).append("</name>");
-            sb.append("</component>").append("</components>");
-            return sb.toString();
-        }
-
-        /**
-         * Extract component name from portNumber's annotations.
-         *
-         * @param pc         modulation config instance
-         * @param portNumber the port number
-         * @return the component name
-         */
-
-
-        private static String ocName(CassiniModulationOpenConfig pc, PortNumber portNumber) {
-            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
-            DeviceId deviceId = pc.handler().data().deviceId();
-            return deviceService.getPort(deviceId, portNumber).annotations().value("oc-name");
-        }
-
-        /*
-         *
-         * Parse filtering string from port and component.
-         * @param portNumber Port Number
-         * @param component port component (optical-channel)
-         * @param bitRate bitRate in bps
-         * @return filtering string in xml format
-
-         */
-        private String modulationEditConfig(CassiniModulationOpenConfig modulationConfig, PortNumber portNumber,
-                                            Object component, long bitRate, String modulation) {
-            /*
-             <components xmlns="http://openconfig.net/yang/platform">
-               <component>
-                 <name>oc1/0</name>
-                 <config>
-                    <name>oc1/0</name>
-                 </config>
-                 <optical-channel xmlns="http://openconfig.net/yang/terminal-device">
-                   <config>
-                      <modulation-format>dp-16-qam</modulation-format>
-                   </config>
-                 </optical-channel>
-               </component>
-             </components>
-             */
-            String modulationOcNos = convertToOcNosModulation(modulation);
-            if (component != null) {
-                // This is an edit-config operation.
-                String portName = ocName(modulationConfig, portNumber); //oc1/0
-                StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
-                sb.append("<component>");
-                sb.append("<name>").append(portName).append("</name>");
-                sb.append("<config>");
-                sb.append("<name>").append(portName).append("</name>");
-                sb.append("</config>");
-                sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
-                        .append("<config>")
-                        .append("<modulation-format>")
-                        .append(modulationOcNos)
-                        .append("</modulation-format>")
-                        .append("</config>")
-                        .append("</optical-channel>");
-                sb.append("</component>");
-                sb.append("</components>");
-                return sb.toString();
-            } else {
-                log.error("Cannot process the component {}.", component.getClass());
-                return null;
-            }
-        }
-
-        private String convertToOcNosModulation(String modulation) {
-            if (modulation.equals(ModulationScheme.DP_QPSK.name())) {
-                return "dp-qpsk";
-            } else {
-                return "dp-16-qam";
-            }
-        }
-
-        private boolean setModulationRpc(PortNumber port, Object component, String editConfig) {
-            NetconfSession session = cassini.getNetconfSession(cassini.did());
-            checkNotNull(session);
-            boolean response = true;
-            StringBuilder rpcReq = new StringBuilder();
-            rpcReq.append(RPC_TAG_NETCONF_BASE)
-                    .append("<edit-config>")
-                    .append("<target><" + DatastoreId.CANDIDATE + "/></target>")
-                    .append("<config>")
-                    .append(editConfig)
-                    .append("</config>")
-                    .append("</edit-config>")
-                    .append(RPC_CLOSE_TAG);
-            log.info("RPC call for Setting Modulation : {}", rpcReq.toString());
-            XMLConfiguration xconf = cassini.executeRpc(session, rpcReq.toString());
-            if (xconf == null) {
-                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
-                        port.toString(), component.toString());
-            } else if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
-                // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
-                response = false;
-                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
-                        port.toString(), component.toString());
-            }
-            try {
-                session.commit();
-            } catch (NetconfException e) {
-                response = false;
-                log.error("error committing modulation changes");
-            }
-            return response;
-        }
-    }
 }
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/TerminalDeviceModulationConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/TerminalDeviceModulationConfig.java
new file mode 100644
index 0000000..5b8992f
--- /dev/null
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/TerminalDeviceModulationConfig.java
@@ -0,0 +1,503 @@
+/*
+ * Copyright 2019-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.
+ *
+ * This Work is contributed by Sterlite Technologies
+ */
+
+package org.onosproject.drivers.odtn;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.drivers.odtn.util.NetconfSessionUtility;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Direction;
+import org.onosproject.net.ModulationScheme;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.ModulationConfig;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.DatastoreId;
+import org.onosproject.netconf.NetconfController;
+import org.onosproject.netconf.NetconfException;
+import org.onosproject.netconf.NetconfSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Optional;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/*
+ * Driver Implementation of the ModulationConfig for OpenConfig terminal devices.
+ */
+public class TerminalDeviceModulationConfig<T> extends AbstractHandlerBehaviour implements ModulationConfig<T> {
+
+
+    public static final String RPC_TAG_NETCONF_BASE =
+            "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";
+
+    public static final String RPC_CLOSE_TAG = "</rpc>";
+
+    public static Logger log = LoggerFactory.getLogger(TerminalDeviceModulationConfig.class);
+
+    public TerminalDeviceModulationConfig.ComponentType state = ComponentType.DIRECTION;
+
+    private static final double OSNR_THRESHOLD_VALUE = 13.0;
+
+
+    public enum BitRate {
+        GBPS_200(200),      // 200 Gbps
+        GBPS_100(100),        // 100 Gbps
+        GBPS_40(40),          // 40 Gbps
+        GBPS_10(10);          // 10 Gbps
+
+        final long value;
+
+        public long getValue() {
+            return value;
+        }
+
+        BitRate(long value) {
+            this.value = value;
+        }
+    }
+
+    public NetconfController getController() {
+        return handler().get(NetconfController.class);
+    }
+
+    /*
+     *
+     * Get the deviceId for which the methods apply.
+     *
+     * @return The deviceId as contained in the handler data
+     */
+
+
+    public DeviceId getDeviceId() {
+        return handler().data().deviceId();
+    }
+
+    /**
+     * Construct a rpc target power message.
+     *
+     * @param filter to build rpc
+     * @return RPC payload
+     */
+    public StringBuilder getModulationSchemeRequestRpc(String filter) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<get>")
+                .append("<filter>")
+                .append(filter)
+                .append("</filter>")
+                .append("</get>");
+        return rpc;
+    }
+
+    /**
+     * Construct a rpc target power message.
+     *
+     * @return RPC payload
+     */
+    public DatastoreId getDataStoreId() {
+        return DatastoreId.RUNNING;
+    }
+
+    /**
+     * Construct a rpc target power message.
+     *
+     * @param name for optical channel name
+     * @return RPC payload
+     */
+    public StringBuilder createModulationFilterRequestRpc(String name) {
+        StringBuilder rpc = new StringBuilder();
+        rpc.append("<name>").append(name).append("</name>");
+        rpc.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">");
+        rpc.append("<config><modulation/></config>");
+        rpc.append("</optical-channel>");
+        return rpc;
+    }
+
+    /*
+     *
+     * Parse filtering string from port and component.
+     * @param portNumber Port Number
+     * @param component port component (optical-channel)
+     * @param bitRate bitRate in bps
+     * @return filtering string in xml format
+
+     */
+    public String modulationEditConfigRequestRpc(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber,
+                                                 Object component, long bitRate, String modulation) {
+        if (component != null) {
+            String portName = state.ocName(modulationConfig, portNumber);
+            //String channelSpacing = channelSpacing(modulationConfig,portNumber);
+            //ChannelSpacing cs= ChannelSpacing.valueOf(channelSpacing);
+            //double csValue= cs.frequency().asGHz();
+
+            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
+            sb.append("<component>").append("<name>").append(portName).append("</name>");
+            if (modulation != null) {
+                // This is an edit-config operation.
+                sb.append("<optical-channel xmlns=\"http://openconfig.net/yang/terminal-device\">")
+                        .append("<config>")
+                        .append("<modulation>")
+                        .append(modulation)
+                        .append("</modulation>")
+                        .append("</config>")
+                        .append("</optical-channel>");
+            }
+            sb.append("</component>").append("</components>");
+            return sb.toString();
+        } else {
+            log.error("Cannot process the component {}.", component.getClass());
+            return null;
+        }
+    }
+
+    public void setModulationSchemeProcessor(PortNumber port, Object component, long bitRate) {
+        ModulationScheme modulation = null;
+        String editConfig = null;
+        double osnr = 0.0;
+        boolean rpcResponse = false;
+        boolean receiver = false;
+
+        // TODO OSNR is valid only for receiver so need to modify
+            /*if(component.toString().equals(Direction.INGRESS.toString())){
+                receiver=true;
+            }*/
+
+        //check if bitrate is less than equal to 100 Gig
+        if (bitRate <= BitRate.GBPS_100.value) {
+            modulation = ModulationScheme.DP_QPSK;
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation.name());
+            //setting the modulation by calling rpc
+            rpcResponse = state.setModulationRpc(port, component, editConfig);
+            if (rpcResponse) {
+                // TODO OSNR is valid only for receiver so need to modify
+                osnr = state.fetchDeviceSnr(state.cassini, port);
+                if (osnr <= OSNR_THRESHOLD_VALUE) {
+                    log.error("Channel not possible for this OSNR Value : {}", osnr);
+                }
+            }
+        } else { // check if bitrate is greater than 100 Gig
+            modulation = ModulationScheme.DP_16QAM;
+            editConfig = state.modulationEditConfig(state.cassini, port, component, bitRate, modulation.name());
+            //setting the modulation by calling rpc
+            rpcResponse = state.setModulationRpc(port, component, editConfig);
+            if (rpcResponse) {
+                //TODO OSNR is valid only for receiver so need to modify
+                osnr =  state.fetchDeviceSnr(state.cassini, port);
+                if (osnr <= OSNR_THRESHOLD_VALUE) {
+                    modulation = ModulationScheme.DP_8QAM;
+                    editConfig =  state.modulationEditConfig(state.cassini, port, component, bitRate,
+                                                             modulation.name());
+                    //setting the modulation by calling rpc
+                    rpcResponse = state.setModulationRpc(port, component, editConfig);
+                    if (rpcResponse) {
+                        // TODO OSNR is valid only for receiver so need to modify
+                        osnr = state.fetchDeviceSnr(state.cassini, port);
+                        if (osnr <= OSNR_THRESHOLD_VALUE) {
+                            log.warn("Channel not possible for this OSNR Value : {}." +
+                                             " Please reduce the channel bitrate.", osnr);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public ModulationScheme modulationSchemeType(String modulationScheme) {
+        return ModulationScheme.valueOf(modulationScheme);
+    }
+
+    /**
+     * Get the target Modulation Scheme on the component.
+     *
+     * @param port      the port
+     * @param component the port component
+     * @return ModulationScheme as per bitRate value
+     **/
+    @Override
+    public Optional<ModulationScheme> getModulationScheme(PortNumber port, T component) {
+        checkType(component);
+        return state.getModulationScheme(port, component);
+    }
+
+    /**
+     * Set the target Modulation Scheme on the component.
+     *
+     * @param port      the port
+     * @param component the port component
+     * @param bitRate   bit rate in bps
+     **/
+    @Override
+    public void setModulationScheme(PortNumber port, T component, long bitRate) {
+        checkType(component);
+        state.setModulationScheme(port, component, bitRate);
+    }
+
+    /*
+     *
+     * Set the ComponentType to invoke proper methods for different template T.
+     * @param component the component.
+     */
+    void checkType(Object component) {
+        String clsName = component.getClass().getName();
+
+        if (component instanceof Direction) {
+            state = TerminalDeviceModulationConfig.ComponentType.DIRECTION;
+        } else if (component instanceof OchSignal) {
+            state = TerminalDeviceModulationConfig.ComponentType.OCHSIGNAL;
+        } else {
+            log.error("Cannot parse the component type {}.", clsName);
+        }
+
+
+        state.cassini = this;
+    }
+
+    /*
+     *
+     * Component type.
+     */
+
+
+    public enum ComponentType {
+
+        /*
+         *
+         * Direction.
+         */
+
+
+        DIRECTION() {
+            @Override
+            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
+                return super.getModulationScheme(port, component);
+            }
+
+            @Override
+            void setModulationScheme(PortNumber port, Object component, long bitRate) {
+                super.setModulationScheme(port, component, bitRate);
+            }
+        },
+
+        /**
+         * OchSignal.
+         */
+
+
+        OCHSIGNAL() {
+            @Override
+            Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
+                return super.getModulationScheme(port, component);
+            }
+
+            @Override
+            void setModulationScheme(PortNumber port, Object component, long bitRate) {
+                super.setModulationScheme(port, component, bitRate);
+            }
+        };
+
+
+        TerminalDeviceModulationConfig cassini;
+
+        /*
+         * mirror method in the internal class.
+         * @param port port
+         * @param component component
+         * @return target modulation
+         */
+        Optional<ModulationScheme> getModulationScheme(PortNumber port, Object component) {
+            NetconfSession session = NetconfSessionUtility
+                    .getNetconfSession(cassini.getDeviceId(), cassini.getController());
+            checkNotNull(session);
+            String filter = createModulationFilter(cassini, port);
+            StringBuilder rpcReq = new StringBuilder();
+            rpcReq.append(RPC_TAG_NETCONF_BASE)
+                    .append(cassini.getModulationSchemeRequestRpc(filter))
+                    .append(RPC_CLOSE_TAG);
+            log.debug("RPC Call for Getting Modulation : \n {}", rpcReq.toString());
+            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
+            if (xconf == null) {
+                log.error("Error in executingRpc");
+                return Optional.empty();
+            }
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("components/component/optical-channel/config");
+
+                String modulationScheme = String.valueOf(config.getString("modulation"));
+
+                return Optional.of(cassini.modulationSchemeType(modulationScheme));
+            } catch (IllegalArgumentException e) {
+                return Optional.empty();
+            }
+        }
+
+        /*
+         * mirror method in the internal class.
+         * @param port port
+         * @param component component
+         * @param power target value
+         */
+        void setModulationScheme(PortNumber port, Object component, long bitRate) {
+            cassini.setModulationSchemeProcessor(port, component, bitRate);
+        }
+
+
+        /*
+         * Get filtered content under <optical-channel><state>.
+         * @param pc power config instance
+         * @param port the port number
+         * @param underState the filter condition
+         * @return RPC reply
+         */
+
+        //RPC call for OSNR still not finalised, need to update Rpc once validated
+        public static XMLConfiguration getTerminalDeviceSnr(TerminalDeviceModulationConfig config, PortNumber port) {
+            NetconfSession session = NetconfSessionUtility
+                    .getNetconfSession(config.getDeviceId(), config.getController());
+            checkNotNull(session);
+            String name = ocName(config, port);
+            StringBuilder rpcReq = new StringBuilder(RPC_TAG_NETCONF_BASE);
+            rpcReq.append("<get><filter>")
+                    .append("<osnr xmlns=\"http://openconfig.net/yang/terminal-device\">")
+                    .append("<instant/>")
+                    .append("</osnr></filter></get>")
+                    .append(RPC_CLOSE_TAG);
+            log.info("RPC Call for Fetching OSNR :\n\n {}", rpcReq.toString());
+            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
+            return xconf;
+        }
+
+        public static String createModulationFilter(TerminalDeviceModulationConfig modulationConfig,
+                                                        PortNumber portNumber) {
+            String name = ocName(modulationConfig, portNumber);
+            StringBuilder sb = new StringBuilder("<components xmlns=\"http://openconfig.net/yang/platform\">");
+            sb.append("<component>")
+                    .append(modulationConfig.createModulationFilterRequestRpc(name));
+            sb.append("</component>").append("</components>");
+            return sb.toString();
+        }
+
+        /**
+         * Extract component name from portNumber's annotations.
+         *
+         * @param pc         modulation config instance
+         * @param portNumber the port number
+         * @return the component name
+         */
+
+
+        public static String ocName(TerminalDeviceModulationConfig pc, PortNumber portNumber) {
+            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+            DeviceId deviceId = pc.handler().data().deviceId();
+            return deviceService.getPort(deviceId, portNumber).annotations().value("oc-name");
+        }
+
+        private static String channelSpacing(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber) {
+            DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
+            DeviceId deviceId = modulationConfig.handler().data().deviceId();
+            String lambda = deviceService.getPort(deviceId, portNumber).annotations().value("lambda");
+
+            ObjectMapper mapper = new ObjectMapper();
+            String channelSpacing = "";
+            try {
+                JsonNode actualObj = mapper.readTree(lambda);
+                JsonNode csNode = actualObj.get("channelSpacing");
+                channelSpacing = csNode.asText();
+                log.info("Channel_Spacing : " + channelSpacing);
+
+            } catch (IOException e) {
+                log.error("Error while parsing Json");
+            }
+            return channelSpacing;
+
+        }
+
+        private double fetchDeviceSnr(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber) {
+            double osnr = 0.0;
+            XMLConfiguration xconf = getTerminalDeviceSnr(cassini, portNumber);
+            if (xconf == null) {
+                return osnr;
+            }
+            try {
+                HierarchicalConfiguration config =
+                        xconf.configurationAt("data/components/component/optical-channel/state/osnr");
+                osnr = Float.valueOf(config.getString("snr")).doubleValue();
+                return osnr;
+            } catch (IllegalArgumentException e) {
+                return osnr;
+            }
+        }
+        /*
+         *
+         * Parse filtering string from port and component.
+         * @param portNumber Port Number
+         * @param component port component (optical-channel)
+         * @param bitRate bitRate in bps
+         * @return filtering string in xml format
+
+         */
+
+        public String modulationEditConfig(TerminalDeviceModulationConfig modulationConfig, PortNumber portNumber,
+                                           Object component, long bitRate, String modulation) {
+            return cassini.modulationEditConfigRequestRpc(modulationConfig, portNumber, component, bitRate, modulation);
+        }
+
+        public boolean setModulationRpc(PortNumber port, Object component, String editConfig) {
+            NetconfSession session = NetconfSessionUtility
+                    .getNetconfSession(cassini.getDeviceId(), cassini.getController());
+            checkNotNull(session);
+            boolean response = true;
+            StringBuilder rpcReq = new StringBuilder();
+            rpcReq.append(RPC_TAG_NETCONF_BASE)
+                    .append("<edit-config>")
+                    .append("<target><" + cassini.getDataStoreId() + "/></target>")
+                    .append("<config>")
+                    .append(editConfig)
+                    .append("</config>")
+                    .append("</edit-config>")
+                    .append(RPC_CLOSE_TAG);
+            log.info("RPC call for Setting Modulation : {}", rpcReq.toString());
+            XMLConfiguration xconf = NetconfSessionUtility.executeRpc(session, rpcReq.toString());
+            if (xconf == null) {
+                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
+                        port.toString(), component.toString());
+            } else if (!xconf.getRoot().getChild(0).getName().equals("ok")) {
+                    // The successful reply should be "<rpc-reply ...><ok /></rpc-reply>"
+                response = false;
+                log.error("The <edit-config> operation to set target-modulation of Port({}:{}) is failed.",
+                        port.toString(), component.toString());
+            }
+            try {
+                session.commit();
+            } catch (NetconfException e) {
+                response = false;
+                log.error("error committing modulation changes");
+            }
+            return response;
+        }
+    }
+
+
+}
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/util/NetconfSessionUtility.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/util/NetconfSessionUtility.java
index 6c9500c..363e90d 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/util/NetconfSessionUtility.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/util/NetconfSessionUtility.java
@@ -18,6 +18,7 @@
 
 package org.onosproject.drivers.odtn.util;
 
+import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.XMLConfiguration;
 import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
 import org.onosproject.drivers.utilities.XmlConfigParser;
@@ -29,6 +30,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.StringWriter;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 
@@ -67,17 +69,37 @@
 
     public static XMLConfiguration executeRpc(NetconfSession session, String message) {
         try {
+            if (log.isDebugEnabled()) {
+                try {
+                    StringWriter stringWriter = new StringWriter();
+                    XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(message);
+                    xconf.setExpressionEngine(new XPathExpressionEngine());
+                    xconf.save(stringWriter);
+                    log.debug("Request {}", stringWriter.toString());
+                } catch (ConfigurationException e) {
+                    log.error("XML Config Exception ", e);
+                }
+            }
             CompletableFuture<String> fut = session.rpc(message);
             String rpcReply = fut.get();
             XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
             xconf.setExpressionEngine(new XPathExpressionEngine());
+            if (log.isDebugEnabled()) {
+                try {
+                    StringWriter stringWriter = new StringWriter();
+                    xconf.save(stringWriter);
+                    log.debug("Response {}", stringWriter.toString());
+                } catch (ConfigurationException e) {
+                    log.error("XML Config Exception ", e);
+                }
+            }
             return xconf;
         } catch (NetconfException ne) {
             log.error("Exception on Netconf protocol: {}.", ne);
         } catch (InterruptedException ie) {
             log.error("Interrupted Exception: {}.", ie);
         } catch (ExecutionException ee) {
-            log.error("Concurrent Exception while executing Netconf operation: {}.", ee.getCause());
+            log.error("Concurrent Exception while executing Netconf operation: {}.", ee);
         }
         return null;
     }
diff --git a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
index a32317a..7f1453f 100644
--- a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
+++ b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
@@ -134,7 +134,7 @@
         <behaviour api="org.onosproject.net.behaviour.PowerConfig"
                    impl="org.onosproject.drivers.odtn.CassiniTerminalDevicePowerConfigExt"/>
         <behaviour api="org.onosproject.net.behaviour.ModulationConfig"
-                   impl="org.onosproject.drivers.odtn.CassiniModulationConfig"/>
+                   impl="org.onosproject.drivers.odtn.TerminalDeviceModulationConfig"/>
     </driver>
     <driver name="nokia-1830" manufacturer="nokia" hwVersion="1830" swVersion="R10.1.1">
         <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"