Update TAPI Connectivity Service on port change 37/97437/30
authorJavier Errea <errea@eurecom.fr>
Mon, 2 Aug 2021 12:27:01 +0000 (14:27 +0200)
committerJavier Errea <errea@eurecom.fr>
Mon, 27 Jun 2022 10:12:41 +0000 (12:12 +0200)
- Update TAPI connections & connectivity service
  on topology update notification
- Update TAPI supported connectivity services (infrastructure)
- Update CEPs of connections
- Add tapiNetworkModelListener to TapiProvider class
- Refactor TAPI connection creation to include lower connections
- Add method for sending a notification on a TAPI topology update
- Refactor differentiation between SWITCH and MUXPDR connectivity
  service creation
- Refactor connectivity service creation when there is
  more than 1 ROADM between end points of the service

JIRA: TRNSPRTPCE-466
Change-Id: I95f7dfba0d9d01c48e60538b215890265d48cf19
Signed-off-by: errea <errea@eurecom.fr>
lighty/src/main/java/io/lighty/controllers/tpce/module/TransportPCEImpl.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/TapiStringConstants.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/ConnectivityUtils.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/connectivity/TapiConnectivityImpl.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/impl/TapiProvider.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiNetworkModelListenerImpl.java [new file with mode: 0644]
tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiPceListenerImpl.java
tapi/src/main/java/org/opendaylight/transportpce/tapi/topology/TapiNetworkModelServiceImpl.java
tapi/src/main/resources/OSGI-INF/blueprint/tapi-blueprint.xml
tapi/src/test/java/org/opendaylight/transportpce/tapi/provider/TapiProviderTest.java

index ef88bf77e81598a2dc3f74de3f7af0bf7b45c118..37a766d4facab32349ebf0eb6eefaac2fdcf5f02 100644 (file)
@@ -80,6 +80,7 @@ import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOper
 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperationsImpl;
 import org.opendaylight.transportpce.tapi.R2RTapiLinkDiscovery;
 import org.opendaylight.transportpce.tapi.impl.TapiProvider;
+import org.opendaylight.transportpce.tapi.listeners.TapiNetworkModelListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl;
@@ -212,26 +213,29 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP
             LOG.info("Creating tapi beans ...");
             TapiLink tapiLink = new TapiLink(networkTransaction);
             R2RTapiLinkDiscovery tapilinkDiscoveryImpl = new R2RTapiLinkDiscovery(networkTransaction,
-                deviceTransactionManager, tapiLink);
+                    deviceTransactionManager, tapiLink);
             TapiRendererListenerImpl tapiRendererListenerImpl = new TapiRendererListenerImpl(lightyServices
                     .getBindingDataBroker());
             TapiPceListenerImpl tapiPceListenerImpl = new TapiPceListenerImpl(lightyServices.getBindingDataBroker());
-            TapiServiceHandlerListenerImpl tapiServiceHandlerListener = new TapiServiceHandlerListenerImpl(lightyServices
-                    .getBindingDataBroker());
+            TapiServiceHandlerListenerImpl tapiServiceHandlerListener = new TapiServiceHandlerListenerImpl(
+                    lightyServices.getBindingDataBroker());
             TransportpceTapinetworkutilsService tapiNetworkutilsServiceImpl = new TapiNetworkUtilsImpl(
                     networkTransaction, tapiLink);
             TapiNetworkModelService tapiNetworkModelService = new TapiNetworkModelServiceImpl(
-                tapilinkDiscoveryImpl, networkTransaction, tapiLink);
+                    tapilinkDiscoveryImpl, networkTransaction, tapiLink,
+                    lightyServices.getBindingNotificationPublishService());
             TapiNetconfTopologyListener tapiNetConfTopologyListener =
                     new TapiNetconfTopologyListener(tapiNetworkModelService);
             TapiOrLinkListener orLinkListener = new TapiOrLinkListener(tapiLink, networkTransaction);
             TapiPortMappingListener tapiPortMappingListener =
-                new TapiPortMappingListener(tapiNetworkModelService);
+                    new TapiPortMappingListener(tapiNetworkModelService);
+            TapiNetworkModelListenerImpl tapiNetworkModelListenerImpl =
+                    new TapiNetworkModelListenerImpl(networkTransaction);
 
             tapiProvider = initTapi(lightyServices, servicehandler, networkTransaction, serviceDataStoreOperations,
-                tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl, tapiPceListenerImpl,
-                tapiRendererListenerImpl, tapiServiceHandlerListener, lightyServices.getNotificationService(),
-                orLinkListener);
+                    tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl,
+                    tapiPceListenerImpl, tapiRendererListenerImpl, tapiServiceHandlerListener,
+                    lightyServices.getNotificationService(), orLinkListener, tapiNetworkModelListenerImpl);
         }
         if (activateNbiNotification) {
             LOG.info("Creating nbi-notifications beans ...");
@@ -299,11 +303,13 @@ public class TransportPCEImpl extends AbstractLightyModule implements TransportP
                                   TransportpceTapinetworkutilsService tapiNetworkutilsServiceImpl,
                                   TapiPceListenerImpl pceListenerImpl, TapiRendererListenerImpl rendererListenerImpl,
                                   TapiServiceHandlerListenerImpl serviceHandlerListenerImpl,
-                                  NotificationService notificationService, TapiOrLinkListener orLinkListener) {
+                                  NotificationService notificationService, TapiOrLinkListener orLinkListener,
+                                  TapiNetworkModelListenerImpl tapiNetworkModelListenerImpl) {
         return new TapiProvider(lightyServices.getBindingDataBroker(), lightyServices.getRpcProviderService(),
             servicehandler, serviceDataStoreOperations, new TapiListener(), networkTransactionService,
             tapiNetConfTopologyListener, tapiPortMappingListener, tapiNetworkutilsServiceImpl, pceListenerImpl,
-            rendererListenerImpl, serviceHandlerListenerImpl, notificationService, orLinkListener);
+            rendererListenerImpl, serviceHandlerListenerImpl, notificationService, orLinkListener,
+            tapiNetworkModelListenerImpl);
     }
 
     private RendererProvider initRenderer(LightyServices lightyServices, TransportpceOlmService olmPowerServiceRpc,
index ffbb2d439bcefb614d0c02c364889b8194398954..52e97af26b7d6d902d2239e8c2dfa367ef258e8d 100644 (file)
@@ -42,6 +42,8 @@ public final class TapiStringConstants {
     public static final String JITTER_VALUE = "12345678";
     public static final String WANDER_VALUE = "12345678";
     public static final String QUEING_LATENCY_VALUE = "12345678";
+    public static final String TAPI_CONNECTION_UPDATE_ERROR = "Could not update TAPI connections";
+    public static final String TAPI_CONNECTION_READ_ERROR = "Could not read TAPI connection data";
 
     private TapiStringConstants() {
         // hiding the default constructor
index 392ae6d60736019cd6486a7e43d0a68a824c9b63..c88c5239c689c25cc09c859a790aaeac49fdfbcd 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.transportpce.tapi.connectivity;
 
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
@@ -119,7 +119,7 @@ import org.slf4j.LoggerFactory;
 public final class ConnectivityUtils {
 
     private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
-        .getBytes(Charset.forName("UTF-8"))).toString());
+        .getBytes(StandardCharsets.UTF_8)).toString());
     private static final Logger LOG = LoggerFactory.getLogger(ConnectivityUtils.class);
 
     private final ServiceDataStoreOperations serviceDataStoreOperations;
@@ -130,6 +130,9 @@ public final class ConnectivityUtils {
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
         connectionFullMap; // this variable is for complete connection objects
     private final NetworkTransactionService networkTransactionService;
+    private Connection topConnRdmRdm;
+    private Connection topConnXpdrXpdrPhtn;
+    private Connection topConnXpdrXpdrOdu;
 
     // TODO -> handle cases for which node id is ROADM-A1 and not ROADMA01 or XPDR-A1 and not XPDRA01
     public ConnectivityUtils(ServiceDataStoreOperations serviceDataStoreOperations,
@@ -140,6 +143,9 @@ public final class ConnectivityUtils {
         this.sipMap = sipMap;
         this.connectionFullMap = new HashMap<>();
         this.networkTransactionService = networkTransactionService;
+        this.topConnRdmRdm = null;
+        this.topConnXpdrXpdrPhtn = null;
+        this.topConnXpdrXpdrOdu = null;
     }
 
     public static ServiceCreateInput buildServiceCreateInput(GenericServiceEndpoint sepA, GenericServiceEndpoint sepZ) {
@@ -301,7 +307,7 @@ public final class ConnectivityUtils {
             .setAdministrativeState(AdministrativeState.UNLOCKED)
             .setOperationalState(OperationalState.ENABLED)
             .setLifecycleState(LifecycleState.INSTALLED)
-            .setUuid(new Uuid(UUID.nameUUIDFromBytes(service.getServiceName().getBytes(Charset.forName("UTF-8")))
+            .setUuid(new Uuid(UUID.nameUUIDFromBytes(service.getServiceName().getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setServiceLayer(mapServiceLayer(serviceAEnd.getServiceFormat(), endPoint1, endPoint2))
             .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY)
@@ -336,7 +342,7 @@ public final class ConnectivityUtils {
     private OpenroadmNodeType getOpenroadmType(String nodeName) {
         LOG.info("Node name = {}", nodeName);
         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",nodeName, TapiStringConstants.DSR))
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node tapiNode
             = this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid);
         if (tapiNode != null) {
@@ -348,10 +354,10 @@ public final class ConnectivityUtils {
 
     private Map<ConnectionKey, Connection> createConnectionsFromService(
             org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEnd
-                serviceAEnd,
+                    serviceAEnd,
             org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceZEnd
-                serviceZEnd,
-        PathDescription pathDescription) {
+                    serviceZEnd,
+            PathDescription pathDescription) {
         Map<ConnectionKey, Connection> connectionServMap = new HashMap<>();
         // build lists with ROADM nodes, XPDR/MUX/SWITCH nodes, ROADM DEG TTPs, ROADM SRG TTPs, XPDR CLIENT TTPs
         //  and XPDR NETWORK TTPs (if any). From the path description. This will help to build the uuid of the CEPs
@@ -364,7 +370,7 @@ public final class ConnectivityUtils {
         List<String> rdmNodelist = new ArrayList<>();
         List<String> xpdrNodelist = new ArrayList<>();
         for (AToZ elem:pathDescription.getAToZDirection().getAToZ().values().stream()
-            .sorted(Comparator.comparing(AToZ::getId)).collect(Collectors.toList())) {
+            .sorted((Comparator.comparing(atoz -> Integer.valueOf(atoz.getId())))).collect(Collectors.toList())) {
             resourceType = elem.getResource().getResource().implementedInterface().getSimpleName();
             switch (resourceType) {
                 case TapiStringConstants.TP:
@@ -466,11 +472,16 @@ public final class ConnectivityUtils {
                 // - XC Connection OTSi betwwen iOTSi y eOTSi of xpdr
                 // - Top connection OTSi between network ports of xpdrs in the Photonic media layer -> i_OTSi
                 connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
+                this.topConnRdmRdm = null;
                 break;
             case ODU:
+                // TODO: verify if this is correct
                 // - XC Connection OTSi betwwen iODU and eODU of xpdr
                 // - Top connection in the ODU layer, between xpdr eODU ports (?)
-                connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
+                if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
+                    connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
+                    this.topConnXpdrXpdrPhtn = null;
+                }
                 break;
             case Ethernet:
                 // Check if OC, OTU and ODU are created
@@ -479,23 +490,26 @@ public final class ConnectivityUtils {
                     connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
                         edgeRoadm1, edgeRoadm2));
                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
+                    this.topConnRdmRdm = null;
                     xpdrClientTplist = getAssociatedClientsPort(xpdrNetworkTplist);
                     LOG.info("Associated client ports = {}", xpdrClientTplist);
                     connectionServMap.putAll(createXpdrCepsAndConnectionsEth(xpdrClientTplist, xpdrNodelist,
                         connectionServMap));
+                    this.topConnXpdrXpdrPhtn = null;
                 }
                 if (openroadmNodeType.equals(OpenroadmNodeType.SWITCH)) {
                     // TODO: We create both ODU and DSR because there is no ODU service creation for the switch
                     // - XC Connection OTSi betwwen iODU and eODU of xpdr
                     // - Top connection in the ODU layer, between xpdr eODU ports (?)
-                    connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
                         xpdrNodelist));
+                    this.topConnXpdrXpdrPhtn = null;
                 }
                 if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
                     // TODO: OTN service but mux has 3 steps at rendering. Verify that things exist
                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
                         xpdrNodelist));
+                    this.topConnXpdrXpdrOdu = null;
                 }
                 break;
             default:
@@ -537,7 +551,7 @@ public final class ConnectivityUtils {
         // DSR top connection between edge xpdr CLIENT DSR
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
-            LayerProtocolName.DSR, xcMap);
+            LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
 
         // DSR top connection that will be added to the service object
@@ -598,7 +612,7 @@ public final class ConnectivityUtils {
 
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU,
-            LayerProtocolName.ODU, xcMap);
+            LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrOdu);
         this.connectionFullMap.put(connectionOdu.key(), connectionOdu);
 
         // ODU top connection that will be added to the service object
@@ -609,7 +623,7 @@ public final class ConnectivityUtils {
 
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
-                LayerProtocolName.DSR, xcMap);
+            LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
 
         // DSR top connection that will be added to the service object
@@ -649,12 +663,13 @@ public final class ConnectivityUtils {
             .get(xpdrNodelist.size() - 1))).findFirst().get();
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU,
-            LayerProtocolName.ODU, xcMap);
+            LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connection.key(), connection);
 
         // ODU top connection that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
+        this.topConnXpdrXpdrOdu = conn;
 
         return connServMap;
     }
@@ -709,13 +724,13 @@ public final class ConnectivityUtils {
             .get(xpdrNodelist.size() - 1))).findFirst().get();
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI,
-            LayerProtocolName.PHOTONICMEDIA, xcMap);
+            LayerProtocolName.PHOTONICMEDIA, xcMap, this.topConnRdmRdm);
         this.connectionFullMap.put(connection.key(), connection);
 
         // OTSi top connection that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
