NBI notification support for service-result-rpc
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / listeners / TapiPceListenerImpl.java
1 /*
2  * Copyright © 2021 Nokia, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.transportpce.tapi.listeners;
9
10 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
11 import java.nio.charset.Charset;
12 import java.util.ArrayList;
13 import java.util.Comparator;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.UUID;
19 import java.util.concurrent.ExecutionException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.network.NetworkTransactionImpl;
24 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
25 import org.opendaylight.transportpce.tapi.TapiStringConstants;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.ServicePathRpcResult;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.TransportpcePceListener;
28 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.service.path.rpc.result.PathDescription;
29 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev220808.service.path.rpc.result.PathDescriptionBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.Network;
31 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.Mapping;
32 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.MappingKey;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.Nodes;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.NodesKey;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType;
36 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.path.description.atoz.direction.AToZ;
37 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.pce.resource.resource.resource.Node;
38 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev230501.pce.resource.resource.resource.TerminationPoint;
39 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev220118.RpcStatusEx;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Context;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.ForwardingDirection;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LayerProtocolName;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.LifecycleState;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.OperationalState;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortDirection;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.PortRole;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.Name;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameBuilder;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev181210.global._class.NameKey;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.Context1;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.CreateConnectivityServiceInput;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.OwnedNodeEdgePoint1Builder;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPoint;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointBuilder;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointKey;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnection;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionBuilder;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.LowerConnectionKey;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePoint;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connection.end.point.ClientNodeEdgePointBuilder;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityService;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceBuilder;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectivityServiceKey;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.Connection;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionBuilder;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.service.ConnectionKey;
69 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContextBuilder;
70 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepList;
71 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder;
72 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext;
73 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePoint;
74 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointBuilder;
75 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.node.OwnedNodeEdgePointKey;
76 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.NodeKey;
77 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.Topology;
78 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.context.TopologyKey;
79 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
82
83 public class TapiPceListenerImpl implements TransportpcePceListener {
84
85     private static final Logger LOG = LoggerFactory.getLogger(TapiPceListenerImpl.class);
86
87     private final Uuid tapiTopoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
88         .getBytes(Charset.forName("UTF-8"))).toString());
89     private ServicePathRpcResult servicePathRpcResult;
90     private CreateConnectivityServiceInput input;
91     private Uuid serviceUuid;
92     private final DataBroker dataBroker;
93     private final NetworkTransactionService networkTransactionService;
94     private final Map<org.opendaylight.yang.gen.v1.urn
95         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
96         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection>
97         connectionFullMap; // this variable is for complete connection objects
98     private Connection topConnRdmRdm;
99     private Connection topConnXpdrXpdrPhtn;
100     private Connection topConnXpdrXpdrOdu;
101
102     public TapiPceListenerImpl(DataBroker dataBroker) {
103         this.connectionFullMap = new HashMap<>();
104         this.dataBroker = dataBroker;
105         this.networkTransactionService = new NetworkTransactionImpl(this.dataBroker);
106         this.topConnRdmRdm = null;
107         this.topConnXpdrXpdrPhtn = null;
108         this.topConnXpdrXpdrOdu = null;
109     }
110
111     @Override
112     public void onServicePathRpcResult(ServicePathRpcResult notification) {
113         if (compareServicePathRpcResult(notification)) {
114             LOG.warn("ServicePathRpcResult already wired !");
115             return;
116         }
117         servicePathRpcResult = notification;
118         switch (servicePathRpcResult.getNotificationType().getIntValue()) {
119             /* path-computation-request. */
120             case 1:
121                 onPathComputationResult(notification);
122                 break;
123             /* cancel-resource-reserve. */
124             case 2:
125                 onCancelResourceResult(notification.getServiceName());
126                 break;
127             default:
128                 break;
129         }
130     }
131
132     /**
133      * Process path computation request result.
134      * @param notification the result notification.
135      */
136     private void onPathComputationResult(ServicePathRpcResult notification) {
137         this.connectionFullMap.clear();
138         LOG.info("PCE '{}' Notification received : {}",servicePathRpcResult.getNotificationType().getName(),
139             notification);
140         if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) {
141             LOG.error("PCE path computation failed !");
142             return;
143         } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) {
144             LOG.warn("PCE path computation returned a Penging RpcStatusEx code!");
145             return;
146         } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) {
147             LOG.error("PCE path computation returned an unknown RpcStatusEx code!");
148             return;
149         }
150
151         LOG.info("PCE calculation done OK !");
152         if (servicePathRpcResult.getPathDescription() == null) {
153             LOG.error("'PathDescription' parameter is null ");
154             return;
155         }
156         PathDescription pathDescription = new PathDescriptionBuilder()
157             .setAToZDirection(servicePathRpcResult.getPathDescription().getAToZDirection())
158             .setZToADirection(servicePathRpcResult.getPathDescription().getZToADirection())
159             .build();
160         LOG.info("PathDescription for TAPI gets : {}", pathDescription);
161         if (input == null) {
162             LOG.error("Input is null !");
163             return;
164         }
165         // TODO: check kind of service: based on the device Id of the input,
166         //  verify the type of XPDR and the capacity and determine if it is an OTN service or pure WDM service
167         // Create connections and ceps for the connectivity service.
168         //  Connections must be with a locked stated. As the renderer hasnt implemented yet the oc's
169         Map<ConnectionKey, Connection> connectionMap = createConnectionsAndCepsForService(pathDescription,
170             input.getConnectivityConstraint().getServiceLayer());
171         // add connections to connection context and to connectivity context
172         updateConnectionContextWithConn(this.connectionFullMap, connectionMap, serviceUuid);
173     }
174
175     private Map<ConnectionKey, Connection> createConnectionsAndCepsForService(PathDescription pathDescription,
176                                                                               LayerProtocolName serviceProtName) {
177         Map<ConnectionKey, Connection> connectionServMap = new HashMap<>();
178         // build lists with ROADM nodes, XPDR/MUX/SWITCH nodes, ROADM DEG TTPs, ROADM SRG TTPs, XPDR CLIENT TTPs
179         //  and XPDR NETWORK TTPs (if any). From the path description. This will help to build the uuid of the CEPs
180         //  and the connections
181         String resourceType;
182         List<String> xpdrClientTplist = new ArrayList<>();
183         List<String> xpdrNetworkTplist = new ArrayList<>();
184         List<String> rdmAddDropTplist = new ArrayList<>();
185         List<String> rdmDegTplist = new ArrayList<>();
186         List<String> rdmNodelist = new ArrayList<>();
187         List<String> xpdrNodelist = new ArrayList<>();
188         for (AToZ elem:pathDescription.getAToZDirection().getAToZ().values().stream()
189             .sorted((Comparator.comparing(atoz -> Integer.valueOf(atoz.getId())))).collect(Collectors.toList())) {
190             resourceType = elem.getResource().getResource().implementedInterface().getSimpleName();
191             switch (resourceType) {
192                 case TapiStringConstants.TP:
193                     TerminationPoint tp = (TerminationPoint) elem.getResource().getResource();
194                     String tpID = tp.getTpId();
195                     String tpNode;
196                     if (tpID.contains("CLIENT")) {
197                         tpNode = tp.getTpNodeId();
198                         if (!xpdrClientTplist.contains(String.join("+", tpNode, tpID))) {
199                             xpdrClientTplist.add(String.join("+", tpNode, tpID));
200                         }
201                     }
202                     if (tpID.contains("NETWORK")) {
203                         tpNode = tp.getTpNodeId();
204                         if (!xpdrNetworkTplist.contains(String.join("+", tpNode, tpID))) {
205                             xpdrNetworkTplist.add(String.join("+", tpNode, tpID));
206                         }
207                     }
208                     if (tpID.contains("PP")) {
209                         tpNode = getIdBasedOnModelVersion(tp.getTpNodeId());
210                         LOG.info("ROADM Node of tp = {}", tpNode);
211                         if (!rdmAddDropTplist.contains(String.join("+", tpNode, tpID))) {
212                             rdmAddDropTplist.add(String.join("+", tpNode, tpID));
213                         }
214                     }
215                     if (tpID.contains("TTP")) {
216                         tpNode = getIdBasedOnModelVersion(tp.getTpNodeId());
217                         LOG.info("ROADM Node of tp = {}", tpNode);
218                         if (!rdmDegTplist.contains(String.join("+", tpNode, tpID))) {
219                             rdmDegTplist.add(String.join("+", tpNode, tpID));
220                         }
221                     }
222                     break;
223                 case TapiStringConstants.NODE:
224                     Node node = (Node) elem.getResource().getResource();
225                     String nodeId = node.getNodeId();
226                     if (nodeId.contains("XPDR") || nodeId.contains("SPDR") || nodeId.contains("MXPDR")) {
227                         LOG.info("Node id = {}", nodeId);
228                         if (!xpdrNodelist.contains(nodeId)) {
229                             xpdrNodelist.add(nodeId); // should contain only 2
230                         }
231                     }
232                     if (nodeId.contains("ROADM")) {
233                         nodeId = getIdBasedOnModelVersion(nodeId);
234                         LOG.info("Node id = {}", nodeId);
235                         if (!rdmNodelist.contains(nodeId)) {
236                             rdmNodelist.add(nodeId);
237                         }
238                     }
239                     break;
240                 default:
241                     LOG.warn("Resource is a {}", resourceType);
242             }
243         }
244         LOG.info("ROADM node list = {}", rdmNodelist.toString());
245         LOG.info("ROADM degree list = {}", rdmDegTplist.toString());
246         LOG.info("ROADM addrop list = {}", rdmAddDropTplist.toString());
247         LOG.info("XPDR node list = {}", xpdrNodelist.toString());
248         LOG.info("XPDR network list = {}", xpdrNetworkTplist.toString());
249         LOG.info("XPDR client list = {}", xpdrClientTplist.toString());
250         // TODO -> for 10GB eth and ODU services there are no ROADMs in path description as they use the OTU link,
251         //  but for 100GB eth all is created at once. Check if the roadm list is empty to determine whether we need
252         //  to trigger all the steps or not
253         String edgeRoadm1 = "";
254         String edgeRoadm2 = "";
255         if (!rdmNodelist.isEmpty()) {
256             edgeRoadm1 = rdmNodelist.get(0);
257             edgeRoadm2 = rdmNodelist.get(rdmNodelist.size() - 1);
258             LOG.info("edgeRoadm1 = {}", edgeRoadm1);
259             LOG.info("edgeRoadm2 = {}", edgeRoadm2);
260         }
261         // create corresponding CEPs and Connections. Connections should be added to the corresponding context
262         // CEPs must be included in the topology context as an augmentation for each ONEP!!
263         // TODO -> Maybe we dont need to create the connections and ceps if the previous service doesnt exist??
264         //  As mentioned above, for 100GbE service creation there are ROADMs in the path description.
265         //  What are the configurations needed here? No OTU, ODU... what kind of cross connections is needed?
266         //  this needs to be changed
267
268         // TODO: OpenROADM getNodeType from the NamesList to verify what needs to be created
269         OpenroadmNodeType openroadmNodeType = getOpenRoadmNodeType(xpdrNodelist);
270         switch (serviceProtName) {
271             case PHOTONICMEDIA:
272                 // Identify number of ROADMs
273                 // - XC Connection between MC CEPs mapped from MC NEPs (within a roadm)
274                 // - XC Connection between OTSiMC CEPs mapped from OTSiMC NEPs (within a roadm)
275                 // - Top Connection MC betwwen MC CEPs of different roadms
276                 // - Top Connection OTSiMC betwwen OTSiMC CEPs of extreme roadms
277                 connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
278                     edgeRoadm1, edgeRoadm2));
279                 if (!pathDescription.getAToZDirection().getAToZ().values().stream().findFirst().orElseThrow().getId()
280                         .contains("ROADM")) {
281                     // - XC Connection OTSi betwwen iOTSi y eOTSi of xpdr
282                     // - Top connection OTSi between network ports of xpdrs in the Photonic media layer -> i_OTSi
283                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
284                     this.topConnRdmRdm = null;
285                 }
286                 break;
287             case ODU:
288                 // TODO: verify if this is correct
289                 LOG.info("OTN ODU service");
290                 // - XC Connection OTSi between iODU and eODU of xpdr
291                 // - Top connection in the ODU layer, between xpdr iODU ports
292                 if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
293                     connectionServMap.putAll(createXpdrCepsAndConnectionsOdu(xpdrNetworkTplist, xpdrNodelist));
294                     this.topConnXpdrXpdrPhtn = null;
295                 }
296                 break;
297             case ETH:
298                 LOG.info("WDM service");
299                 if (openroadmNodeType.equals(OpenroadmNodeType.TPDR)) {
300                     // TODO: WDM service. Only och/otu4 needed and then directly DSR top connection.
301                     //  Need to find the associated client ports of the network port
302                     // - Same as for PHOTONIC MEDIA service
303                     // - Do we nedd cross connection in the ODU layer??
304                     // - Top connection DSR between client ports of the transponder
305                     connectionServMap.putAll(createRoadmCepsAndConnections(rdmAddDropTplist, rdmDegTplist, rdmNodelist,
306                         edgeRoadm1, edgeRoadm2));
307                     connectionServMap.putAll(createXpdrCepsAndConnectionsPht(xpdrNetworkTplist, xpdrNodelist));
308                     this.topConnRdmRdm = null;
309                     xpdrClientTplist = getAssociatedClientsPort(xpdrNetworkTplist);
310                     LOG.info("Associated client ports = {}", xpdrClientTplist);
311                     connectionServMap.putAll(createXpdrCepsAndConnectionsEth(xpdrClientTplist, xpdrNodelist,
312                         connectionServMap));
313                     this.topConnXpdrXpdrPhtn = null;
314                 }
315                 break;
316             case DSR:
317                 LOG.info("OTN XGE/ODUe service");
318                 // - XC connection between iODU and eODU
319                 // - Top connection between eODU ports
320                 // - Top connection between DSR ports
321                 if (openroadmNodeType.equals(OpenroadmNodeType.SWITCH)) {
322                     // TODO: We create both ODU and DSR because there is no ODU service creation for the switch
323                     // - XC Connection OTSi betwwen iODU and eODU of xpdr
324                     // - Top connection in the ODU layer, between xpdr eODU ports (?)
325                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
326                         xpdrNodelist));
327                     this.topConnXpdrXpdrPhtn = null;
328                 }
329                 if (openroadmNodeType.equals(OpenroadmNodeType.MUXPDR)) {
330                     // TODO: OTN service but mux has 3 steps at rendering. Verify that things exist
331                     connectionServMap.putAll(createXpdrCepsAndConnectionsDsr(xpdrClientTplist, xpdrNetworkTplist,
332                         xpdrNodelist));
333                     this.topConnXpdrXpdrOdu = null;
334                 }
335                 break;
336             default:
337                 LOG.error("Service type format {} not supported", serviceProtName.getName());
338         }
339         return connectionServMap;
340     }
341
342     /**
343      * Process cancel resource result.
344      * @param serviceName Service name to build uuid.
345      */
346     private void onCancelResourceResult(String serviceName) {
347         if (servicePathRpcResult.getStatus() == RpcStatusEx.Failed) {
348             LOG.info("PCE cancel resource failed !");
349             return;
350         } else if (servicePathRpcResult.getStatus() == RpcStatusEx.Pending) {
351             LOG.warn("PCE cancel returned a Penging RpcStatusEx code!");
352             return;
353         } else if (servicePathRpcResult.getStatus() != RpcStatusEx.Successful) {
354             LOG.error("PCE cancel returned an unknown RpcStatusEx code!");
355             return;
356         }
357         LOG.info("PCE cancel resource done OK !");
358         Uuid suuid = new Uuid(UUID.nameUUIDFromBytes(serviceName.getBytes(Charset.forName("UTF-8")))
359             .toString());
360         // get connections of connectivity service and remove them from tapi context and then remove
361         //  service from context. The CEPs are maintained as they could be reused by another service
362         ConnectivityService connService = getConnectivityService(suuid);
363         if (connService == null) {
364             LOG.error("Service doesnt exist in tapi context");
365             return;
366         }
367         for (Connection connection:connService.getConnection().values()) {
368             deleteConnection(connection.getConnectionUuid());
369         }
370         deleteConnectivityService(suuid);
371     }
372
373     @SuppressFBWarnings(
374         value = "ES_COMPARING_STRINGS_WITH_EQ",
375         justification = "false positives, not strings but real object references comparisons")
376     private Boolean compareServicePathRpcResult(ServicePathRpcResult notification) {
377         if (servicePathRpcResult == null) {
378             return false;
379         }
380         if (servicePathRpcResult.getNotificationType() != notification.getNotificationType()) {
381             return false;
382         }
383         if (servicePathRpcResult.getServiceName() != notification.getServiceName()) {
384             return false;
385         }
386         if (servicePathRpcResult.getStatus() != notification.getStatus()) {
387             return false;
388         }
389         if (servicePathRpcResult.getStatusMessage() != notification.getStatusMessage()) {
390             return false;
391         }
392         return true;
393     }
394
395     private Map<ConnectionKey, Connection> createXpdrCepsAndConnectionsEth(List<String> xpdrClientTplist,
396                                                                            List<String> xpdrNodelist,
397                                                                            Map<ConnectionKey, Connection> lowerConn) {
398         // TODO: do we need to create cross connection between iODU and eODU??
399         // add the lower connections of the previous steps for this kind of service
400         Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
401         for (Connection lowConn: lowerConn.values()) {
402             LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(lowConn.getConnectionUuid()).build();
403             xcMap.put(conn.key(), conn);
404         }
405         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
406         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
407             ConnectionEndPoint> cepMapDsr = new HashMap<>();
408         // Create 1 cep per Xpdr in the CLIENT
409         // 1 top connection DSR between the CLIENT xpdrs
410         for (String xpdr:xpdrNodelist) {
411             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
412             String spcXpdrClient = xpdrClientTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst()
413                     .orElseThrow();
414             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR,
415                 LayerProtocolName.DSR);
416             putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, netCep1);
417
418             cepMapDsr.put(netCep1.key(), netCep1);
419         }
420         String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
421             .get(0))).findFirst().orElseThrow();
422         String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
423             .get(xpdrNodelist.size() - 1))).findFirst().orElseThrow();
424
425         // DSR top connection between edge xpdr CLIENT DSR
426         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
427             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
428                 LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
429         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
430
431         // DSR top connection that will be added to the service object
432         Connection conn1 = new ConnectionBuilder().setConnectionUuid(connectionDsr.getUuid()).build();
433         connServMap.put(conn1.key(), conn1);
434
435         return connServMap;
436     }
437
438     private Map<ConnectionKey,Connection> createXpdrCepsAndConnectionsDsr(List<String> xpdrClientTplist,
439                                                                           List<String> xpdrNetworkTplist,
440                                                                           List<String> xpdrNodelist) {
441         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
442         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
443             ConnectionEndPoint> cepMapDsr = new HashMap<>();
444         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
445             ConnectionEndPoint> cepMapOdu = new HashMap<>();
446         // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will
447         //  be added to the lower connection of a top connection
448         Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
449
450         // Create 1 cep per Xpdr in the CLIENT, 1 cep per Xpdr eODU, 1 XC between eODU and iODE,
451         // 1 top connection between eODU and a top connection DSR between the CLIENT xpdrs
452         for (String xpdr:xpdrNodelist) {
453             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
454             String spcXpdrClient = xpdrClientTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst()
455                     .orElseThrow();
456             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR,
457                 LayerProtocolName.DSR);
458             putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.DSR, TapiStringConstants.DSR, netCep1);
459
460             ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrClient, TapiStringConstants.E_ODU,
461                 TapiStringConstants.DSR, LayerProtocolName.ODU);
462             putXpdrCepInTopologyContext(xpdr, spcXpdrClient, TapiStringConstants.E_ODU, TapiStringConstants.DSR,
463                 netCep2);
464
465             String spcXpdrNetwork = getAssociatedNetworkPort(spcXpdrClient, xpdrNetworkTplist);
466             ConnectionEndPoint netCep3 = getAssociatediODUCep(spcXpdrNetwork);
467
468             cepMapDsr.put(netCep1.key(), netCep1);
469             cepMapOdu.put(netCep2.key(), netCep2);
470             // Create x connection between I_ODU and E_ODU within xpdr
471             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
472                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrClient, spcXpdrNetwork,
473                     TapiStringConstants.ODU, LayerProtocolName.ODU);
474             this.connectionFullMap.put(connection.key(), connection);
475
476             // Create X connection that will be added to the service object
477             LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
478             xcMap.put(conn.key(), conn);
479         }
480
481         String spcXpdr1 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
482             .get(0))).findFirst().orElseThrow();
483         String spcXpdr2 = xpdrClientTplist.stream().filter(adp -> adp.contains(xpdrNodelist
484             .get(xpdrNodelist.size() - 1))).findFirst().orElseThrow();
485
486         // eODU top connection between edge xpdr CLIENT eODU
487         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
488             connectionOdu = createTopConnection(spcXpdr1, spcXpdr2, cepMapOdu, TapiStringConstants.E_ODU,
489                 LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrOdu);
490         this.connectionFullMap.put(connectionOdu.key(), connectionOdu);
491
492         // ODU top connection that will be added to the service object and also lower connection
493         Connection conn = new ConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build();
494         connServMap.put(conn.key(), conn);
495         LowerConnection lowerConn = new LowerConnectionBuilder().setConnectionUuid(connectionOdu.getUuid()).build();
496         xcMap.put(lowerConn.key(), lowerConn);
497
498         // DSR top connection between edge xpdr CLIENT DSR
499         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
500             connectionDsr = createTopConnection(spcXpdr1, spcXpdr2, cepMapDsr, TapiStringConstants.DSR,
501                 LayerProtocolName.DSR, xcMap, this.topConnXpdrXpdrPhtn);
502         this.connectionFullMap.put(connectionDsr.key(), connectionDsr);
503
504         // DSR top connection that will be added to the service object
505         Connection conn1 = new ConnectionBuilder().setConnectionUuid(connectionDsr.getUuid()).build();
506         connServMap.put(conn1.key(), conn1);
507
508         return connServMap;
509     }
510
511     private Map<ConnectionKey, Connection> createXpdrCepsAndConnectionsOdu(List<String> xpdrNetworkTplist,
512                                                                            List<String> xpdrNodelist) {
513         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
514         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
515             ConnectionEndPoint> cepMap = new HashMap<>();
516         // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will
517         //  be added to the lower connection of a top connection
518         Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
519         // Create 1 cep per Xpdr in the I_ODU and a top
520         // connection iODU between the xpdrs
521         for (String xpdr:xpdrNodelist) {
522             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
523             String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst()
524                     .orElseThrow();
525             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.I_ODU,
526                 TapiStringConstants.DSR, LayerProtocolName.ODU);
527             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.I_ODU, TapiStringConstants.DSR,
528                 netCep1);
529
530             cepMap.put(netCep1.key(), netCep1);
531         }
532
533         // ODU top connection between edge xpdr i_ODU
534         String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
535             .get(0))).findFirst().orElseThrow();
536         String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
537             .get(xpdrNodelist.size() - 1))).findFirst().orElseThrow();
538         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
539             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_ODU,
540                 LayerProtocolName.ODU, xcMap, this.topConnXpdrXpdrPhtn);
541         this.connectionFullMap.put(connection.key(), connection);
542
543         // ODU top connection that will be added to the service object
544         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
545         connServMap.put(conn.key(), conn);
546         this.topConnXpdrXpdrOdu = conn;
547
548         return connServMap;
549     }
550
551     private Map<ConnectionKey, Connection> createXpdrCepsAndConnectionsPht(List<String> xpdrNetworkTplist,
552                                                                            List<String> xpdrNodelist) {
553         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
554         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
555             ConnectionEndPoint> cepMap = new HashMap<>();
556         // TODO: when upgrading the models to 2.1.3, get the connection inclusion because those connections will
557         //  be added to the lower connection of a top connection
558         Map<LowerConnectionKey, LowerConnection> xcMap = new HashMap<>();
559
560         // create ceps and xc connections within xpdr
561         for (String xpdr:xpdrNodelist) {
562             LOG.info("Creating ceps and xc for xpdr {}", xpdr);
563             String spcXpdrNetwork = xpdrNetworkTplist.stream().filter(netp -> netp.contains(xpdr)).findFirst()
564                 .orElseThrow();
565             // There should be 1 network tp per xpdr
566             // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
567             //  3 different MC CEPs giving different IDs to show that they are different
568             // Create 3 CEPs for each xpdr otsi node and the corresponding cross connection matchin the NEPs
569             ConnectionEndPoint netCep1 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.PHTNC_MEDIA,
570                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
571             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.PHTNC_MEDIA, TapiStringConstants.OTSI,
572                 netCep1);
573             ConnectionEndPoint netCep2 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.E_OTSI,
574                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
575             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.E_OTSI, TapiStringConstants.OTSI,
576                 netCep2);
577             ConnectionEndPoint netCep3 = createCepXpdr(spcXpdrNetwork, TapiStringConstants.I_OTSI,
578                 TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
579             putXpdrCepInTopologyContext(xpdr, spcXpdrNetwork, TapiStringConstants.I_OTSI, TapiStringConstants.OTSI,
580                 netCep3);
581             cepMap.put(netCep1.key(), netCep1);
582             cepMap.put(netCep2.key(), netCep2);
583             cepMap.put(netCep3.key(), netCep3);
584
585             // Create x connection between I_OTSi and E_OTSi within xpdr
586             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
587                 connection = createXCBetweenCeps(netCep2, netCep3, spcXpdrNetwork, spcXpdrNetwork,
588                     TapiStringConstants.OTSI, LayerProtocolName.PHOTONICMEDIA);
589             this.connectionFullMap.put(connection.key(), connection);
590
591             // Create X connection that will be added to the service object
592             LowerConnection conn = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
593             xcMap.put(conn.key(), conn);
594         }
595         // OTSi top connection between edge I_OTSI Xpdr
596         String spcXpdr1 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
597             .get(0))).findFirst().orElseThrow();
598         String spcXpdr2 = xpdrNetworkTplist.stream().filter(adp -> adp.contains(xpdrNodelist
599             .get(xpdrNodelist.size() - 1))).findFirst().orElseThrow();
600         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
601             connection = createTopConnection(spcXpdr1, spcXpdr2, cepMap, TapiStringConstants.I_OTSI,
602                 LayerProtocolName.PHOTONICMEDIA, xcMap, this.topConnRdmRdm);
603         this.connectionFullMap.put(connection.key(), connection);
604
605         // OTSi top connection that will be added to the service object
606         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
607         connServMap.put(conn.key(), conn);
608         this.topConnXpdrXpdrPhtn = conn;
609         return connServMap;
610     }
611
612     private Map<ConnectionKey, Connection> createRoadmCepsAndConnections(List<String> rdmAddDropTplist,
613                                                                          List<String> rdmDegTplist,
614                                                                          List<String> rdmNodelist,
615                                                                          String edgeRoadm1, String edgeRoadm2) {
616         // TODO: will need to check if things exist already or not
617         Map<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
618             ConnectionEndPoint> cepMap = new HashMap<>();
619         // create ceps and x connections within roadm
620         Map<LowerConnectionKey, LowerConnection> xcLowerMap = new HashMap<>();
621         for (String roadm : rdmNodelist) {
622             LOG.info("Creating ceps and xc for roadm {}", roadm);
623             if (roadm.equals(edgeRoadm1) || roadm.equals(edgeRoadm2)) {
624                 LOG.info("EDGE ROADM, cross connections needed between SRG and DEG");
625                 String spcRdmAD = rdmAddDropTplist.stream().filter(adp -> adp.contains(roadm)).findFirst()
626                     .orElseThrow();
627                 LOG.info("AD port of ROADm {} = {}", roadm, spcRdmAD);
628                 // There should be only 1 AD and 1 DEG per roadm
629                 // TODO photonic media model should be updated to have the corresponding CEPs. I will just create
630                 //  3 different MC CEPs giving different IDs to show that they are different
631                 // Create 3 CEPs for each AD and DEG and the corresponding cross connections, matching the NEPs
632                 // created in the topology creation
633                 // add CEPs to the topology to the corresponding ONEP
634                 ConnectionEndPoint adCep1 = createCepRoadm(spcRdmAD, TapiStringConstants.PHTNC_MEDIA);
635                 putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.PHTNC_MEDIA, adCep1);
636                 ConnectionEndPoint adCep2 = createCepRoadm(spcRdmAD, TapiStringConstants.MC);
637                 putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.MC, adCep2);
638                 ConnectionEndPoint adCep3 = createCepRoadm(spcRdmAD, TapiStringConstants.OTSI_MC);
639                 putRdmCepInTopologyContext(roadm, spcRdmAD, TapiStringConstants.OTSI_MC, adCep3);
640                 cepMap.put(adCep1.key(), adCep1);
641                 cepMap.put(adCep2.key(), adCep2);
642                 cepMap.put(adCep3.key(), adCep3);
643
644                 String spcRdmDEG = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().orElseThrow();
645                 LOG.info("Degree port of ROADm {} = {}", roadm, spcRdmDEG);
646
647                 ConnectionEndPoint degCep1 = createCepRoadm(spcRdmDEG, TapiStringConstants.PHTNC_MEDIA);
648                 putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.PHTNC_MEDIA, degCep1);
649                 ConnectionEndPoint degCep2 = createCepRoadm(spcRdmDEG, TapiStringConstants.MC);
650                 putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.MC, degCep2);
651                 ConnectionEndPoint degCep3 = createCepRoadm(spcRdmDEG, TapiStringConstants.OTSI_MC);
652                 putRdmCepInTopologyContext(roadm, spcRdmDEG, TapiStringConstants.OTSI_MC, degCep3);
653                 cepMap.put(degCep1.key(), degCep1);
654                 cepMap.put(degCep2.key(), degCep2);
655                 cepMap.put(degCep3.key(), degCep3);
656
657                 LOG.info("Going to create cross connections for ROADM {}", roadm);
658                 // Create X connections between MC and OTSi_MC for full map
659                 org.opendaylight.yang.gen.v1.urn
660                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
661                     = createXCBetweenCeps(adCep2, degCep2, spcRdmAD, spcRdmDEG, TapiStringConstants.MC,
662                         LayerProtocolName.PHOTONICMEDIA);
663                 LOG.info("Cross connection 1 created = {}", connection1.toString());
664                 org.opendaylight.yang.gen.v1.urn
665                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
666                     = createXCBetweenCeps(adCep3, degCep3, spcRdmAD, spcRdmDEG, TapiStringConstants.OTSI_MC,
667                         LayerProtocolName.PHOTONICMEDIA);
668                 LOG.info("Cross connection 2 created = {}", connection2.toString());
669                 this.connectionFullMap.put(connection1.key(), connection1);
670                 this.connectionFullMap.put(connection2.key(), connection2);
671
672                 // Create X connections that will be added to the service object
673                 LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
674                 LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
675
676                 xcLowerMap.put(conn1.key(), conn1);
677                 xcLowerMap.put(conn2.key(), conn2);
678             } else {
679                 LOG.info("MIDDLE ROADM, cross connections needed between DEG and DEG");
680                 String spcRdmDEG1 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).findFirst().orElseThrow();
681                 LOG.info("Degree 1 port of ROADm {} = {}", roadm, spcRdmDEG1);
682
683                 ConnectionEndPoint deg1Cep1 = createCepRoadm(spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA);
684                 putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.PHTNC_MEDIA, deg1Cep1);
685                 ConnectionEndPoint deg1Cep2 = createCepRoadm(spcRdmDEG1, TapiStringConstants.MC);
686                 putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.MC, deg1Cep2);
687                 ConnectionEndPoint deg1Cep3 = createCepRoadm(spcRdmDEG1, TapiStringConstants.OTSI_MC);
688                 putRdmCepInTopologyContext(roadm, spcRdmDEG1, TapiStringConstants.OTSI_MC, deg1Cep3);
689                 cepMap.put(deg1Cep1.key(), deg1Cep1);
690                 cepMap.put(deg1Cep2.key(), deg1Cep2);
691                 cepMap.put(deg1Cep3.key(), deg1Cep3);
692
693                 String spcRdmDEG2 = rdmDegTplist.stream().filter(adp -> adp.contains(roadm)).skip(1).findFirst()
694                     .orElseThrow();
695                 LOG.info("Degree 2 port of ROADm {} = {}", roadm, spcRdmDEG2);
696
697                 ConnectionEndPoint deg2Cep1 = createCepRoadm(spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA);
698                 putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.PHTNC_MEDIA, deg2Cep1);
699                 ConnectionEndPoint deg2Cep2 = createCepRoadm(spcRdmDEG2, TapiStringConstants.MC);
700                 putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.MC, deg2Cep2);
701                 ConnectionEndPoint deg2Cep3 = createCepRoadm(spcRdmDEG2, TapiStringConstants.OTSI_MC);
702                 putRdmCepInTopologyContext(roadm, spcRdmDEG2, TapiStringConstants.OTSI_MC, deg2Cep3);
703                 cepMap.put(deg2Cep1.key(), deg2Cep1);
704                 cepMap.put(deg2Cep2.key(), deg2Cep2);
705                 cepMap.put(deg2Cep3.key(), deg2Cep3);
706
707                 LOG.info("Going to create cross connections for ROADM {}", roadm);
708                 // Create X connections between MC and OTSi_MC for full map
709                 org.opendaylight.yang.gen.v1.urn
710                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection1
711                     = createXCBetweenCeps(deg1Cep2, deg2Cep2, spcRdmDEG1, spcRdmDEG2,
712                         TapiStringConstants.MC, LayerProtocolName.PHOTONICMEDIA);
713                 LOG.info("Cross connection 1 created = {}", connection1.toString());
714                 org.opendaylight.yang.gen.v1.urn
715                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection connection2
716                     = createXCBetweenCeps(deg1Cep3, deg2Cep3, spcRdmDEG1, spcRdmDEG2,
717                         TapiStringConstants.OTSI_MC, LayerProtocolName.PHOTONICMEDIA);
718                 LOG.info("Cross connection 2 created = {}", connection2.toString());
719                 this.connectionFullMap.put(connection1.key(), connection1);
720                 this.connectionFullMap.put(connection2.key(), connection2);
721
722                 // Create X connections that will be added to the service object
723                 LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
724                 LowerConnection conn2 = new LowerConnectionBuilder().setConnectionUuid(connection2.getUuid()).build();
725
726                 xcLowerMap.put(conn1.key(), conn1);
727                 xcLowerMap.put(conn2.key(), conn2);
728             }
729         }
730         LOG.info("Going to create top connections between roadms");
731         String spcRdmAD1 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm1)).findFirst().orElseThrow();
732         String spcRdmAD2 = rdmAddDropTplist.stream().filter(adp -> adp.contains(edgeRoadm2)).findFirst().orElseThrow();
733         // MC top connection between edge roadms
734         LOG.info("Going to created top connection between MC");
735         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
736             connection = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.MC,
737                 LayerProtocolName.PHOTONICMEDIA, xcLowerMap, null);
738         this.connectionFullMap.put(connection.key(), connection);
739         LOG.info("Top connection created = {}", connection.toString());
740
741         Map<ConnectionKey, Connection> connServMap = new HashMap<>();
742         // OTSiMC top connections that will be added to the service object
743         Connection conn = new ConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
744         connServMap.put(conn.key(), conn);
745         LowerConnection conn1 = new LowerConnectionBuilder().setConnectionUuid(connection.getUuid()).build();
746         Map<LowerConnectionKey, LowerConnection> topLowerMap = new HashMap<>();
747         topLowerMap.put(conn1.key(), conn1);
748
749         // OTSiMC top connection between edge roadms
750         LOG.info("Going to created top connection between OTSiMC");
751         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
752             connection1 = createTopConnection(spcRdmAD1, spcRdmAD2, cepMap, TapiStringConstants.OTSI_MC,
753                 LayerProtocolName.PHOTONICMEDIA, topLowerMap, null);
754         this.connectionFullMap.put(connection1.key(), connection1);
755         LOG.info("Top connection created = {}", connection1.toString());
756
757         // OTSiMC top connections that will be added to the service object
758         Connection conn2 = new ConnectionBuilder().setConnectionUuid(connection1.getUuid()).build();
759         connServMap.put(conn2.key(), conn2);
760         this.topConnRdmRdm = conn2;
761         return connServMap;
762     }
763
764     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
765             createTopConnection(String tp1, String tp2,
766                         Map<org.opendaylight.yang.gen.v1.urn
767                             .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey,
768                             ConnectionEndPoint> cepMap, String qual, LayerProtocolName topPortocol,
769                         Map<LowerConnectionKey, LowerConnection> xcMap, Connection additionalLowerConn) {
770         // find cep for each AD MC of roadm 1 and 2
771         LOG.info("Top connection name = {}", String.join("+", "TOP", tp1, tp2, qual));
772         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep1 =
773             cepMap.get(new org.opendaylight.yang.gen.v1.urn
774                     .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
775                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp1.split("\\+")[0],
776                         qual, tp1.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
777                     .toString())));
778         LOG.info("ADCEP1 = {}", adCep1.toString());
779         org.opendaylight.yang.gen.v1.urn
780                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep1 =
781             new org.opendaylight.yang.gen.v1.urn
782                     .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
783                 .setNodeEdgePointUuid(adCep1.getClientNodeEdgePoint()
784                     .values().stream().findFirst().orElseThrow().getNodeEdgePointUuid())
785                 .setTopologyUuid(adCep1.getClientNodeEdgePoint()
786                     .values().stream().findFirst().orElseThrow().getTopologyUuid())
787                 .setNodeUuid(adCep1.getClientNodeEdgePoint()
788                     .values().stream().findFirst().orElseThrow().getNodeUuid())
789                 .setConnectionEndPointUuid(adCep1.getUuid())
790                 .build();
791         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.ConnectionEndPoint adCep2 =
792             cepMap.get(new org.opendaylight.yang.gen.v1.urn
793                     .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(
794                 new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", tp2.split("\\+")[0],
795                         qual, tp2.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
796                     .toString())));
797         LOG.info("ADCEP2 = {}", adCep2.toString());
798         org.opendaylight.yang.gen.v1.urn
799                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cep2 =
800             new org.opendaylight.yang.gen.v1.urn
801                     .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
802                 .setNodeEdgePointUuid(adCep2.getClientNodeEdgePoint()
803                     .values().stream().findFirst().orElseThrow().getNodeEdgePointUuid())
804                 .setTopologyUuid(adCep2.getClientNodeEdgePoint()
805                     .values().stream().findFirst().orElseThrow().getTopologyUuid())
806                 .setNodeUuid(adCep2.getClientNodeEdgePoint()
807                     .values().stream().findFirst().orElseThrow().getNodeUuid())
808                 .setConnectionEndPointUuid(adCep1.getUuid())
809                 .build();
810         Map<ConnectionEndPointKey, org.opendaylight.yang.gen.v1.urn
811             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ceps = new HashMap<>();
812         ceps.put(cep1.key(), cep1);
813         ceps.put(cep2.key(), cep2);
814         Name connName = new NameBuilder()
815             .setValueName("Connection name")
816             .setValue(String.join("+", "TOP", tp1, tp2, qual))
817             .build();
818         // TODO: lower connection, supported link.......
819         if (additionalLowerConn != null) {
820             xcMap.putIfAbsent(new LowerConnectionKey(additionalLowerConn.getConnectionUuid()),
821                 new LowerConnectionBuilder().setConnectionUuid(additionalLowerConn.getConnectionUuid()).build());
822         }
823         return new org.opendaylight.yang.gen.v1.urn
824                 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
825             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "TOP", tp1, tp2, qual))
826                 .getBytes(Charset.forName("UTF-8"))).toString()))
827             .setName(Map.of(connName.key(), connName))
828             .setConnectionEndPoint(ceps)
829             .setOperationalState(OperationalState.DISABLED)
830             .setLayerProtocolName(topPortocol)
831             .setLifecycleState(LifecycleState.POTENTIALAVAILABLE)
832             .setDirection(ForwardingDirection.BIDIRECTIONAL)
833             .setLowerConnection(xcMap)
834             .build();
835     }
836
837     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection
838             createXCBetweenCeps(ConnectionEndPoint cep1, ConnectionEndPoint cep2, String tp1, String tp2, String qual,
839                         LayerProtocolName xcProtocol) {
840         LOG.info("Creation cross connection between: {} and {}", tp1, tp2);
841         LOG.info("Cross connection name = {}", String.join("+", "XC", tp1, tp2, qual));
842         LOG.info("CEP1 = {}", cep1.getClientNodeEdgePoint().toString());
843         LOG.info("CEP2 = {}", cep2.getClientNodeEdgePoint().toString());
844         org.opendaylight.yang.gen.v1.urn
845                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ1 =
846             new org.opendaylight.yang.gen.v1.urn
847                     .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
848                 .setNodeEdgePointUuid(cep1.getClientNodeEdgePoint()
849                     .values().stream().findFirst().orElseThrow().getNodeEdgePointUuid())
850                 .setTopologyUuid(cep1.getClientNodeEdgePoint()
851                     .values().stream().findFirst().orElseThrow().getTopologyUuid())
852                 .setNodeUuid(cep1.getClientNodeEdgePoint()
853                     .values().stream().findFirst().orElseThrow().getNodeUuid())
854                 .setConnectionEndPointUuid(cep1.getUuid())
855                 .build();
856         org.opendaylight.yang.gen.v1.urn
857                 .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint cepServ2 =
858             new org.opendaylight.yang.gen.v1.urn
859                     .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPointBuilder()
860                 .setNodeEdgePointUuid(cep2.getClientNodeEdgePoint()
861                     .values().stream().findFirst().orElseThrow().getNodeEdgePointUuid())
862                 .setTopologyUuid(cep2.getClientNodeEdgePoint()
863                     .values().stream().findFirst().orElseThrow().getTopologyUuid())
864                 .setNodeUuid(cep2.getClientNodeEdgePoint()
865                     .values().stream().findFirst().orElseThrow().getNodeUuid())
866                 .setConnectionEndPointUuid(cep2.getUuid())
867                 .build();
868         Map<ConnectionEndPointKey, org.opendaylight.yang.gen.v1.urn
869             .onf.otcc.yang.tapi.connectivity.rev181210.connection.ConnectionEndPoint> ceps = new HashMap<>();
870         ceps.put(cepServ1.key(), cepServ1);
871         ceps.put(cepServ2.key(), cepServ2);
872         Name connName = new NameBuilder()
873             .setValueName("Connection name")
874             .setValue(String.join("+", "XC", tp1, tp2, qual))
875             .build();
876         // TODO: lower connection, supported link.......
877         return new org.opendaylight.yang.gen.v1.urn
878                 .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionBuilder()
879             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "XC", tp1, tp2, qual))
880                 .getBytes(Charset.forName("UTF-8"))).toString()))
881             .setName(Map.of(connName.key(), connName))
882             .setConnectionEndPoint(ceps)
883             .setOperationalState(OperationalState.ENABLED)
884             .setLayerProtocolName(xcProtocol)
885             .setLifecycleState(LifecycleState.INSTALLED)
886             .setDirection(ForwardingDirection.BIDIRECTIONAL)
887             .build();
888     }
889
890     private ConnectionEndPoint createCepRoadm(String id, String qualifier) {
891         LOG.info("NEP = {}", String.join("+", id.split("\\+")[0], qualifier, id.split("\\+")[1]));
892         Name cepName = new NameBuilder()
893             .setValueName("ConnectionEndPoint name")
894             .setValue(String.join("+", id.split("\\+")[0], qualifier,
895                 id.split("\\+")[1]))
896             .build();
897         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
898             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
899                     qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
900                 .toString()))
901             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
902                     "PHOTONIC_MEDIA")).getBytes(Charset.forName("UTF-8")))
903                 .toString()))
904             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
905                 .getBytes(Charset.forName("UTF-8"))).toString()))
906             .build();
907         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
908         // TODO: add parent ONEP??
909         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
910             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
911                     qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
912                 .toString()))
913             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
914             .setName(Map.of(cepName.key(), cepName))
915             .setConnectionPortRole(PortRole.SYMMETRIC)
916             .setConnectionPortDirection(PortDirection.BIDIRECTIONAL)
917             .setOperationalState(OperationalState.ENABLED)
918             .setLifecycleState(LifecycleState.INSTALLED)
919             .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA);
920         return cepBldr.build();
921     }
922
923     private ConnectionEndPoint createCepXpdr(String id, String qualifier, String nodeLayer,
924                                              LayerProtocolName cepProtocol) {
925         Name cepName = new NameBuilder()
926             .setValueName("ConnectionEndPoint name")
927             .setValue(String.join("+", id.split("\\+")[0], qualifier,
928                 id.split("\\+")[1]))
929             .build();
930         ClientNodeEdgePoint cnep = new ClientNodeEdgePointBuilder()
931             .setNodeEdgePointUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", id.split("\\+")[0],
932                     qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
933                 .toString()))
934             .setNodeUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+",id.split("\\+")[0],
935                     nodeLayer)).getBytes(Charset.forName("UTF-8")))
936                 .toString()))
937             .setTopologyUuid(new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
938                 .getBytes(Charset.forName("UTF-8"))).toString()))
939             .build();
940         // TODO: add augmentation with the corresponding cep-spec (i.e. MC, OTSiMC...)
941         // TODO: add parent ONEP??
942         ConnectionEndPointBuilder cepBldr = new ConnectionEndPointBuilder()
943             .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP", id.split("\\+")[0],
944                     qualifier, id.split("\\+")[1])).getBytes(Charset.forName("UTF-8")))
945                 .toString()))
946             .setClientNodeEdgePoint(Map.of(cnep.key(), cnep))
947             .setName(Map.of(cepName.key(), cepName))
948             .setConnectionPortRole(PortRole.SYMMETRIC)
949             .setConnectionPortDirection(PortDirection.BIDIRECTIONAL)
950             .setOperationalState(OperationalState.ENABLED)
951             .setLifecycleState(LifecycleState.INSTALLED)
952             .setLayerProtocolName(cepProtocol);
953         return cepBldr.build();
954     }
955
956     private void putRdmCepInTopologyContext(String node, String spcRdmAD, String qual, ConnectionEndPoint cep) {
957         LOG.info("NEP id before Merge = {}", String.join("+", node, qual, spcRdmAD.split("\\+")[1]));
958         LOG.info("Node of NEP id before Merge = {}", String.join("+", node, TapiStringConstants.PHTNC_MEDIA));
959         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
960         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
961             .getBytes(Charset.forName("UTF-8"))).toString());
962         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, TapiStringConstants.PHTNC_MEDIA)
963             .getBytes(Charset.forName("UTF-8"))).toString());
964         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcRdmAD.split("\\+")[1])
965             .getBytes(Charset.forName("UTF-8"))).toString());
966         updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
967     }
968
969     private void putXpdrCepInTopologyContext(String node, String spcXpdrNet, String qual, String nodeLayer,
970                                              ConnectionEndPoint cep) {
971         // Give uuids so that it is easier to look for things: topology uuid, node uuid, nep uuid, cep
972         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
973             .getBytes(Charset.forName("UTF-8"))).toString());
974         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, nodeLayer)
975             .getBytes(Charset.forName("UTF-8"))).toString());
976         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes(String.join("+", node, qual, spcXpdrNet.split("\\+")[1])
977             .getBytes(Charset.forName("UTF-8"))).toString());
978         updateTopologyWithCep(topoUuid, nodeUuid, nepUuid, cep);
979     }
980
981     public void updateTopologyWithCep(Uuid topoUuid, Uuid nodeUuid, Uuid nepUuid, ConnectionEndPoint cep) {
982         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
983         InstanceIdentifier<OwnedNodeEdgePoint> onepIID = InstanceIdentifier.builder(Context.class)
984             .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class)
985             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class)
986             .child(Topology.class, new TopologyKey(topoUuid))
987             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
988                 new NodeKey(nodeUuid))
989             .child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid))
990             .build();
991         try {
992             Optional<OwnedNodeEdgePoint> optionalOnep = this.networkTransactionService.read(
993                 LogicalDatastoreType.OPERATIONAL, onepIID).get();
994             if (!optionalOnep.isPresent()) {
995                 LOG.error("ONEP is not present in datastore");
996                 return;
997             }
998             OwnedNodeEdgePoint onep = optionalOnep.orElseThrow();
999             LOG.info("ONEP found = {}", onep.toString());
1000             // TODO -> If cep exists -> skip merging to datasore
1001             OwnedNodeEdgePoint1 onep1 = onep.augmentation(OwnedNodeEdgePoint1.class);
1002             if (onep1 != null && onep1.getCepList() != null && onep1.getCepList().getConnectionEndPoint() != null) {
1003                 if (onep1.getCepList().getConnectionEndPoint().containsKey(
1004                         new org.opendaylight.yang.gen.v1
1005                             .urn.onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cep.key()))) {
1006                     LOG.info("CEP already in topology, skipping merge");
1007                     return;
1008                 }
1009             }
1010             // Updated ONEP
1011             CepList cepList = new CepListBuilder().setConnectionEndPoint(Map.of(cep.key(), cep)).build();
1012             OwnedNodeEdgePoint1 onep1Bldr = new OwnedNodeEdgePoint1Builder().setCepList(cepList).build();
1013             OwnedNodeEdgePoint newOnep = new OwnedNodeEdgePointBuilder(onep)
1014                 .addAugmentation(onep1Bldr)
1015                 .build();
1016             LOG.info("New ONEP is {}", newOnep.toString());
1017             // merge in datastore
1018             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, onepIID,
1019                 newOnep);
1020             this.networkTransactionService.commit().get();
1021             LOG.info("CEP added successfully.");
1022         } catch (InterruptedException | ExecutionException e) {
1023             LOG.error("Couldnt update cep in topology", e);
1024         }
1025     }
1026
1027     private void updateConnectionContextWithConn(
1028             Map<org.opendaylight.yang.gen.v1.urn
1029                     .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey,
1030                 org.opendaylight.yang.gen.v1.urn
1031                     .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connFullMap,
1032             Map<ConnectionKey, Connection> connMap, Uuid suuid) {
1033         // TODO: verify this is correct. Should we identify the context IID with the context UUID??
1034         try {
1035             ConnectivityService connServ = getConnectivityService(suuid);
1036             ConnectivityService updtConnServ = new ConnectivityServiceBuilder(connServ)
1037                 .setConnection(connMap)
1038                 .build();
1039
1040             // Perform the merge operation with the new conn service and the connection context updated
1041             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext
1042                 connectivityContext = new ConnectivityContextBuilder()
1043                     .setConnectivityService(Map.of(updtConnServ.key(), updtConnServ))
1044                     .setConnection(connFullMap)
1045                     .build();
1046             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
1047                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext> connectivitycontextIID =
1048                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
1049                     .child(org.opendaylight.yang.gen.v1.urn
1050                         .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
1051                     .build();
1052             // merge in datastore
1053             this.networkTransactionService.merge(LogicalDatastoreType.OPERATIONAL, connectivitycontextIID,
1054                 connectivityContext);
1055             this.networkTransactionService.commit().get();
1056             LOG.info("TAPI connectivity merged successfully.");
1057         } catch (InterruptedException | ExecutionException e) {
1058             LOG.error("Failed to merge TAPI connectivity", e);
1059         }
1060     }
1061
1062     private ConnectivityService getConnectivityService(Uuid suuid) {
1063         try {
1064             // First read connectivity service with service uuid and update info
1065             InstanceIdentifier<ConnectivityService> connectivityServIID =
1066                 InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
1067                     .child(org.opendaylight.yang.gen.v1.urn
1068                         .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
1069                     .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
1070                     .build();
1071
1072             Optional<ConnectivityService> optConnServ =
1073                 this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, connectivityServIID).get();
1074             if (!optConnServ.isPresent()) {
1075                 LOG.error("Connectivity service not found in tapi context");
1076                 return null;
1077             }
1078             return optConnServ.orElseThrow();
1079         } catch (InterruptedException | ExecutionException e) {
1080             LOG.error("Connectivity service not found in tapi context. Error:", e);
1081             return null;
1082         }
1083     }
1084
1085     private void deleteConnectivityService(Uuid suuid) {
1086         // First read connectivity service with service uuid and update info
1087         InstanceIdentifier<ConnectivityService> connectivityServIID =
1088             InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
1089                 .child(org.opendaylight.yang.gen.v1.urn
1090                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
1091                 .child(ConnectivityService.class, new ConnectivityServiceKey(suuid))
1092                 .build();
1093         try {
1094             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectivityServIID);
1095             this.networkTransactionService.commit().get();
1096         } catch (InterruptedException | ExecutionException e) {
1097             LOG.error("Failed to delete TAPI connectivity service", e);
1098         }
1099     }
1100
1101     private void deleteConnection(Uuid connectionUuid) {
1102         // First read connectivity service with service uuid and update info
1103         InstanceIdentifier<org.opendaylight.yang.gen.v1
1104                 .urn.onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection> connectionIID =
1105             InstanceIdentifier.builder(Context.class).augmentation(Context1.class)
1106                 .child(org.opendaylight.yang.gen.v1.urn
1107                     .onf.otcc.yang.tapi.connectivity.rev181210.context.ConnectivityContext.class)
1108                 .child(org.opendaylight.yang.gen.v1.urn
1109                         .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.Connection.class,
1110                     new org.opendaylight.yang.gen.v1.urn
1111                             .onf.otcc.yang.tapi.connectivity.rev181210.connectivity.context.ConnectionKey(
1112                         connectionUuid))
1113                 .build();
1114         try {
1115             this.networkTransactionService.delete(LogicalDatastoreType.OPERATIONAL, connectionIID);
1116             this.networkTransactionService.commit().get();
1117         } catch (InterruptedException | ExecutionException e) {
1118             LOG.error("Failed to delete TAPI connection", e);
1119         }
1120     }
1121
1122     private String getIdBasedOnModelVersion(String nodeid) {
1123         return nodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*")
1124             ? String.join("-", nodeid.split("-")[0], nodeid.split("-")[1]) : nodeid.split("-")[0];
1125     }
1126
1127     private ConnectionEndPoint getAssociatediODUCep(String spcXpdrNetwork) {
1128         Uuid topoUuid = new Uuid(UUID.nameUUIDFromBytes(TapiStringConstants.T0_FULL_MULTILAYER
1129             .getBytes(Charset.forName("UTF-8"))).toString());
1130         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
1131             TapiStringConstants.DSR).getBytes(Charset.forName("UTF-8")))).toString());
1132         Uuid nepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", spcXpdrNetwork.split("\\+")[0],
1133                 TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]).getBytes(Charset.forName("UTF-8"))))
1134             .toString());
1135         Uuid cepUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+", "CEP",
1136             spcXpdrNetwork.split("\\+")[0], TapiStringConstants.I_ODU, spcXpdrNetwork.split("\\+")[1]))
1137             .getBytes(Charset.forName("UTF-8"))).toString());
1138         InstanceIdentifier<OwnedNodeEdgePoint> nepIID = InstanceIdentifier.builder(Context.class)
1139             .augmentation(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.Context1.class)
1140             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.context.TopologyContext.class)
1141             .child(Topology.class, new TopologyKey(topoUuid))
1142             .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
1143                 new NodeKey(nodeUuid)).child(OwnedNodeEdgePoint.class, new OwnedNodeEdgePointKey(nepUuid)).build();
1144         try {
1145             Optional<OwnedNodeEdgePoint> optNode = this.networkTransactionService
1146                 .read(LogicalDatastoreType.OPERATIONAL, nepIID).get();
1147             if (!optNode.isPresent()) {
1148                 LOG.error("Node is not present in datastore");
1149                 return null;
1150             }
1151             if (optNode.orElseThrow().augmentation(OwnedNodeEdgePoint1.class) == null) {
1152                 LOG.error("Node doesnt have ceps");
1153                 return null;
1154             }
1155             return optNode.orElseThrow().augmentation(OwnedNodeEdgePoint1.class).getCepList().getConnectionEndPoint()
1156                 .get(new org.opendaylight.yang.gen.v1.urn
1157                     .onf.otcc.yang.tapi.connectivity.rev181210.cep.list.ConnectionEndPointKey(cepUuid));
1158         } catch (InterruptedException | ExecutionException e) {
1159             LOG.error("Couldnt read node in topology", e);
1160             return null;
1161         }
1162     }
1163
1164     private String getAssociatedNetworkPort(String spcXpdrClient, List<String> xpdrNetworkTplist) {
1165         for (String networkPort:xpdrNetworkTplist) {
1166             if (networkPort.split("\\+")[0].equals(spcXpdrClient.split("\\+")[0])) {
1167                 return networkPort;
1168             }
1169         }
1170         return null;
1171     }
1172
1173     private OpenroadmNodeType getOpenRoadmNodeType(List<String> xpdrNodelist) {
1174         List<OpenroadmNodeType> openroadmNodeTypeList = new ArrayList<>();
1175         for (String xpdrNode:xpdrNodelist) {
1176             Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes((String.join("+",xpdrNode, TapiStringConstants.DSR))
1177                 .getBytes(Charset.forName("UTF-8"))).toString());
1178             InstanceIdentifier<org.opendaylight.yang.gen.v1.urn
1179                     .onf.otcc.yang.tapi.topology.rev181210.topology.Node> nodeIID
1180                 = InstanceIdentifier.builder(Context.class).augmentation(org.opendaylight.yang.gen.v1.urn
1181                             .onf.otcc.yang.tapi.topology.rev181210.Context1.class).child(TopologyContext.class)
1182                     .child(Topology.class, new TopologyKey(this.tapiTopoUuid))
1183                     .child(org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node.class,
1184                             new NodeKey(nodeUuid)).build();
1185             try {
1186                 Optional<org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev181210.topology.Node> optNode
1187                     = this.networkTransactionService.read(LogicalDatastoreType.OPERATIONAL, nodeIID).get();
1188                 if (!optNode.isPresent()) {
1189                     return null;
1190                 }
1191                 OpenroadmNodeType openroadmNodeType = OpenroadmNodeType.forName(optNode.orElseThrow().getName().get(
1192                     new NameKey("Node Type")).getValue());
1193                 if (!openroadmNodeTypeList.contains(openroadmNodeType)) {
1194                     openroadmNodeTypeList.add(openroadmNodeType);
1195                 }
1196             } catch (InterruptedException | ExecutionException e) {
1197                 LOG.error("Couldnt read node in topology", e);
1198                 return null;
1199             }
1200         }
1201         // TODO for now check that there is only one type, otherwise error
1202         if (openroadmNodeTypeList.size() != 1) {
1203             LOG.error("More than one xpdr type. List = {}", openroadmNodeTypeList);
1204             return null;
1205         }
1206         return openroadmNodeTypeList.get(0);
1207     }
1208
1209     private List<String> getAssociatedClientsPort(List<String> xpdrNetworkTplist) {
1210         List<String> clientPortList = new ArrayList<>();
1211         for (String networkPort:xpdrNetworkTplist) {
1212             String nodeId = String.join("-", networkPort.split("\\+")[0].split("-")[0],
1213                 networkPort.split("\\+")[0].split("-")[1]);
1214             String tpId = networkPort.split("\\+")[1];
1215             InstanceIdentifier<Mapping> mapIID = InstanceIdentifier.builder(Network.class)
1216                 .child(Nodes.class, new NodesKey(nodeId))
1217                 .child(Mapping.class, new MappingKey(tpId)).build();
1218             try {
1219                 Optional<Mapping> optMapping = this.networkTransactionService.read(LogicalDatastoreType.CONFIGURATION,
1220                     mapIID).get();
1221                 if (!optMapping.isPresent()) {
1222                     LOG.error("Couldnt find mapping for port {} of node {}", tpId, nodeId);
1223                 }
1224                 Mapping mapping = optMapping.orElseThrow();
1225                 LOG.info("Mapping for node+port {}+{} = {}", nodeId, tpId, mapping);
1226                 String key = String.join("+", String.join("-", nodeId, tpId.split("\\-")[0]),
1227                     mapping.getConnectionMapLcp());
1228                 LOG.info("Key to be added to list = {}", key);
1229                 if (!clientPortList.contains(key)) {
1230                     clientPortList.add(key);
1231                 }
1232             } catch (InterruptedException | ExecutionException e) {
1233                 LOG.error("Couldnt read mapping from datastore", e);
1234                 return null;
1235             }
1236
1237         }
1238         return clientPortList;
1239     }
1240
1241     public void setInput(CreateConnectivityServiceInput input) {
1242         this.input = input;
1243     }
1244
1245     public void setServiceUuid(Uuid serviceUuid) {
1246         this.serviceUuid = serviceUuid;
1247     }
1248 }