-
+        this.topConnXpdrXpdrPhtn = conn;
 
         return connServMap;
     }
@@ -724,106 +739,149 @@ public final class ConnectivityUtils {
                                                                          List<String> rdmDegTplist,
                                                                          List<String> rdmNodelist,
                                                                          String edgeRoadm1, String edgeRoadm2) {
-        // TODO: when the number of roadms between 2 SPDR/XPDR is more thatn 1, we need to refine this code
-        Map<ConnectionKey, Connection> connServMap = new HashMap<>();
+        // TODO: will need to check if things exist already or not
         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
             ConnectionEndPoint> cepMap = new HashMap<>();
-        Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
         // create ceps and x connections within roadm
+        Map<LowerConnectionKey, LowerConnection> xcLowerMap = new HashMap<>();
         for (String roadm : rdmNodelist) {
             LOG.info("Creating ceps and xc for roadm {}", roadm);
-            String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
-            LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
-            // There should be only 1 AD and 1 DEG per roadm
-            // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
-            //  3 different MC CEPs giving different IDs to show that they are different
-            // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
-            // created in the topology creation
-            // add CEPs to the topology to the corresponding ONEP
-            ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
-            ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
-            ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
-            cepMap.put(adCep1.key(), adCep1);
-            cepMap.put(adCep2.key(), adCep2);
-            cepMap.put(adCep3.key(), adCep3);
-
-            String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
-            LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
-
-            ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
-            ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
-            ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
-            cepMap.put(degCep1.key(), degCep1);
-            cepMap.put(degCep2.key(), degCep2);
-            cepMap.put(degCep3.key(), degCep3);
-
-            LOG.info("Going to create cross connections for ROADM {}", roadm);
-            // Create X connections between MC and OTSi_MC for full map
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection1 = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
-                LayerProtocolName.PHOTONICMEDIA);
-            LOG.info("Cross connection 1 created = {}", connection1);
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection2 = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
-                LayerProtocolName.PHOTONICMEDIA);
-            LOG.info("Cross connection 2 created = {}", connection2);
-            this.connectionFullMap.put(connection1.key(), connection1);
-            this.connectionFullMap.put(connection2.key(), connection2);
-
-            // Create X connections that will be added to the service object
-            LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
-            LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
-
-            xcMap.put(conn1.key(), conn1);
-            xcMap.put(conn2.key(), conn2);
-        }
-        LOG.info("Going to create top connections betwee roadms");
-        // create top connections between roadms: MC connections between AD MC CEPs of roadms
-        for (int i = 0; i < rdmNodelist.size(); i++) {
-            if (rdmNodelist.size() <= (i + 1)) {
-                LOG.info("Reached last roadm. No more MC connections");
-                break;
+            if (roadm.equals(edgeRoadm1) || roadm.equals(edgeRoadm2)) {
+                LOG.info("EDGE ROADM, cross connections needed between SRG and DEG");
+                String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
+                // There should be only 1 AD and 1 DEG per roadm
+                // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
+                //  3 different MC CEPs giving different IDs to show that they are different
+                // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
+                // created in the topology creation
+                // add CEPs to the topology to the corresponding ONEP
+                ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
+                ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
+                ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
+                cepMap.put(adCep1.key(), adCep1);
+                cepMap.put(adCep2.key(), adCep2);
+                cepMap.put(adCep3.key(), adCep3);
+
+                String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
+
+                ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
+                ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
+                ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
+                cepMap.put(degCep1.key(), degCep1);
+                cepMap.put(degCep2.key(), degCep2);
+                cepMap.put(degCep3.key(), degCep3);
+
+                LOG.info("Going to create cross connections for ROADM {}", roadm);
+                // Create X connections between MC and OTSi_MC for full map
+                org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
+                    = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
+                        LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 1 created = {}", connection1.toString());
+                org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
+                    = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
+                    LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 2 created = {}", connection2.toString());
+                this.connectionFullMap.put(connection1.key(), connection1);
+                this.connectionFullMap.put(connection2.key(), connection2);
+
+                // Create X connections that will be added to the service object
+                LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+                LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
+
+                xcLowerMap.put(conn1.key(), conn1);
+                xcLowerMap.put(conn2.key(), conn2);
+            } else {
+                LOG.info("MIDDLE ROADM, cross connections needed between DEG and DEG");
+                String spcRdmDEG1 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("Degree 1 port of ROADm {} = {}", roadm, spcRdmDEG1);
+
+                ConnectionEndPoint deg1Cep1 = createCepRoadm(spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA, deg1Cep1);
+                ConnectionEndPoint deg1Cep2 = createCepRoadm(spcRdmDEG1, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.MC, deg1Cep2);
+                ConnectionEndPoint deg1Cep3 = createCepRoadm(spcRdmDEG1, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.OTSI_MC, deg1Cep3);
+                cepMap.put(deg1Cep1.key(), deg1Cep1);
+                cepMap.put(deg1Cep2.key(), deg1Cep2);
+                cepMap.put(deg1Cep3.key(), deg1Cep3);
+
+                String spcRdmDEG2 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).skip(1).findFirst().get();
+                LOG.info("Degree 2 port of ROADm {} = {}", roadm, spcRdmDEG2);
+
+                ConnectionEndPoint deg2Cep1 = createCepRoadm(spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA, deg2Cep1);
+                ConnectionEndPoint deg2Cep2 = createCepRoadm(spcRdmDEG2, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.MC, deg2Cep2);
+                ConnectionEndPoint deg2Cep3 = createCepRoadm(spcRdmDEG2, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.OTSI_MC, deg2Cep3);
+                cepMap.put(deg2Cep1.key(), deg2Cep1);
+                cepMap.put(deg2Cep2.key(), deg2Cep2);
+                cepMap.put(deg2Cep3.key(), deg2Cep3);
+
+                LOG.info("Going to create cross connections for ROADM {}", roadm);
+                // Create X connections between MC and OTSi_MC for full map
+                org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
+                    = createXCBetweenCeps(deg1Cep2, deg2Cep2, spcRdmDEG1, spcRdmDEG2,
+                    TapiStringConstants.MC, LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 1 created = {}", connection1.toString());
+                org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
+                    = createXCBetweenCeps(deg1Cep3, deg2Cep3, spcRdmDEG1, spcRdmDEG2,
+                    TapiStringConstants.OTSI_MC, LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 2 created = {}", connection2.toString());
+                this.connectionFullMap.put(connection1.key(), connection1);
+                this.connectionFullMap.put(connection2.key(), connection2);
+
+                // Create X connections that will be added to the service object
+                LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+                LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
+
+                xcLowerMap.put(conn1.key(), conn1);
+                xcLowerMap.put(conn2.key(), conn2);
             }
-            // Current roadm with roadm i + 1 --> MC
-            String roadm1 = rdmNodelist.get(i);
-            String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm1)).findFirst().get();
-            String roadm2 = rdmNodelist.get(i + 1);
-            String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm2)).findFirst().get();
-            LOG.info("Creating top connection from {} to {} between tps: {}-{}", roadm1, roadm2, spcRdmAD1, spcRdmAD2);
-
-            // Create top connections between MC for full map
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
-                LayerProtocolName.PHOTONICMEDIA, xcMap);
-            this.connectionFullMap.put(connection.key(), connection);
-            LOG.info("Top connection created = {}", connection);
-
-            // Create top connections that will be added to the service object
-            Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
-            connServMap.put(conn.key(), conn);
-            LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
-            xcMap.put(conn1.key(), conn1);
         }
-
-        // OTSiMC top connection between edge roadms
-        LOG.info("Going to created top connection between OTSiMC");
+        LOG.info("Going to create top connections between roadms");
         String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm1)).findFirst().get();
         String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().get();
+        // MC top connection between edge roadms
+        LOG.info("Going to created top connection between MC");
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-            connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
-            LayerProtocolName.PHOTONICMEDIA, xcMap);
+            connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
+            LayerProtocolName.PHOTONICMEDIA, xcLowerMap, null);
         this.connectionFullMap.put(connection.key(), connection);
-        LOG.info("Top connection created = {}", connection);
+        LOG.info("Top connection created = {}", connection.toString());
 
+        Map<ConnectionKey, Connection> connServMap = new HashMap<>();
         // OTSiMC top connections that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
+        LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
+        Map<LowerConnectionKey, LowerConnection> topLowerMap = new HashMap<>();
+        topLowerMap.put(conn1.key(), conn1);
+
+        // OTSiMC top connection between edge roadms
+        LOG.info("Going to created top connection between OTSiMC");
+        org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
+            connection1 = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
+            LayerProtocolName.PHOTONICMEDIA, topLowerMap, null);
+        this.connectionFullMap.put(connection1.key(), connection1);
+        LOG.info("Top connection created = {}", connection1.toString());
+
+        // OTSiMC top connections that will be added to the service object
+        Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+        connServMap.put(conn2.key(), conn2);
+        this.topConnRdmRdm = conn2;
         return connServMap;
     }
 
@@ -832,14 +890,14 @@ public final class ConnectivityUtils {
                         Map<org.opendaylight.yang.gen.v1.urn
                             .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
                             ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol,
-                                Map<LowerConnectionKey, LowerConnection> xcMap) {
+                        Map<LowerConnectionKey, LowerConnection> xcMap, Connection additionalLowerConn) {
         // find cep for each AD MC of roadm 1 and 2
         LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual));
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 =
             cepMap.get(new org.opendaylight.yang.gen.v1.urn
                 .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp1.split("\\+")[0],
-                    qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                        qual, tp1.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                     .toString())));
         LOG.info("ADCEP1 = {}", adCep1);
         org.opendaylight.yang.gen.v1.urn
@@ -858,7 +916,7 @@ public final class ConnectivityUtils {
             cepMap.get(new org.opendaylight.yang.gen.v1.urn
                 .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp2.split("\\+")[0],
-                    qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                        qual, tp2.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                     .toString())));
         LOG.info("ADCEP2 = {}", adCep2);
         org.opendaylight.yang.gen.v1.urn
@@ -882,10 +940,14 @@ public final class ConnectivityUtils {
             .setValue(String.join("+", "TOP", tp1, tp2, qual))
             .build();
         // TODO: lower connection, supported link.......
+        if (additionalLowerConn != null) {
+            xcMap.putIfAbsent(new LowerConnectionKey(additionalLowerConn.getConnectionUuid()),
+                new LowerConnectionBuilder().setConnectionUuid(additionalLowerConn.getConnectionUuid()).build());
+        }
         return new org.opendaylight.yang.gen.v1.urn
             .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "TOP", tp1, tp2, qual))
-                .getBytes(Charset.forName("UTF-8"))).toString()))
+                .getBytes(StandardCharsets.UTF_8)).toString()))
             .setName(Map.of(connName.key(), connName))
             .setConnectionEndPoint(ceps)
             .setOperationalState(OperationalState.ENABLED)
@@ -939,7 +1001,7 @@ public final class ConnectivityUtils {
         return new org.opendaylight.yang.gen.v1.urn
             .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "XC", tp1, tp2, qual))
-                .getBytes(Charset.forName("UTF-8"))).toString()))
+                .getBytes(StandardCharsets.UTF_8)).toString()))
             .setName(Map.of(connName.key(), connName))
             .setConnectionEndPoint(ceps)
             .setOperationalState(OperationalState.ENABLED)
@@ -958,19 +1020,19 @@ public final class ConnectivityUtils {
             .build();
         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
-                qualifier)).getBytes(Charset.forName("UTF-8")))
+                    qualifier)).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
-                .getBytes(Charset.forName("UTF-8"))).toString()))
+                .getBytes(StandardCharsets.UTF_8)).toString()))
             .build();
         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
         // TODO: add parent ONEP??
         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
             .setName(Map.of(cepName.key(), cepName))
@@ -991,19 +1053,19 @@ public final class ConnectivityUtils {
             .build();
         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
-                nodeLayer)).getBytes(Charset.forName("UTF-8")))
+                    nodeLayer)).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
-                .getBytes(Charset.forName("UTF-8"))).toString()))
+                .getBytes(StandardCharsets.UTF_8)).toString()))
             .build();
         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
         // TODO: add parent ONEP??
         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(StandardCharsets.UTF_8))
                 .toString()))
             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
             .setName(Map.of(cepName.key(), cepName))
@@ -1016,8 +1078,8 @@ public final class ConnectivityUtils {
     }
 
     private EndPoint mapServiceZEndPoint(
-            org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceZEnd
-                serviceZEnd, PathDescription pathDescription) {
+        org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceZEnd
+            serviceZEnd, PathDescription pathDescription) {
         EndPointBuilder endPointBuilder = new EndPointBuilder();
         // 1. Service Format: ODU, OTU, ETH
         ServiceFormat serviceFormat = serviceZEnd.getServiceFormat();
@@ -1073,8 +1135,8 @@ public final class ConnectivityUtils {
     }
 
     private EndPoint mapServiceAEndPoint(
-            org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEnd
-                serviceAEnd, PathDescription pathDescription) {
+        org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.service.ServiceAEnd
+            serviceAEnd, PathDescription pathDescription) {
         EndPointBuilder endPointBuilder = new EndPointBuilder();
         // 1. Service Format: ODU, OTU, ETH
         ServiceFormat serviceFormat = serviceAEnd.getServiceFormat();
@@ -1136,7 +1198,7 @@ public final class ConnectivityUtils {
             ZToA firstElement = mapztoa.values().stream().filter(ztoa -> ztoa.getId().equals("0")).findFirst().get();
             TerminationPoint tp = (TerminationPoint) firstElement.getResource().getResource();
             Uuid sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                tp.getTpNodeId(), TapiStringConstants.MC, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
+                    tp.getTpNodeId(), TapiStringConstants.MC, tp.getTpId())).getBytes(StandardCharsets.UTF_8))
                 .toString());
             LOG.info("SIP name = {}", String.join("+", tp.getTpNodeId(), TapiStringConstants.MC, tp.getTpId()));
             for (ServiceInterfacePoint sip:this.sipMap.values()) {
@@ -1157,9 +1219,8 @@ public final class ConnectivityUtils {
                     firstElement = mapztoa.values().stream().filter(ztoa -> ztoa.getId().equals("2")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Network-Network ports --> iODU layer SIPs TODO --> updated to E_ODU
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.I_ODU, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.I_ODU, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("SIP name = {}", String.join("+", tp.getTpNodeId(), TapiStringConstants.I_ODU,
                         tp.getTpId()));
                     break;
@@ -1167,9 +1228,8 @@ public final class ConnectivityUtils {
                     firstElement = mapztoa.values().stream().filter(ztoa -> ztoa.getId().equals("2")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Network-Network ports --> iOTSi layer SIPs
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.I_OTSI, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.I_OTSI, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("SIP name = {}", String.join("+", tp.getTpNodeId(), TapiStringConstants.I_OTSI,
                         tp.getTpId()));
                     break;
@@ -1178,9 +1238,8 @@ public final class ConnectivityUtils {
                     firstElement = mapztoa.values().stream().filter(ztoa -> ztoa.getId().equals("0")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Client-client ports --> DSR layer SIPs
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.DSR, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.DSR, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("SIP name = {}", String.join("+", tp.getTpNodeId(), TapiStringConstants.DSR,
                         tp.getTpId()));
                     break;
@@ -1211,7 +1270,7 @@ public final class ConnectivityUtils {
             LOG.info("First element of service path = {}", firstElement.getResource().getResource());
             TerminationPoint tp = (TerminationPoint) firstElement.getResource().getResource();
             Uuid sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                tp.getTpNodeId(), TapiStringConstants.MC, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
+                    tp.getTpNodeId(), TapiStringConstants.MC, tp.getTpId())).getBytes(StandardCharsets.UTF_8))
                 .toString());
             LOG.info("ROADM SIP name = {}", String.join("+", tp.getTpNodeId(), TapiStringConstants.MC,
                 tp.getTpId()));
@@ -1233,9 +1292,8 @@ public final class ConnectivityUtils {
                     firstElement = mapatoz.values().stream().filter(atoz -> atoz.getId().equals("2")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Network-Network ports --> iODU layer SIPs. TODO -> updated to eODU
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.I_ODU, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.I_ODU, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("ODU XPDR SIP name = {}", String.join("+", tp.getTpNodeId(),
                         TapiStringConstants.I_ODU, tp.getTpId()));
                     break;
@@ -1243,9 +1301,8 @@ public final class ConnectivityUtils {
                     firstElement = mapatoz.values().stream().filter(atoz -> atoz.getId().equals("2")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Network-Network ports --> iOTSi layer SIPs
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.I_OTSI, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.I_OTSI, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("OTU XPDR SIP name = {}", String.join("+", tp.getTpNodeId(),
                         TapiStringConstants.I_OTSI, tp.getTpId()));
                     break;
@@ -1254,9 +1311,8 @@ public final class ConnectivityUtils {
                     firstElement = mapatoz.values().stream().filter(atoz -> atoz.getId().equals("0")).findFirst().get();
                     tp = (TerminationPoint) firstElement.getResource().getResource();
                     // Client-client ports --> DSR layer SIPs
-                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP",
-                        tp.getTpNodeId(), TapiStringConstants.DSR, tp.getTpId())).getBytes(Charset.forName("UTF-8")))
-                        .toString());
+                    sipUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "SIP", tp.getTpNodeId(),
+                            TapiStringConstants.DSR, tp.getTpId())).getBytes(StandardCharsets.UTF_8)).toString());
                     LOG.info("DSR XPDR SIP name = {}", String.join("+", tp.getTpNodeId(),
                         TapiStringConstants.DSR, tp.getTpId()));
                     break;
@@ -1281,11 +1337,11 @@ public final class ConnectivityUtils {
         LOG.info("Node of NEP id before Merge = {}", String.join("+", node, TapiStringConstants.PHTNC_MEDIA));
         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, TapiStringConstants.PHTNC_MEDIA)
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcRdmAD.split("\\+")[1])
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         this.tapiContext.updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
     }
 
@@ -1293,17 +1349,17 @@ public final class ConnectivityUtils {
                                              ConnectionEndPoint cep) {
         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, nodeLayer)
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcXpdrNet.split("\\+")[1])
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         this.tapiContext.updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
     }
 
     public Map<org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
+        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
+        org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
             getConnectionFullMap() {
         return this.connectionFullMap;
     }
@@ -1404,7 +1460,7 @@ public final class ConnectivityUtils {
         //  It could be obtained from the SIP which has the NEP and includes all the OR name.
         Uuid sipUuid = endPoint.getServiceInterfacePoint().getServiceInterfacePointUuid();
         // Todo -> need to find the NEP associated to that SIP
-        Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeZid.getBytes(Charset.forName("UTF-8"))).toString());
+        Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeZid.getBytes(StandardCharsets.UTF_8)).toString());
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node =
             this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid);
         if (node == null) {
@@ -1492,10 +1548,10 @@ public final class ConnectivityUtils {
         if (!serviceLayer.equals(LayerProtocolName.ETH)) {
             serviceZEndBuilder
                 .setEthernetAttributes(new EthernetAttributesBuilder().setSubrateEthSla(new SubrateEthSlaBuilder()
-                    .setCommittedBurstSize(Uint16.valueOf(64))
-                    .setCommittedInfoRate(Uint32.valueOf(100000))
-                    .build())
-                .build());
+                        .setCommittedBurstSize(Uint16.valueOf(64))
+                        .setCommittedInfoRate(Uint32.valueOf(100000))
+                        .build())
+                    .build());
         }
         return serviceZEndBuilder.build();
     }
@@ -1509,7 +1565,7 @@ public final class ConnectivityUtils {
         //  It could be obtained from the SIP which has the NEP and includes all the OR name.
         Uuid sipUuid = endPoint.getServiceInterfacePoint().getServiceInterfacePointUuid();
         // Todo -> need to find the NEP associated to that SIP
-        Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeAid.getBytes(Charset.forName("UTF-8"))).toString());
+        Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeAid.getBytes(StandardCharsets.UTF_8)).toString());
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node node =
             this.tapiContext.getTapiNode(this.tapiTopoUuid, nodeUuid);
         if (node == null) {
@@ -1552,11 +1608,11 @@ public final class ConnectivityUtils {
             .setServiceFormat(serviceFormat)
             .setServiceRate(Uint32.valueOf(capacity))
             .setEthernetAttributes(new EthernetAttributesBuilder().setSubrateEthSla(
-                        new org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.subrate.eth
-                            .sla.SubrateEthSlaBuilder()
-                    .setCommittedBurstSize(Uint16.valueOf(64))
-                    .setCommittedInfoRate(Uint32.valueOf(100000))
-                    .build())
+                    new org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev211210.subrate.eth
+                        .sla.SubrateEthSlaBuilder()
+                        .setCommittedBurstSize(Uint16.valueOf(64))
+                        .setCommittedInfoRate(Uint32.valueOf(100000))
+                        .build())
                 .build())
             .setTxDirection(Map.of(new TxDirectionKey(Uint8.ZERO), new TxDirectionBuilder()
                 .setPort(new PortBuilder()
@@ -1599,10 +1655,10 @@ public final class ConnectivityUtils {
         if (!serviceLayer.equals(LayerProtocolName.ETH)) {
             serviceAEndBuilder
                 .setEthernetAttributes(new EthernetAttributesBuilder().setSubrateEthSla(new SubrateEthSlaBuilder()
-                    .setCommittedBurstSize(Uint16.valueOf(64))
-                    .setCommittedInfoRate(Uint32.valueOf(100000))
-                    .build())
-                .build());
+                        .setCommittedBurstSize(Uint16.valueOf(64))
+                        .setCommittedInfoRate(Uint32.valueOf(100000))
+                        .build())
+                    .build());
         }
         return serviceAEndBuilder.build();
     }
@@ -1631,13 +1687,13 @@ public final class ConnectivityUtils {
 
     private ConnectionEndPoint getAssociatediODUCep(String spcXpdrNetwork) {
         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
-            TapiStringConstants.DSR).getBytes(Charset.forName("UTF-8")))).toString());
+            TapiStringConstants.DSR).getBytes(StandardCharsets.UTF_8))).toString());
         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
-                TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]).getBytes(Charset.forName("UTF-8"))))
+                TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]).getBytes(StandardCharsets.UTF_8)))
             .toString());
         Uuid cepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP",
             spcXpdrNetwork.split("\\+")[0], TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]))
-            .getBytes(Charset.forName("UTF-8"))).toString());
+            .getBytes(StandardCharsets.UTF_8)).toString());
         return this.tapiContext.getTapiCEP(this.tapiTopoUuid, nodeUuid, nepUuid, cepUuid);
     }
 
@@ -1686,7 +1742,7 @@ public final class ConnectivityUtils {
         List<OpenroadmNodeType> openroadmNodeTypeList = new ArrayList<>();
         for (String xpdrNode:xpdrNodelist) {
             Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",xpdrNode, TapiStringConstants.DSR))
-                .getBytes(Charset.forName("UTF-8"))).toString());
+                .getBytes(StandardCharsets.UTF_8)).toString());
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
                 .onf.otcc.yang.tapi.topology.rev181210.topology.Node> nodeIID = InstanceIdentifier.builder(
                     Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
@@ -1717,4 +1773,4 @@ public final class ConnectivityUtils {
         }
         return openroadmNodeTypeList.get(0);
     }
-}
+}
\ No newline at end of file
index bd7932f1378062465ede4a5f6c386a327f1c8603..a4499cf020941e187f28b448e679dfcbb56e746b 100644 (file)
@@ -183,6 +183,7 @@ public class TapiConnectivityImpl implements TapiConnectivityService {
             .setOperationalState(OperationalState.DISABLED)
             .setLifecycleState(LifecycleState.PLANNED)
             .setServiceLayer(input.getConnectivityConstraint().getServiceLayer())
+            .setServiceLevel(input.getConnectivityConstraint().getServiceLevel())
             .setServiceType(ServiceType.POINTTOPOINTCONNECTIVITY)
             .setConnectivityDirection(ForwardingDirection.BIDIRECTIONAL)
             .setName(Map.of(name.key(), name))
index fe0487234db9ac6cce3ac1df76344067511491ef..b68f43ccf5c26fb0c0c6a23b9248a211f4558ae1 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.transportpce.common.network.NetworkTransactionService;
 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
 import org.opendaylight.transportpce.tapi.connectivity.ConnectivityUtils;
 import org.opendaylight.transportpce.tapi.connectivity.TapiConnectivityImpl;
+import org.opendaylight.transportpce.tapi.listeners.TapiNetworkModelListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl;
@@ -82,6 +83,7 @@ public class TapiProvider {
     private ListenerRegistration<TransportpcePceListener> pcelistenerRegistration;
     private ListenerRegistration<TransportpceRendererListener> rendererlistenerRegistration;
     private ListenerRegistration<TransportpceServicehandlerListener> servicehandlerlistenerRegistration;
+    private ListenerRegistration<TapiNetworkModelListenerImpl> tapinetworkmodellistenerRegistration;
     private final OrgOpenroadmServiceService serviceHandler;
     private final ServiceDataStoreOperations serviceDataStoreOperations;
     private final TapiListener tapiListener;
@@ -94,6 +96,7 @@ public class TapiProvider {
     private TapiRendererListenerImpl rendererListenerImpl;
     private TapiServiceHandlerListenerImpl serviceHandlerListenerImpl;
     private final NotificationService notificationService;
+    private TapiNetworkModelListenerImpl tapiNetworkModelListenerImpl;
 
     public TapiProvider(DataBroker dataBroker, RpcProviderService rpcProviderService,
             OrgOpenroadmServiceService serviceHandler, ServiceDataStoreOperations serviceDataStoreOperations,
@@ -101,7 +104,8 @@ public class TapiProvider {
             TapiNetconfTopologyListener topologyListener, TapiPortMappingListener tapiPortMappingListener,
             TransportpceTapinetworkutilsService tapiNetworkUtils, TapiPceListenerImpl pceListenerImpl,
             TapiRendererListenerImpl rendererListenerImpl, TapiServiceHandlerListenerImpl serviceHandlerListenerImpl,
-            NotificationService notificationService, TapiOrLinkListener orLinkListener) {
+            NotificationService notificationService, TapiOrLinkListener orLinkListener,
+                        TapiNetworkModelListenerImpl tapiNetworkModelListenerImpl) {
         this.dataBroker = dataBroker;
         this.rpcProviderService = rpcProviderService;
         this.serviceHandler = serviceHandler;
@@ -116,6 +120,7 @@ public class TapiProvider {
         this.serviceHandlerListenerImpl = serviceHandlerListenerImpl;
         this.notificationService = notificationService;
         this.orLinkListener = orLinkListener;
+        this.tapiNetworkModelListenerImpl = tapiNetworkModelListenerImpl;
     }
 
     /**
@@ -161,6 +166,8 @@ public class TapiProvider {
         rendererlistenerRegistration = notificationService.registerNotificationListener(rendererListenerImpl);
         servicehandlerlistenerRegistration =
                 notificationService.registerNotificationListener(serviceHandlerListenerImpl);
+        tapinetworkmodellistenerRegistration =
+                notificationService.registerNotificationListener(tapiNetworkModelListenerImpl);
     }
 
     /**
@@ -184,5 +191,6 @@ public class TapiProvider {
         rendererlistenerRegistration.close();
         servicehandlerlistenerRegistration.close();
         rpcRegistration.close();
+        tapinetworkmodellistenerRegistration.close();
     }
 }
diff --git a/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiNetworkModelListenerImpl.java b/tapi/src/main/java/org/opendaylight/transportpce/tapi/listeners/TapiNetworkModelListenerImpl.java
new file mode 100644 (file)
index 0000000..995fee8
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Copyright Â© 2021 Nokia, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.transportpce.tapi.listeners;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.transportpce.common.network.NetworkTransactionService;
+import org.opendaylight.transportpce.tapi.TapiStringConstants;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.AdministrativeState;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnection;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NameAndValueChange;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.Notification;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NotificationType;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.ObjectType;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.TapiNotificationListener;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.NodeEdgePointRef;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.Enumeration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TapiNetworkModelListenerImpl implements TapiNotificationListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TapiNetworkModelListenerImpl.class);
+    private final NetworkTransactionService networkTransactionService;
+    private final List<ConnectivityService> connectivityServiceChanges = new ArrayList<>();
+    private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
+            .getBytes(StandardCharsets.UTF_8)).toString());
+    private final List<LayerProtocolName> orderedServiceLayerList;
+
+
+    public TapiNetworkModelListenerImpl(NetworkTransactionService networkTransactionService) {
+        this.networkTransactionService = networkTransactionService;
+        this.orderedServiceLayerList = List.of(LayerProtocolName.PHOTONICMEDIA, LayerProtocolName.ODU,
+            LayerProtocolName.DSR, LayerProtocolName.ETH);
+    }
+
+    @Override
+    public void onNotification(Notification notification) {
+        LOG.info("Received network model notification {}", notification);
+        if (notification.getNotificationType() == NotificationType.ATTRIBUTEVALUECHANGE
+                && notification.getTargetObjectType() == ObjectType.NODEEDGEPOINT) {
+            if (notification.getChangedAttributes() == null) {
+                return;
+            }
+            // TODO: need to re-think this to update first the connections from roadm to roadm and then the others
+            updateConnections(notification.getChangedAttributes().keySet().stream()
+                    .map(changedAttributesKey -> new Uuid(changedAttributesKey.getValueName()))
+                    .collect(Collectors.toList()),
+                notification.getChangedAttributes().values().stream()
+                    .map(NameAndValueChange::getNewValue)
+                    .collect(Collectors.toList()));
+            updateConnectivityServices();
+            // todo  create NotificationPublishSerivce (Tapi) object + send Notification
+        }
+    }
+
+    private void updateConnectivityServices() {
+        try {
+            this.connectivityServiceChanges.clear();
+            InstanceIdentifier<ConnectivityContext> connectivityContextIID =
+                InstanceIdentifier.builder(Context.class).augmentation(
+                        org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                    .child(ConnectivityContext.class)
+                    .build();
+            Optional<ConnectivityContext> optConnContext =
+                this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
+            if (optConnContext.isEmpty()) {
+                LOG.error("Could not update TAPI connectivity services");
+                return;
+            }
+            ConnectivityContext connContext = optConnContext.get();
+            Map<Uuid, Enumeration[]> states = new HashMap<>();
+            if (connContext.getConnectivityService() == null) {
+                return;
+            }
+            for (ConnectivityService connService : connContext.getConnectivityService().values()) {
+                LOG.info("Connectivity service = {}", connService);
+                // TODO: maybe we need to check lower connections if my new code doesnt work
+                states.put(connService.getUuid(), getStates(connService));
+                AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
+                OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
+
+                InstanceIdentifier<ConnectivityService> connServIID = InstanceIdentifier
+                    .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi
+                        .connectivity.rev181210.Context1.class)
+                    .child(ConnectivityContext.class)
+                    .child(ConnectivityService.class, new ConnectivityServiceKey(connService.getUuid()))
+                    .build();
+                ConnectivityService changedConnServ = new ConnectivityServiceBuilder()
+                    .setUuid(connService.getUuid())
+                    .setAdministrativeState(adminState)
+                    .setOperationalState(operState)
+                    .build();
+                this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connServIID,
+                    changedConnServ);
+                this.networkTransactionService.commit().get();
+
+                if (connService.getAdministrativeState() != adminState
+                    || connService.getOperationalState() != operState) {
+                    this.connectivityServiceChanges.add(changedConnServ);
+                }
+            }
+            // TODO: this last function may need some refactoring... if the PHOT_MEDIA goes down,
+            //  then ODU goes down and then DSR should also go down
+            for (ConnectivityService connService : connContext.getConnectivityService().values()) {
+                AdministrativeState adminState = (AdministrativeState) states.get(connService.getUuid())[0];
+                OperationalState operState = (OperationalState) states.get(connService.getUuid())[1];
+                this.connectivityServiceChanges.addAll(updateSupportedConnectivityServices(
+                    connContext.getConnectivityService().values(), connService.getUuid(), adminState, operState,
+                    LayerProtocolName.ODU));
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Could not update TAPI connectivity services");
+        }
+    }
+
+    private Enumeration[] getStates(ConnectivityService connService) throws InterruptedException, ExecutionException {
+        OperationalState operState = OperationalState.ENABLED;
+        AdministrativeState adminState = AdministrativeState.UNLOCKED;
+        if (connService.getConnection() == null) {
+            LOG.info("No connections on service = {}", connService);
+            return new Enumeration[]{null, null};
+        }
+        for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210
+                .connectivity.service.Connection connection : connService.getConnection().values()) {
+            InstanceIdentifier<Connection> connIID =
+                InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                    .child(ConnectivityContext.class)
+                    .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
+                    .build();
+            Optional<Connection> optConn = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL,
+                connIID).get();
+            if (optConn.isEmpty()) {
+                LOG.error("Could not get state for a TAPI connection");
+                continue;
+            }
+            LOG.info("State of connection {} of connectivity service {} = {}", optConn.get().getUuid().getValue(),
+                connService.getUuid().getValue(), optConn.get().getOperationalState().getName());
+            if (optConn.get().getOperationalState() == OperationalState.DISABLED) {
+                adminState = AdministrativeState.LOCKED;
+                operState = OperationalState.DISABLED;
+            }
+        }
+        return new Enumeration[]{adminState, operState};
+    }
+
+    private void updateConnections(List<Uuid> changedOneps, List<String> onepStates) {
+        LOG.info("Updating TAPI connections");
+        LOG.info("Change in oneps = {}, new states = {}", changedOneps, onepStates);
+        try {
+            //should it return a list of connections?
+            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivityContextIID =
+                InstanceIdentifier.builder(Context.class).augmentation(
+                            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                        .child(org.opendaylight.yang.gen.v1.urn
+                                .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                        .build();
+            Optional<org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> optConnContext =
+                this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityContextIID).get();
+            if (optConnContext.isEmpty()) {
+                LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
+                return;
+            }
+            if (optConnContext.get().getConnectivityService() == null) {
+                LOG.info("No TAPI connectivity service to update");
+                return;
+            }
+            // TODO: order services from lower layer to upper layer
+            Map<ConnectivityServiceKey, ConnectivityService> connServMap
+                    = optConnContext.get().getConnectivityService();
+            if (connServMap == null) {
+                LOG.info("No connections to update");
+                return;
+            }
+            connServMap = orderConnServiceMap(connServMap);
+            for (ConnectivityService connService : connServMap.values()) {
+                LOG.info("Looping through connectivity service = {}", connService.getUuid().getValue());
+                if (connService.getConnection() == null) {
+                    continue;
+                }
+                for (org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210
+                        .connectivity.service.Connection connection : connService.getConnection().values()) {
+                    InstanceIdentifier<Connection> connIID =
+                        InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
+                            .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                                .child(org.opendaylight.yang.gen.v1.urn
+                                        .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                                .child(Connection.class, new ConnectionKey(connection.getConnectionUuid()))
+                                .build();
+                    Optional<Connection> optConn =
+                        this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
+                    if (optConn.isEmpty()) {
+                        LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
+                        continue;
+                    }
+                    Connection newConn = optConn.get();
+                    // Check LowerConnection states and if any of the lower connection is disabled then we can put
+                    // the connection out of service. And based on the connection previous state we decide
+                    // the update necessary
+                    OperationalState newConnState = newConn.getOperationalState();
+                    if (newConn.getLowerConnection() != null) {
+                        newConnState = updateLowerConnections(changedOneps, onepStates,
+                                newConn.getLowerConnection().values(), newConn.getOperationalState());
+                    }
+                    if (newConnState.equals(newConn.getOperationalState())) {
+                        // To check if the oneps are from the original Top connection
+                        newConnState = getConnectionState(changedOneps, onepStates, newConn);
+                    }
+
+                    LOG.info("Previous connection state = {} & New connection state = {}",
+                            newConn.getOperationalState().getName(), newConnState.getName());
+                    Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
+                    // TODO: the changed NEP is a DEG port which is not in any connection,
+                    //  therefore we also need to change the cross connections,
+                    //  the lower connections uuid and check the states.
+                    //  If any of the lower connections of a connection is DISABLED then the top connection is DISABLED
+                    this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
+                    this.networkTransactionService.commit().get();
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
+        }
+    }
+
+    private Map<ConnectivityServiceKey, ConnectivityService> orderConnServiceMap(
+            Map<ConnectivityServiceKey, ConnectivityService> connServMap) {
+        Map<ConnectivityServiceKey, ConnectivityService> orderedServiceMap = new HashMap<>();
+        for (LayerProtocolName lpn:this.orderedServiceLayerList) {
+            for (ConnectivityService connServ:connServMap.values()) {
+                if (connServ.getServiceLayer().equals(lpn)) {
+                    LOG.info("Layer of service is equal to entry of lpn = {}", lpn);
+                    orderedServiceMap.put(connServ.key(), connServ);
+                }
+            }
+        }
+        LOG.info("Ordered map of services = {}", orderedServiceMap);
+        return orderedServiceMap;
+    }
+
+    private OperationalState updateLowerConnections(List<Uuid> changedOneps, List<String> onepStates,
+                                                    Collection<LowerConnection> lowerConnections,
+                                                    OperationalState uppConnState) {
+        LOG.info("Updating lower connections");
+        OperationalState topConnectionState = uppConnState;
+        Boolean allLowerConnEna = true;
+        try {
+            for (LowerConnection lowerConn:lowerConnections) {
+                InstanceIdentifier<Connection> connIID =
+                    InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                            .child(org.opendaylight.yang.gen.v1.urn
+                                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                            .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
+                            .build();
+                Optional<Connection> optConn =
+                        this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
+                if (optConn.isEmpty()) {
+                    LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
+                    continue;
+                }
+                Connection newConn = optConn.get(); // Current state of connection
+                if (newConn.getLowerConnection() != null) {
+                    // TODO: we can receive disable here because the lower connection haven been yet looped through and
+                    //  therefore it is disabled but it has to be changed to enable before returning disable.
+                    //  We need to recall the update Lower Connections with the lower connection we are checking now
+                    //  and all its lower connections, until no lower connections are found in the connection
+                    updateLowerConnections(changedOneps, onepStates, newConn.getLowerConnection().values(),
+                            newConn.getOperationalState());
+                }
+                OperationalState newConnState = getConnectionState(changedOneps, onepStates, newConn);
+                // updated connection state if it contains a nep that has changed
+                if (!newConn.getOperationalState().equals(newConnState)) {
+                    Connection changedConn = new ConnectionBuilder(newConn).setOperationalState(newConnState).build();
+                    this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connIID, changedConn);
+                    this.networkTransactionService.commit().get();
+                }
+                if (newConnState.equals(OperationalState.DISABLED)) {
+                    LOG.info("LowerConnection state is disable");
+                    allLowerConnEna = false;
+                    topConnectionState = OperationalState.DISABLED;
+                }
+            }
+            if (allLowerConnEna) {
+                return OperationalState.ENABLED;
+            }
+            return OperationalState.DISABLED;
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
+            return topConnectionState;
+        }
+    }
+
+    private OperationalState getConnectionState(List<Uuid> changedOneps, List<String> operState, Connection conn)
+            throws InterruptedException, ExecutionException {
+        LOG.info("Getting TAPI connectionState");
+        List<Uuid> connectionNeps = Objects.requireNonNull(conn.getConnectionEndPoint()).values().stream()
+            .map(NodeEdgePointRef::getNodeEdgePointUuid).collect(Collectors.toList());
+        LOG.info("Changed neps = {}", changedOneps);
+        LOG.info("Connection NEPs = {}", connectionNeps);
+        if (!Collections.disjoint(changedOneps, connectionNeps)) {
+            LOG.info("Connection neps {} are included in changed oneps {}", connectionNeps, changedOneps);
+            if ((changedOneps.contains(connectionNeps.get(0)) ? transformOperState(operState.get(
+                    changedOneps.indexOf(connectionNeps.get(0)))) : null) == OperationalState.DISABLED
+                        || (changedOneps.contains(connectionNeps.get(1)) ? transformOperState(operState.get(
+                                changedOneps.indexOf(connectionNeps.get(1)))) : null) == OperationalState.DISABLED) {
+                return OperationalState.DISABLED;
+            }
+            LOG.info("Didnt transform correctly the states");
+            for (Uuid connectionNep : connectionNeps) {
+                Optional<org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ocep
+                    = conn.getConnectionEndPoint().values().stream()
+                        .filter(connectionEndPoint -> connectionEndPoint.getNodeEdgePointUuid() == connectionNep)
+                        .findFirst();
+                if (ocep.isEmpty()) {
+                    continue;
+                }
+                InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
+                    .augmentation(Context1.class).child(TopologyContext.class)
+                    .child(Topology.class, new TopologyKey(tapiTopoUuid))
+                    .child(Node.class, new NodeKey(ocep.get().getNodeUuid()))
+                    .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(connectionNep))
+                    .build();
+                Optional<OwnedNodeEdgePoint> onep =
+                    this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, onepIID).get();
+                if (onep.isEmpty() || onep.get().augmentation(OwnedNodeEdgePoint1.class) == null
+                        || onep.get().augmentation(OwnedNodeEdgePoint1.class).getCepList() == null) {
+                    continue;
+                }
+                if (onep.get().getOperationalState() == OperationalState.DISABLED
+                        && !changedOneps.contains(onep.get().getUuid())) {
+                    return OperationalState.DISABLED;
+                }
+            }
+            return OperationalState.ENABLED;
+        }
+        LOG.info("Connection state = {}. Going to check lower connections", conn.getOperationalState());
+        // TODO --> check all lower connections state and if all of them are enabled we return enable, otherwise disable
+        if (conn.getLowerConnection() != null && allLowerConEnabled(conn.getLowerConnection().values())) {
+            return OperationalState.ENABLED;
+        }
+        return conn.getOperationalState();
+    }
+
+    private boolean allLowerConEnabled(Collection<LowerConnection> lowerConnections) {
+        try {
+            for (LowerConnection lowerConn:lowerConnections) {
+                InstanceIdentifier<Connection> connIID =
+                    InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
+                            .onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                        .child(org.opendaylight.yang.gen.v1.urn
+                            .onf.otcc.yang.tapi.connectivity.rev181210.context
+                            .ConnectivityContext.class)
+                        .child(Connection.class, new ConnectionKey(lowerConn.getConnectionUuid()))
+                        .build();
+                Optional<Connection> optConn =
+                    this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connIID).get();
+                if (optConn.isEmpty()) {
+                    LOG.error(TapiStringConstants.TAPI_CONNECTION_READ_ERROR);
+                    continue;
+                }
+                Connection newConn = optConn.get(); // Current state of connection
+                // updated connection state if it contains a nep that has changed
+                if (newConn.getOperationalState().equals(OperationalState.DISABLED)) {
+                    LOG.info("LowerConnection state is disable");
+                    return false;
+                }
+            }
+            return true;
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error(TapiStringConstants.TAPI_CONNECTION_UPDATE_ERROR);
+            return false;
+        }
+    }
+
+    private List<ConnectivityService> updateSupportedConnectivityServices(Collection<ConnectivityService> connServices,
+                                                                          Uuid supportingConnService,
+                                                                          AdministrativeState adminState,
+                                                                          OperationalState operState,
+                                                                          LayerProtocolName layer) {
+        // TODO we need to check this function
+        List<ConnectivityService> changedServices = new ArrayList<>();
+        if (adminState != AdministrativeState.LOCKED && operState != OperationalState.DISABLED) {
+            return changedServices;
+        }
+        try {
+            for (ConnectivityService supportedConnService : connServices) {
+                // TODO currently supporting service uuid is saved in service layer, replace with name as soon
+                // as name is implemented
+                if (supportedConnService.getServiceLayer() != layer) {
+                    continue;
+                }
+                InstanceIdentifier<ConnectivityService> supportedConnServIID = InstanceIdentifier
+                    .builder(Context.class).augmentation(org.opendaylight.yang.gen.v1
+                        .urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1.class)
+                    .child(org.opendaylight.yang.gen.v1
+                        .urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                    .child(ConnectivityService.class, new ConnectivityServiceKey(supportedConnService.getUuid()))
+                    .build();
+                Optional<ConnectivityService> optNewConnService = this.networkTransactionService.read(
+                    LogicalDatastoreType.OPERATIONAL, supportedConnServIID).get();
+                if (optNewConnService.isEmpty()) {
+                    LOG.error("Could not update TAPI connectivity service");
+                    continue;
+                }
+                ConnectivityService newConnService = optNewConnService.get();
+                if (supportedConnService.getServiceLevel() != null
+                        && supportedConnService.getServiceLevel().equals(supportingConnService.getValue())
+                        && newConnService.getAdministrativeState() != AdministrativeState.LOCKED
+                        && newConnService.getOperationalState() != OperationalState.DISABLED) {
+
+                    ConnectivityService changedSupportedConnServ = new ConnectivityServiceBuilder()
+                        .setUuid(supportedConnService.getUuid())
+                        .setAdministrativeState(adminState)
+                        .setOperationalState(operState)
+                        .build();
+                    // TODO: may need to update connections...
+                    this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, supportedConnServIID,
+                        changedSupportedConnServ);
+                    this.networkTransactionService.commit().get();
+                    changedServices.add(changedSupportedConnServ);
+                    if (layer == LayerProtocolName.ODU) {
+                        changedServices.addAll(updateSupportedConnectivityServices(connServices,
+                            supportedConnService.getUuid(), adminState, operState, LayerProtocolName.DSR));
+                    }
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Could not update TAPI connectivity service");
+        }
+        return changedServices;
+    }
+
+    private OperationalState transformOperState(String operString) {
+        LOG.debug("Operstring to be converted = {}", operString);
+        State operState = org.opendaylight.transportpce.networkmodel.util.TopologyUtils.setNetworkOperState(operString);
+        LOG.debug("State received from topologyutils = {}", operState);
+        return operState.equals(State.InService) ? OperationalState.ENABLED : OperationalState.DISABLED;
+    }
+
+}
index c37edd616ad56643f13efea909c58048a63537dc..713e496f5db0425be70ec583f39ab322f4b644c1 100644 (file)
@@ -96,11 +96,17 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
         connectionFullMap; // this variable is for complete connection objects
+    private Connection topConnRdmRdm;
+    private Connection topConnXpdrXpdrPhtn;
+    private Connection topConnXpdrXpdrOdu;
 
     public TapiPceListenerImpl(DataBroker dataBroker) {
         this.connectionFullMap = new HashMap<>();
         this.dataBroker = dataBroker;
         this.networkTransactionService = new NetworkTransactionImpl(new RequestProcessor(this.dataBroker));
+        this.topConnRdmRdm = null;
+        this.topConnXpdrXpdrPhtn = null;
+        this.topConnXpdrXpdrOdu = null;
     }
 
     @Override
@@ -131,7 +137,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
     private void onPathComputationResult(ServicePathRpcResult notification) {
         this.connectionFullMap.clear();
         LOG.info("PCE '{}' Notification received : {}",servicePathRpcResult.getNotificationType().getName(),
-                notification);
+            notification);
         if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) {
             LOG.error("PCE path computation failed !");
             return;
@@ -162,7 +168,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // Create connections and ceps for the connectivity service.
         //  Connections must be with a locked stated. As the renderer hasnt implemented yet the oc's
         Map<ConnectionKey, Connection> connectionMap = createConnectionsAndCepsForService(pathDescription,
-                input.getConnectivityConstraint().getServiceLayer());
+            input.getConnectivityConstraint().getServiceLayer());
         // add connections to connection context and to connectivity context
         updateConnectionContextWithConn(this.connectionFullMap, connectionMap, serviceUuid);
     }
@@ -181,7 +187,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         List<String> rdmNodelist = new ArrayList<>();
         List<String> xpdrNodelist = new ArrayList<>();
         for (AToZ elem:pathDescription.getAToZDirection().getAToZ().values().stream()
-                .sorted(Comparator.comparing(AToZ::getId)).collect(Collectors.toList())) {
+            .sorted((Comparator.comparing(atoz -> Integer.valueOf(atoz.getId())))).collect(Collectors.toList())) {
             resourceType = elem.getResource().getResource().implementedInterface().getSimpleName();
             switch (resourceType) {
                 case TapiStringConstants.TP:
@@ -270,19 +276,24 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                 // - Top Connection MC betwwen MC CEPs of different roadms
                 // - Top Connection OTSiMC betwwen OTSiMC CEPs of extreme roadms
                 connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
-                        edgeRoadm1, edgeRoadm2));
+                    edgeRoadm1, edgeRoadm2));
                 if (!pathDescription.getAToZDirection().getAToZ().values().stream().findFirst().get().getId()
                         .contains("ROADM")) {
                     // - XC Connection OTSi betwwen iOTSi y eOTSi of xpdr
                     // - Top connection OTSi between network ports of xpdrs in the Photonic media layer -> i_OTSi
                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
+                    this.topConnRdmRdm = null;
                 }
                 break;
             case ODU:
+                // TODO: verify if this is correct
                 LOG.info("OTN ODU service");
                 // - XC Connection OTSi between iODU and eODU of xpdr
                 // - Top connection in the ODU layer, between xpdr iODU ports
-                connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
+                if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
+                    connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
+                    this.topConnXpdrXpdrPhtn = null;
+                }
                 break;
             case ETH:
                 LOG.info("WDM service");
@@ -295,10 +306,12 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                     connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
                         edgeRoadm1, edgeRoadm2));
                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
+                    this.topConnRdmRdm = null;
                     xpdrClientTplist = getAssociatedClientsPort(xpdrNetworkTplist);
                     LOG.info("Associated client ports = {}", xpdrClientTplist);
                     connectionServMap.putAll(createXpdrCepsAndConnectionsEth(xpdrClientTplist, xpdrNodelist,
                         connectionServMap));
+                    this.topConnXpdrXpdrPhtn = null;
                 }
                 break;
             case DSR:
@@ -310,14 +323,15 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                     // TODO: We create both ODU and DSR because there is no ODU service creation for the switch
                     // - XC Connection OTSi betwwen iODU and eODU of xpdr
                     // - Top connection in the ODU layer, between xpdr eODU ports (?)
-                    connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
                         xpdrNodelist));
+                    this.topConnXpdrXpdrPhtn = null;
                 }
                 if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
                     // TODO: OTN service but mux has 3 steps at rendering. Verify that things exist
                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
                         xpdrNodelist));
+                    this.topConnXpdrXpdrOdu = null;
                 }
                 break;
             default:
@@ -343,7 +357,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         }
         LOG.info("PCE cancel resource done OK !");
         Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8")))
-                .toString());
+            .toString());
         // get connections of connectivity service and remove them from tapi context and then remove
         //  service from context. The CEPs are maintained as they could be reused by another service
         ConnectivityService connService = getConnectivityService(suuid);
@@ -358,8 +372,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
     }
 
     @SuppressFBWarnings(
-            value = "ES_COMPARING_STRINGS_WITH_EQ",
-            justification = "false positives, not strings but real object references comparisons")
+        value = "ES_COMPARING_STRINGS_WITH_EQ",
+        justification = "false positives, not strings but real object references comparisons")
     private Boolean compareServicePathRpcResult(ServicePathRpcResult notification) {
         if (servicePathRpcResult == null) {
             return false;
@@ -412,7 +426,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // DSR top connection between edge xpdr CLIENT DSR
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
-            LayerProtocolName.DSR, xcMap);
+                LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
 
         // DSR top connection that will be added to the service object
@@ -457,7 +471,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             // Create x connection between I_ODU and E_ODU within xpdr
             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrClient, spcXpdrNetwork,
-                TapiStringConstants.ODU, LayerProtocolName.ODU);
+                    TapiStringConstants.ODU, LayerProtocolName.ODU);
             this.connectionFullMap.put(connection.key(), connection);
 
             // Create X connection that will be added to the service object
@@ -473,7 +487,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // eODU top connection between edge xpdr CLIENT eODU
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU,
-            LayerProtocolName.ODU, xcMap);
+                LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrOdu);
         this.connectionFullMap.put(connectionOdu.key(), connectionOdu);
 
         // ODU top connection that will be added to the service object and also lower connection
@@ -485,7 +499,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // DSR top connection between edge xpdr CLIENT DSR
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
-            LayerProtocolName.DSR, xcMap);
+                LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
 
         // DSR top connection that will be added to the service object
@@ -524,12 +538,13 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .get(xpdrNodelist.size() - 1))).findFirst().get();
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU,
-            LayerProtocolName.ODU, xcMap);
+                LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrPhtn);
         this.connectionFullMap.put(connection.key(), connection);
 
         // ODU top connection that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
+        this.topConnXpdrXpdrOdu = conn;
 
         return connServMap;
     }
@@ -543,7 +558,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         //  be added to the lower connection of a top connection
         Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
 
-        // create ceps and x connections within xpdr
+        // create ceps and xc connections within xpdr
         for (String xpdr:xpdrNodelist) {
             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
             String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst().get();
@@ -570,7 +585,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             // Create x connection between I_OTSi and E_OTSi within xpdr
             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrNetwork, spcXpdrNetwork,
-                TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
+                    TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
             this.connectionFullMap.put(connection.key(), connection);
 
             // Create X connection that will be added to the service object
@@ -584,14 +599,13 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .get(xpdrNodelist.size() - 1))).findFirst().get();
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI,
-            LayerProtocolName.PHOTONICMEDIA, xcMap);
+                LayerProtocolName.PHOTONICMEDIA, xcMap, this.topConnRdmRdm);
         this.connectionFullMap.put(connection.key(), connection);
 
         // OTSi top connection that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
-
-
+        this.topConnXpdrXpdrPhtn = conn;
         return connServMap;
     }
 
@@ -600,128 +614,170 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                                                                          List<String> rdmNodelist,
                                                                          String edgeRoadm1, String edgeRoadm2) {
         // TODO: will need to check if things exist already or not
-        Map<ConnectionKey, Connection> connServMap = new HashMap<>();
         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
             ConnectionEndPoint> cepMap = new HashMap<>();
         // create ceps and x connections within roadm
-        Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
+        Map<LowerConnectionKey, LowerConnection> xcLowerMap = new HashMap<>();
         for (String roadm : rdmNodelist) {
             LOG.info("Creating ceps and xc for roadm {}", roadm);
-            String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
-            LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
-            // There should be only 1 AD and 1 DEG per roadm
-            // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
-            //  3 different MC CEPs giving different IDs to show that they are different
-            // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
-            // created in the topology creation
-            // add CEPs to the topology to the corresponding ONEP
-            ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
-            ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
-            ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
-            putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
-            cepMap.put(adCep1.key(), adCep1);
-            cepMap.put(adCep2.key(), adCep2);
-            cepMap.put(adCep3.key(), adCep3);
-
-            String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
-            LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
-
-            ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
-            ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
-            ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
-            putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
-            cepMap.put(degCep1.key(), degCep1);
-            cepMap.put(degCep2.key(), degCep2);
-            cepMap.put(degCep3.key(), degCep3);
-
-            LOG.info("Going to create cross connections for ROADM {}", roadm);
-            // Create X connections between MC and OTSi_MC for full map
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection1 = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
-                LayerProtocolName.PHOTONICMEDIA);
-            LOG.info("Cross connection 1 created = {}", connection1.toString());
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection2 = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
-                LayerProtocolName.PHOTONICMEDIA);
-            LOG.info("Cross connection 2 created = {}", connection2.toString());
-            this.connectionFullMap.put(connection1.key(), connection1);
-            this.connectionFullMap.put(connection2.key(), connection2);
-
-            // Create X connections that will be added to the service object
-            LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
-            LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
-
-            xcMap.put(conn1.key(), conn1);
-            xcMap.put(conn2.key(), conn2);
-        }
-        LOG.info("Going to create top connections between roadms");
-        // create top connections between roadms: MC connections between AD MC CEPs of roadms
-        for (int i = 0; i < rdmNodelist.size(); i++) {
-            if (rdmNodelist.size() <= (i + 1)) {
-                LOG.info("Reached last roadm. No more MC connections");
-                break;
+            if (roadm.equals(edgeRoadm1) || roadm.equals(edgeRoadm2)) {
+                LOG.info("EDGE ROADM, cross connections needed between SRG and DEG");
+                String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
+                // There should be only 1 AD and 1 DEG per roadm
+                // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
+                //  3 different MC CEPs giving different IDs to show that they are different
+                // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
+                // created in the topology creation
+                // add CEPs to the topology to the corresponding ONEP
+                ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
+                ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
+                ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
+                cepMap.put(adCep1.key(), adCep1);
+                cepMap.put(adCep2.key(), adCep2);
+                cepMap.put(adCep3.key(), adCep3);
+
+                String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
+
+                ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
+                ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
+                ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
+                cepMap.put(degCep1.key(), degCep1);
+                cepMap.put(degCep2.key(), degCep2);
+                cepMap.put(degCep3.key(), degCep3);
+
+                LOG.info("Going to create cross connections for ROADM {}", roadm);
+                // Create X connections between MC and OTSi_MC for full map
+                org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
+                    = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
+                        LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 1 created = {}", connection1.toString());
+                org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
+                    = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
+                        LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 2 created = {}", connection2.toString());
+                this.connectionFullMap.put(connection1.key(), connection1);
+                this.connectionFullMap.put(connection2.key(), connection2);
+
+                // Create X connections that will be added to the service object
+                LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+                LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
+
+                xcLowerMap.put(conn1.key(), conn1);
+                xcLowerMap.put(conn2.key(), conn2);
+            } else {
+                LOG.info("MIDDLE ROADM, cross connections needed between DEG and DEG");
+                String spcRdmDEG1 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().get();
+                LOG.info("Degree 1 port of ROADm {} = {}", roadm, spcRdmDEG1);
+
+                ConnectionEndPoint deg1Cep1 = createCepRoadm(spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA, deg1Cep1);
+                ConnectionEndPoint deg1Cep2 = createCepRoadm(spcRdmDEG1, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.MC, deg1Cep2);
+                ConnectionEndPoint deg1Cep3 = createCepRoadm(spcRdmDEG1, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.OTSI_MC, deg1Cep3);
+                cepMap.put(deg1Cep1.key(), deg1Cep1);
+                cepMap.put(deg1Cep2.key(), deg1Cep2);
+                cepMap.put(deg1Cep3.key(), deg1Cep3);
+
+                String spcRdmDEG2 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).skip(1).findFirst().get();
+                LOG.info("Degree 2 port of ROADm {} = {}", roadm, spcRdmDEG2);
+
+                ConnectionEndPoint deg2Cep1 = createCepRoadm(spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA, deg2Cep1);
+                ConnectionEndPoint deg2Cep2 = createCepRoadm(spcRdmDEG2, TapiStringConstants.MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.MC, deg2Cep2);
+                ConnectionEndPoint deg2Cep3 = createCepRoadm(spcRdmDEG2, TapiStringConstants.OTSI_MC);
+                putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.OTSI_MC, deg2Cep3);
+                cepMap.put(deg2Cep1.key(), deg2Cep1);
+                cepMap.put(deg2Cep2.key(), deg2Cep2);
+                cepMap.put(deg2Cep3.key(), deg2Cep3);
+
+                LOG.info("Going to create cross connections for ROADM {}", roadm);
+                // Create X connections between MC and OTSi_MC for full map
+                org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
+                    = createXCBetweenCeps(deg1Cep2, deg2Cep2, spcRdmDEG1, spcRdmDEG2,
+                        TapiStringConstants.MC, LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 1 created = {}", connection1.toString());
+                org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
+                    = createXCBetweenCeps(deg1Cep3, deg2Cep3, spcRdmDEG1, spcRdmDEG2,
+                        TapiStringConstants.OTSI_MC, LayerProtocolName.PHOTONICMEDIA);
+                LOG.info("Cross connection 2 created = {}", connection2.toString());
+                this.connectionFullMap.put(connection1.key(), connection1);
+                this.connectionFullMap.put(connection2.key(), connection2);
+
+                // Create X connections that will be added to the service object
+                LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+                LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
+
+                xcLowerMap.put(conn1.key(), conn1);
+                xcLowerMap.put(conn2.key(), conn2);
             }
-            // Current roadm with roadm i + 1 --> MC
-            String roadm1 = rdmNodelist.get(i);
-            String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm1)).findFirst().get();
-            String roadm2 = rdmNodelist.get(i + 1);
-            String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm2)).findFirst().get();
-            LOG.info("Creating top connection from {} to {} between tps: {}-{}", roadm1, roadm2, spcRdmAD1, spcRdmAD2);
-
-            // Create top connections between MC for full map
-            org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-                connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
-                LayerProtocolName.PHOTONICMEDIA, xcMap);
-            this.connectionFullMap.put(connection.key(), connection);
-            LOG.info("Top connection created = {}", connection.toString());
-
-            // Create top connections that will be added to the service object and lower
-            // connection to the next top connection
-            Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
-            connServMap.put(conn.key(), conn);
-            LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
-            xcMap.put(conn1.key(), conn1);
         }
-
-        // OTSiMC top connection between edge roadms
-        LOG.info("Going to created top connection between OTSiMC");
+        LOG.info("Going to create top connections between roadms");
         String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm1)).findFirst().get();
         String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().get();
+        // MC top connection between edge roadms
+        LOG.info("Going to created top connection between MC");
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
-            connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
-            LayerProtocolName.PHOTONICMEDIA, xcMap);
+            connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
+                LayerProtocolName.PHOTONICMEDIA, xcLowerMap, null);
         this.connectionFullMap.put(connection.key(), connection);
         LOG.info("Top connection created = {}", connection.toString());
 
+        Map<ConnectionKey, Connection> connServMap = new HashMap<>();
         // OTSiMC top connections that will be added to the service object
         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
         connServMap.put(conn.key(), conn);
+        LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
+        Map<LowerConnectionKey, LowerConnection> topLowerMap = new HashMap<>();
+        topLowerMap.put(conn1.key(), conn1);
+
+        // OTSiMC top connection between edge roadms
+        LOG.info("Going to created top connection between OTSiMC");
+        org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
+            connection1 = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
+                LayerProtocolName.PHOTONICMEDIA, topLowerMap, null);
+        this.connectionFullMap.put(connection1.key(), connection1);
+        LOG.info("Top connection created = {}", connection1.toString());
+
+        // OTSiMC top connections that will be added to the service object
+        Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
+        connServMap.put(conn2.key(), conn2);
+        this.topConnRdmRdm = conn2;
         return connServMap;
     }
 
     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
             createTopConnection(String tp1, String tp2,
                         Map<org.opendaylight.yang.gen.v1.urn
-                                .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
-                                ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol,
-                                Map<LowerConnectionKey, LowerConnection> xcMap) {
+                            .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
+                            ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol,
+                        Map<LowerConnectionKey, LowerConnection> xcMap, Connection additionalLowerConn) {
         // find cep for each AD MC of roadm 1 and 2
         LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual));
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 =
             cepMap.get(new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
+                    .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp1.split("\\+")[0],
-                    qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                        qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                     .toString())));
         LOG.info("ADCEP1 = {}", adCep1.toString());
         org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep1 =
+                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep1 =
             new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
                 .setNodeEdgePointUuid(adCep1.getClientNodeEdgePoint()
                     .values().stream().findFirst().get().getNodeEdgePointUuid())
                 .setTopologyUuid(adCep1.getClientNodeEdgePoint()
@@ -732,15 +788,15 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                 .build();
         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep2 =
             cepMap.get(new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
+                    .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp2.split("\\+")[0],
-                    qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                        qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                     .toString())));
         LOG.info("ADCEP2 = {}", adCep2.toString());
         org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep2 =
+                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep2 =
             new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
                 .setNodeEdgePointUuid(adCep2.getClientNodeEdgePoint()
                     .values().stream().findFirst().get().getNodeEdgePointUuid())
                 .setTopologyUuid(adCep2.getClientNodeEdgePoint()
@@ -758,8 +814,12 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .setValue(String.join("+", "TOP", tp1, tp2, qual))
             .build();
         // TODO: lower connection, supported link.......
+        if (additionalLowerConn != null) {
+            xcMap.putIfAbsent(new LowerConnectionKey(additionalLowerConn.getConnectionUuid()),
+                new LowerConnectionBuilder().setConnectionUuid(additionalLowerConn.getConnectionUuid()).build());
+        }
         return new org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
+                .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "TOP", tp1, tp2, qual))
                 .getBytes(Charset.forName("UTF-8"))).toString()))
             .setName(Map.of(connName.key(), connName))
@@ -780,9 +840,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         LOG.info("CEP1 = {}", cep1.getClientNodeEdgePoint().toString());
         LOG.info("CEP2 = {}", cep2.getClientNodeEdgePoint().toString());
         org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ1 =
+                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ1 =
             new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
                 .setNodeEdgePointUuid(cep1.getClientNodeEdgePoint()
                     .values().stream().findFirst().get().getNodeEdgePointUuid())
                 .setTopologyUuid(cep1.getClientNodeEdgePoint()
@@ -792,9 +852,9 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
                 .setConnectionEndPointUuid(cep1.getUuid())
                 .build();
         org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ2 =
+                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ2 =
             new org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
                 .setNodeEdgePointUuid(cep2.getClientNodeEdgePoint()
                     .values().stream().findFirst().get().getNodeEdgePointUuid())
                 .setTopologyUuid(cep2.getClientNodeEdgePoint()
@@ -813,7 +873,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .build();
         // TODO: lower connection, supported link.......
         return new org.opendaylight.yang.gen.v1.urn
-            .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
+                .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "XC", tp1, tp2, qual))
                 .getBytes(Charset.forName("UTF-8"))).toString()))
             .setName(Map.of(connName.key(), connName))
@@ -834,10 +894,10 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .build();
         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
-                qualifier)).getBytes(Charset.forName("UTF-8")))
+                    "PHOTONIC_MEDIA")).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
                 .getBytes(Charset.forName("UTF-8"))).toString()))
@@ -846,7 +906,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // TODO: add parent ONEP??
         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
             .setName(Map.of(cepName.key(), cepName))
@@ -867,10 +927,10 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             .build();
         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
-                nodeLayer)).getBytes(Charset.forName("UTF-8")))
+                    nodeLayer)).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
                 .getBytes(Charset.forName("UTF-8"))).toString()))
@@ -879,7 +939,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // TODO: add parent ONEP??
         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
-                qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
+                    qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
                 .toString()))
             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
             .setName(Map.of(cepName.key(), cepName))
@@ -939,8 +999,8 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class);
             if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null) {
                 if (onep1.getCepList().getConnectionEndPoint().containsKey(
-                    new org.opendaylight.yang.gen.v1
-                        .urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cep.key()))) {
+                        new org.opendaylight.yang.gen.v1
+                            .urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cep.key()))) {
                     LOG.info("CEP already in topology, skipping merge");
                     return;
                 }
@@ -964,7 +1024,7 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
 
     private void updateConnectionContextWithConn(
             Map<org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
+                    .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
                 org.opendaylight.yang.gen.v1.urn
                     .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connFullMap,
             Map<ConnectionKey, Connection> connMap, Uuid suuid) {
@@ -972,24 +1032,24 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         try {
             ConnectivityService connServ = getConnectivityService(suuid);
             ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connServ)
-                    .setConnection(connMap)
-                    .build();
+                .setConnection(connMap)
+                .build();
 
             // Perform the merge operation with the new conn service and the connection context updated
             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext
-                    connectivityContext = new ConnectivityContextBuilder()
+                connectivityContext = new ConnectivityContextBuilder()
                     .setConnectivityService(Map.of(updtConnServ.key(), updtConnServ))
                     .setConnection(connFullMap)
                     .build();
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivitycontextIID =
-                    InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
-                            .child(org.opendaylight.yang.gen.v1.urn
-                                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
-                            .build();
+                InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
+                    .child(org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                    .build();
             // merge in datastore
             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectivitycontextIID,
-                    connectivityContext);
+                connectivityContext);
             this.networkTransactionService.commit().get();
             LOG.info("TAPI connectivity merged successfully.");
         } catch (InterruptedException | ExecutionException e) {
@@ -999,13 +1059,13 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
 
     private ConnectivityService getConnectivityService(Uuid suuid) {
         try {
-        // First read connectivity service with service uuid and update info
+            // First read connectivity service with service uuid and update info
             InstanceIdentifier<ConnectivityService> connectivityServIID =
                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
-                        .child(org.opendaylight.yang.gen.v1.urn
-                                .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
-                        .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
-                        .build();
+                    .child(org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                    .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
+                    .build();
 
             Optional<ConnectivityService> optConnServ =
                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get();
@@ -1023,11 +1083,11 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
     private void deleteConnectivityService(Uuid suuid) {
         // First read connectivity service with service uuid and update info
         InstanceIdentifier<ConnectivityService> connectivityServIID =
-                InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
-                        .child(org.opendaylight.yang.gen.v1.urn
-                                .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
-                        .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
-                        .build();
+            InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
+                .child(org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
+                .build();
         try {
             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID);
             this.networkTransactionService.commit().get();
@@ -1040,15 +1100,15 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
         // First read connectivity service with service uuid and update info
         InstanceIdentifier<org.opendaylight.yang.gen.v1
                 .urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionIID =
-                InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
-                        .child(org.opendaylight.yang.gen.v1.urn
-                                .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
-                        .child(org.opendaylight.yang.gen.v1.urn
-                                .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
-                                new org.opendaylight.yang.gen.v1.urn
-                                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey(
-                                                connectionUuid))
-                        .build();
+            InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
+                .child(org.opendaylight.yang.gen.v1.urn
+                    .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
+                .child(org.opendaylight.yang.gen.v1.urn
+                        .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
+                    new org.opendaylight.yang.gen.v1.urn
+                            .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey(
+                        connectionUuid))
+                .build();
         try {
             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID);
             this.networkTransactionService.commit().get();
@@ -1114,12 +1174,12 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
             Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",xpdrNode, TapiStringConstants.DSR))
                 .getBytes(Charset.forName("UTF-8"))).toString());
             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
-                .onf.otcc.yang.tapi.topology.rev181210.topology.Node> nodeIID = InstanceIdentifier.builder(
-                    Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
-                    .onf.otcc.yang.tapi.topology.rev181210.Context1.class).child(TopologyContext.class)
-                .child(Topology.class, new TopologyKey(this.tapiTopoUuid))
-                .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
-                    new NodeKey(nodeUuid)).build();
+                    .onf.otcc.yang.tapi.topology.rev181210.topology.Node> nodeIID
+                = InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
+                            .onf.otcc.yang.tapi.topology.rev181210.Context1.class).child(TopologyContext.class)
+                    .child(Topology.class, new TopologyKey(this.tapiTopoUuid))
+                    .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
+                            new NodeKey(nodeUuid)).build();
             try {
                 Optional<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node> optNode
                     = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, nodeIID).get();
@@ -1183,4 +1243,4 @@ public class TapiPceListenerImpl implements TransportpcePceListener {
     public void setServiceUuid(Uuid serviceUuid) {
         this.serviceUuid = serviceUuid;
     }
-}
+}
\ No newline at end of file
index a0c1a355df3fb4983f5b3cee867e78d0f0fef79a..39163fed44d3b3e2f7bee68343fff67a92edaccb 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
+import org.opendaylight.mdsal.binding.api.NotificationPublishService;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
 import org.opendaylight.transportpce.tapi.R2RTapiLinkDiscovery;
@@ -66,6 +67,11 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.glob
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePoint;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePointBuilder;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.tapi.context.ServiceInterfacePointKey;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1Builder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPoint;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey;
@@ -75,9 +81,17 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev18121
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPoint;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.EndPointKey;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepList;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.dsr.rev181210.DIGITALSIGNALTYPE100GigE;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.dsr.rev181210.DIGITALSIGNALTYPE10GigELAN;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.dsr.rev181210.DIGITALSIGNALTYPEGigE;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NotificationBuilder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.NotificationType;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.ObjectType;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.notification.ChangedAttributes;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.notification.ChangedAttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.notification.rev181210.notification.ChangedAttributesKey;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.odu.rev181210.ODUTYPEODU0;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.odu.rev181210.ODUTYPEODU2;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.odu.rev181210.ODUTYPEODU2E;
@@ -120,6 +134,7 @@ import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.tr
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.timing.pac.LatencyCharacteristic;
 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.transfer.timing.pac.LatencyCharacteristicBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
 import org.opendaylight.yangtools.yang.common.Uint16;
 import org.opendaylight.yangtools.yang.common.Uint32;
 import org.slf4j.Logger;
@@ -134,13 +149,16 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService {
     private Map<ServiceInterfacePointKey, ServiceInterfacePoint> sipMap;
     private final R2RTapiLinkDiscovery linkDiscovery;
     private final TapiLink tapiLink;
+    private final NotificationPublishService notificationPublishService;
 
     public TapiNetworkModelServiceImpl(final R2RTapiLinkDiscovery linkDiscovery,
-                                       NetworkTransactionService networkTransactionService, TapiLink tapiLink) {
+                                       NetworkTransactionService networkTransactionService, TapiLink tapiLink,
+                                       final NotificationPublishService notificationPublishService) {
         this.networkTransactionService = networkTransactionService;
         this.sipMap = new HashMap<>();
         this.linkDiscovery = linkDiscovery;
         this.tapiLink = tapiLink;
+        this.notificationPublishService = notificationPublishService;
     }
 
     @Override
@@ -237,10 +255,38 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService {
 
         List<Uuid> changedOneps = updateNeps(mapping, uuids);
         updateLinks(changedOneps, mapping);
+        sendNotification(changedOneps, mapping);
 
         LOG.info("Updated TAPI topology successfully.");
     }
 
+    private void sendNotification(List<Uuid> changedOneps, Mapping mapping) {
+        Notification notification = new NotificationBuilder()
+            .setNotificationType(NotificationType.ATTRIBUTEVALUECHANGE)
+            .setTargetObjectType(ObjectType.NODEEDGEPOINT)
+            .setChangedAttributes(getChangedAttributes(changedOneps, mapping))
+            .setUuid(tapiTopoUuid)
+            .build();
+        try {
+            notificationPublishService.putNotification(notification);
+        } catch (InterruptedException e) {
+            LOG.error("Could not send notification");
+        }
+    }
+
+    private Map<ChangedAttributesKey, ChangedAttributes> getChangedAttributes(List<Uuid> changedOneps,
+                                                                              Mapping mapping) {
+        Map<ChangedAttributesKey, ChangedAttributes> changedAttributes = new HashMap<>();
+        for (Uuid nep : changedOneps) {
+            changedAttributes.put(new ChangedAttributesKey(nep.getValue()),
+                new ChangedAttributesBuilder().setValueName(nep.getValue())
+                    .setOldValue(mapping.getPortOperState().equals("InService") ? "OutOfService" : "InService")
+                    .setNewValue(mapping.getPortOperState())
+                    .build());
+        }
+        return changedAttributes;
+    }
+
     private void updateLinks(List<Uuid> changedOneps, Mapping mapping) {
         try {
             InstanceIdentifier<Topology> topoIID = InstanceIdentifier.builder(Context.class)
@@ -294,6 +340,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService {
                     for (OwnedNodeEdgePoint onep : oneps) {
                         changedOneps.add(onep.getUuid());
                         updateSips(mapping, onep);
+                        CepList cepList = getUpdatedCeps(mapping, onep);
                         InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
                                 .augmentation(Context1.class).child(TopologyContext.class)
                                 .child(Topology.class, new TopologyKey(tapiTopoUuid))
@@ -301,6 +348,7 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService {
                                 .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(onep.getUuid()))
                                 .build();
                         OwnedNodeEdgePoint onepblr = new OwnedNodeEdgePointBuilder().setUuid(onep.getUuid())
+                                .addAugmentation(new OwnedNodeEdgePoint1Builder().setCepList(cepList).build())
                                 .setAdministrativeState(transformAdminState(mapping.getPortAdminState()))
                                 .setOperationalState(transformOperState(mapping.getPortOperState())).build();
                         this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, onepIID, onepblr);
@@ -314,6 +362,20 @@ public class TapiNetworkModelServiceImpl implements TapiNetworkModelService {
         return changedOneps;
     }
 
+    private CepList getUpdatedCeps(Mapping mapping, OwnedNodeEdgePoint onep) {
+        OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class);
+        Map<ConnectionEndPointKey, ConnectionEndPoint> cepMap = new HashMap<>();
+        if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null) {
+            for (Map.Entry<ConnectionEndPointKey, ConnectionEndPoint> entry : onep1.getCepList().getConnectionEndPoint()
+                    .entrySet()) {
+                ConnectionEndPoint cep = new ConnectionEndPointBuilder(entry.getValue())
+                        .setOperationalState(transformOperState(mapping.getPortOperState())).build();
+                cepMap.put(entry.getKey(), cep);
+            }
+        }
+        return new CepListBuilder().setConnectionEndPoint(cepMap).build();
+    }
+
     private List<Uuid> getChangedNodeUuids(String nodeId, Mapping mapping) {
         List<Uuid> uuids = new ArrayList<>();
         if (nodeId.contains("ROADM")) {
index a44df320738ecf15f3a98bcc6432078ae625c5cc..62a1d9633fb08fdfd6b876dd24e3e870ae8bf948 100644 (file)
@@ -22,6 +22,9 @@ Author: Gilles Thouenon <gilles.thouenon@orange.com>
     <reference id="notificationService"
                interface="org.opendaylight.mdsal.binding.api.NotificationService"/>
 
+    <reference id="notificationPublishService"
+               interface="org.opendaylight.mdsal.binding.api.NotificationPublishService"/>
+
     <reference id="rpcProviderService"
           interface="org.opendaylight.mdsal.binding.api.RpcProviderService"/>
 
@@ -55,10 +58,15 @@ Author: Gilles Thouenon <gilles.thouenon@orange.com>
         <argument ref="dataBroker" />
     </bean>
 
+    <bean id="tapiNetworkModelListenerImpl" class="org.opendaylight.transportpce.tapi.listeners.TapiNetworkModelListenerImpl">
+        <argument ref="networkTransactionImpl" />
+    </bean>
+
     <bean id="tapiNetworkModelService" class="org.opendaylight.transportpce.tapi.topology.TapiNetworkModelServiceImpl">
         <argument ref="tapilinkDiscoveryImpl" />
         <argument ref="networkTransactionImpl" />
         <argument ref="tapiLink" />
+        <argument ref="notificationPublishService" />
     </bean>
 
     <bean id="tapiNetconfTopologyListener" class="org.opendaylight.transportpce.tapi.topology.TapiNetconfTopologyListener">
@@ -92,6 +100,7 @@ Author: Gilles Thouenon <gilles.thouenon@orange.com>
         <argument ref="tapiServiceHandlerListener" />
         <argument ref="notificationService" />
         <argument ref="tapiOrLinkListener" />
+        <argument ref="tapiNetworkModelListenerImpl" />
     </bean>
 
     <bean id="tapiPortMappingListener" class="org.opendaylight.transportpce.tapi.topology.TapiPortMappingListener">
index 8a575abd6254fb3a4375398bf9ec797957606a2a..90877fb3e17a798b4d2f0b185b5af6c78cf4cd81 100644 (file)
@@ -23,6 +23,7 @@ import org.opendaylight.transportpce.common.network.NetworkTransactionService;
 import org.opendaylight.transportpce.common.network.RequestProcessor;
 import org.opendaylight.transportpce.servicehandler.service.ServiceDataStoreOperations;
 import org.opendaylight.transportpce.tapi.impl.TapiProvider;
+import org.opendaylight.transportpce.tapi.listeners.TapiNetworkModelListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiPceListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiRendererListenerImpl;
 import org.opendaylight.transportpce.tapi.listeners.TapiServiceHandlerListenerImpl;
@@ -73,6 +74,9 @@ public class TapiProviderTest extends AbstractTest {
     @Mock
     TapiServiceHandlerListenerImpl serviceHandlerListenerImpl;
 
+    @Mock
+    TapiNetworkModelListenerImpl networkModelListener;
+
     private AutoCloseable closeable;
 
     @Before
@@ -91,7 +95,7 @@ public class TapiProviderTest extends AbstractTest {
         TapiProvider provider =  new TapiProvider(getDataBroker(), rpcProviderRegistry, serviceHandler,
             serviceDataStoreOperations, tapiListener, networkTransactionService, topologyListener,
             tapiPortMappingListener, tapiNetworkUtils, pceListenerImpl, rendererListenerImpl,
-            serviceHandlerListenerImpl, getNotificationService(), orLinkListener);
+            serviceHandlerListenerImpl, getNotificationService(), orLinkListener, networkModelListener);
 
         provider.init();