Consolidate ConnectivityUtils
[transportpce.git] / tapi / src / main / java / org / opendaylight / transportpce / tapi / topology / ConvertORTopoToTapiFullTopo.java
1 /*
2  * Copyright © 2021 Nokia.  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.topology;
9
10 import java.nio.charset.Charset;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.UUID;
17 import java.util.stream.Collectors;
18 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
19 import org.opendaylight.transportpce.tapi.TapiStringConstants;
20 import org.opendaylight.transportpce.tapi.impl.TapiProvider;
21 import org.opendaylight.transportpce.tapi.utils.TapiLink;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Link1;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.TerminationPoint1;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
25 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmNodeType;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev230526.OpenroadmTpType;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.network.topology.rev230526.Node1;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.node.TerminationPoint;
32 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.AdministrativeState;
33 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Direction;
34 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LayerProtocolName;
35 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.LifecycleState;
36 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.OperationalState;
37 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.PortRole;
38 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.Uuid;
39 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.Name;
40 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameBuilder;
41 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.global._class.NameKey;
42 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePoint;
43 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.common.rev221121.tapi.context.ServiceInterfacePointKey;
44 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1;
45 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.OwnedNodeEdgePoint1Builder;
46 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.cep.list.ConnectionEndPoint;
47 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.context.topology.context.topology.node.owned.node.edge.point.CepList;
48 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.connectivity.rev221121.context.topology.context.topology.node.owned.node.edge.point.CepListBuilder;
49 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIERMC;
50 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROMS;
51 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTS;
52 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.photonic.media.rev221121.PHOTONICLAYERQUALIFIEROTSiMC;
53 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroup;
54 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.InterRuleGroupKey;
55 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroup;
56 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.NodeRuleGroupKey;
57 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePoint;
58 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointBuilder;
59 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.OwnedNodeEdgePointKey;
60 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.RiskParameterPacBuilder;
61 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.node.edge.point.SupportedCepLayerProtocolQualifierInstancesBuilder;
62 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristic;
63 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.risk.parameter.pac.RiskCharacteristicBuilder;
64 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Link;
65 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.LinkKey;
66 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeBuilder;
67 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.NodeKey;
68 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristic;
69 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.cost.pac.CostCharacteristicBuilder;
70 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristic;
71 import org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.transfer.timing.pac.LatencyCharacteristicBuilder;
72 import org.opendaylight.yangtools.yang.common.Uint64;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76
77 public class ConvertORTopoToTapiFullTopo {
78
79     private static final Logger LOG = LoggerFactory.getLogger(ConvertORTopoToTapiFullTopo.class);
80     private String ietfNodeId;
81     private OpenroadmNodeType ietfNodeType;
82     private Uuid tapiTopoUuid;
83     private Map<NodeKey, org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node>
84         tapiNodes;
85     private Map<LinkKey, Link> tapiLinks;
86     private Map<ServiceInterfacePointKey, ServiceInterfacePoint> tapiSips;
87     private final TapiLink tapiLink;
88     private static String topologicalMode = TapiProvider.TOPOLOGICAL_MODE;
89
90
91     public ConvertORTopoToTapiFullTopo(Uuid tapiTopoUuid, TapiLink tapiLink) {
92         this.tapiTopoUuid = tapiTopoUuid;
93         this.tapiNodes = new HashMap<>();
94         this.tapiLinks = new HashMap<>();
95         this.tapiSips = new HashMap<>();
96         this.tapiLink = tapiLink;
97     }
98
99     public void convertRdmToRdmLinks(
100             List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
101                 .networks.network.Link> rdmTordmLinkList) {
102         List<String> linksToNotConvert = new ArrayList<>();
103         LOG.info("creation of {} roadm to roadm links", rdmTordmLinkList.size() / 2);
104         for (var link : rdmTordmLinkList) {
105             if (linksToNotConvert.contains(link.getLinkId().getValue())) {
106                 continue;
107             }
108             var lnk1 = link.augmentation(Link1.class);
109             var lnk1OppLnk = lnk1.getOppositeLink();
110             var oppositeLink = rdmTordmLinkList.stream()
111                 .filter(l -> l.getLinkId().equals(lnk1OppLnk))
112                 .findAny().orElse(null);
113             AdminStates oppLnkAdmState = null;
114             State oppLnkOpState = null;
115             if (oppositeLink != null) {
116                 oppLnkAdmState = oppositeLink.augmentation(Link1.class).getAdministrativeState();
117                 oppLnkOpState = oppositeLink.augmentation(Link1.class).getOperationalState();
118             }
119             var linkSrc = link.getSource();
120             String linkSrcNodeValue = linkSrc.getSourceNode().getValue();
121             var linkDst = link.getDestination();
122             String linkDstNodeValue = linkDst.getDestNode().getValue();
123             var lnkAdmState = lnk1.getAdministrativeState();
124             var lnkOpState = lnk1.getOperationalState();
125             Link tapLink = this.tapiLink.createTapiLink(
126                 String.join("-", linkSrcNodeValue.split("-")[0], linkSrcNodeValue.split("-")[1]),
127                 linkSrc.getSourceTp().getValue(),
128                 String.join("-", linkDstNodeValue.split("-")[0], linkDstNodeValue.split("-")[1]),
129                 linkDst.getDestTp().getValue(),
130                 TapiStringConstants.OMS_RDM_RDM_LINK,
131                 TapiStringConstants.PHTNC_MEDIA,
132                 TapiStringConstants.PHTNC_MEDIA,
133                 TapiStringConstants.PHTNC_MEDIA_OTS,
134                 TapiStringConstants.PHTNC_MEDIA_OTS,
135                 //adminState,
136                 lnkAdmState == null || oppLnkAdmState == null
137                     ? null : this.tapiLink.setTapiAdminState(lnkAdmState, oppLnkAdmState).getName(),
138                 //operState,
139                 lnkOpState == null || oppLnkOpState == null
140                     ? null : this.tapiLink.setTapiOperationalState(lnkOpState, oppLnkOpState).getName(),
141                 Set.of(LayerProtocolName.PHOTONICMEDIA),
142                 Set.of(LayerProtocolName.PHOTONICMEDIA.getName()),
143                 this.tapiTopoUuid);
144             linksToNotConvert.add(lnk1OppLnk.getValue());
145             tapiLinks.put(tapLink.key(), tapLink);
146             Map<Map<String, String>, ConnectionEndPoint> cepMap = this.tapiLink.getCepMap();
147             LOG.debug("CONVERTTOFULL147, cepMap is {}", cepMap);
148             addCepToOnepAndNode(cepMap);
149         }
150     }
151
152     public void convertRoadmNode(Node roadm, Network openroadmTopo, String topoMode) {
153         setTopologicalMode(topoMode);
154         if (topoMode.equals("Full")) {
155             convertRoadmNodeFull(roadm, openroadmTopo);
156         } else {
157             convertRoadmNodeAbstracted(openroadmTopo);
158         }
159     }
160
161     private void addCepToOnepAndNode(Map<Map<String, String>, ConnectionEndPoint> cepMap) {
162
163         for (Map.Entry<Map<String, String>, ConnectionEndPoint> cepEntry : cepMap.entrySet()) {
164             String nepNodeId = cepEntry.getKey().entrySet().stream().findFirst().orElseThrow().getValue();
165             LOG.debug("CONVERTTOFULL165, Node UUID is {}", nepNodeId);
166             List<NodeKey> listKey = tapiNodes.entrySet().stream().map(Map.Entry::getKey).collect(Collectors.toList());
167             //.forEach(Function.identity().toString());
168             LOG.debug("CONVERTTOFULL168, TapiNode Keys are {}", tapiNodes
169                 .entrySet().stream()
170                 .map(Map.Entry::getKey)
171                 .collect(Collectors.toList()));
172             LOG.debug("CONVERTTOFULL172, TapiNode Keys are {}", tapiNodes
173                 .entrySet().stream()
174                 .map(nep -> nep.getValue().getName().toString())
175                 .collect(Collectors.toList()));
176             if (!listKey.toString().contains(nepNodeId)) {
177                 LOG.info("ConvertToFullLINE178, ListKey {} of TapiNodes does not contain NodeUuid {}",
178                     listKey, nepNodeId);
179             }
180             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node node = tapiNodes
181                 .entrySet().stream()
182                 .filter(theNode -> theNode.getKey().getUuid().toString().equals(nepNodeId))
183                 .map(Map.Entry::getValue).findFirst().orElseThrow();
184             var onepMap = node.getOwnedNodeEdgePoint();
185             OwnedNodeEdgePoint ownedNep = onepMap.entrySet().stream()
186                 .filter(onep -> onep.getKey().getUuid().toString()
187                     .equals(cepEntry.getKey().entrySet().stream().findFirst().orElseThrow().getKey()))
188                 .map(Map.Entry::getValue).findFirst().orElseThrow();
189             CepList cepList = new CepListBuilder()
190                 .setConnectionEndPoint(Map.of(cepEntry.getValue().key(), cepEntry.getValue()))
191                 .build();
192             OwnedNodeEdgePoint1 onep1Bldr = new OwnedNodeEdgePoint1Builder().setCepList(cepList).build();
193             OwnedNodeEdgePoint newOnep = new OwnedNodeEdgePointBuilder(ownedNep)
194                     .addAugmentation(onep1Bldr)
195                     .build();
196             onepMap.put(newOnep.key(), newOnep);
197             var newNode = new  org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology
198                     .NodeBuilder(node)
199                 .setOwnedNodeEdgePoint(onepMap)
200                 .build();
201             this.tapiNodes.put(newNode.key(), newNode);
202             LOG.debug("CONVERTTOFULL201, successfully create node {} with CepList {} ", newNode.getName(), cepList);
203         }
204     }
205
206     private void convertRoadmNodeFull(Node roadm, Network openroadmTopo) {
207         this.ietfNodeId = roadm.getNodeId().getValue();
208         this.ietfNodeType = roadm.augmentation(
209                 org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class)
210             .getNodeType();
211         Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> oneplist = new HashMap<>();
212         // 1. Get degree and srg nodes to map TPs into NEPs
213         if (openroadmTopo.getNode() == null) {
214             LOG.warn("Openroadm-topology is null.");
215             return;
216         }
217         int numNeps = 0;
218         int numSips = 0;
219         List<Node> nodeList = new ArrayList<Node>(openroadmTopo.getNode().values());
220         for (Node node:nodeList) {
221             String nodeId = node.getNodeId().getValue();
222             if (node.getSupportingNode().values().stream()
223                     .noneMatch(sp -> sp.getNodeRef().getValue().equals(this.ietfNodeId))) {
224                 LOG.debug("Abstracted node {} is not part of {}", nodeId, this.ietfNodeId);
225                 continue;
226             }
227             var node1 = node.augmentation(
228                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1.class);
229             if (node.augmentation(Node1.class) == null && node1 == null) {
230                 LOG.warn("Abstracted node {} doesnt have type of node or is not disaggregated", nodeId);
231                 continue;
232             }
233             OpenroadmNodeType nodeType = node.augmentation(
234                         org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev230526.Node1.class)
235                 .getNodeType();
236             var node1TpValues = node1.getTerminationPoint().values();
237             LOG.info("TPs of node: {}", node1TpValues);
238             switch (nodeType.getIntValue()) {
239                 case 11:
240                     LOG.info("Degree node");
241                     // Get only external TPs of the degree
242                     List<TerminationPoint> degPortList = node1TpValues.stream()
243                         .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
244                                 == OpenroadmTpType.DEGREETXRXTTP.getIntValue()
245                             || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
246                                 == OpenroadmTpType.DEGREERXTTP.getIntValue()
247                             || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
248                                 == OpenroadmTpType.DEGREETXTTP.getIntValue())
249                         .collect(Collectors.toList());
250                     // Convert TP List in NEPs and put it in onepl
251                     LOG.info("Degree port List: {}", degPortList.toString());
252                     // TODO: deg port could be sip. e.g. MDONS
253                     oneplist.putAll(populateNepsForRdmNode(
254                         nodeId, degPortList, false, TapiStringConstants.PHTNC_MEDIA_OTS));
255                     oneplist.putAll(populateNepsForRdmNode(
256                         nodeId, degPortList, false, TapiStringConstants.PHTNC_MEDIA_OMS));
257                     numNeps += degPortList.size() * 2;
258                     break;
259                 case 12:
260                     LOG.info("SRG node");
261                     // Get only external TPs of the srg
262                     List<TerminationPoint> srgPortList = node1TpValues.stream()
263                         .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
264                                 == OpenroadmTpType.SRGTXRXPP.getIntValue()
265                             || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
266                                 == OpenroadmTpType.SRGRXPP.getIntValue()
267                             || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
268                                 == OpenroadmTpType.SRGTXPP.getIntValue())
269                         .collect(Collectors.toList());
270                     // Convert TP List in NEPs and put it in onepl
271                     LOG.info("Srg port List: {}", srgPortList);
272                     oneplist.putAll(populateNepsForRdmNode(
273                         nodeId, srgPortList, true, TapiStringConstants.PHTNC_MEDIA_OTS));
274
275                     numNeps += srgPortList.size();
276                     numSips += srgPortList.size();
277                     break;
278                 default:
279                     LOG.error("Node {} type not supported", nodeType.getName());
280             }
281         }
282         // create tapi Node
283         // UUID
284         String nodeIdPhMed = String.join("+", this.ietfNodeId, TapiStringConstants.PHTNC_MEDIA);
285         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(nodeIdPhMed.getBytes(Charset.forName("UTF-8"))).toString());
286         LOG.info("Creation of PHOTONIC node for {}, of Uuid {}", this.ietfNodeId, nodeUuid);
287         // Names
288         Name nodeNames =  new NameBuilder().setValueName("roadm node name").setValue(nodeIdPhMed).build();
289         Name nameNodeType = new NameBuilder().setValueName("Node Type").setValue(this.ietfNodeType.getName()).build();
290         // Protocol Layer
291         Set<LayerProtocolName> layerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA);
292         // Build tapi node
293         LOG.debug("CONVERTTOFULL SRG OTSNode of retrieved OnepMap {} ",
294             oneplist.entrySet().stream().filter(e -> e.getValue()
295                 .getSupportedCepLayerProtocolQualifierInstances()
296                     .contains(new SupportedCepLayerProtocolQualifierInstancesBuilder()
297                         .setNumberOfCepInstances(Uint64.valueOf(1))
298                         .setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE)
299                     .build()))
300             .collect(Collectors.toList()).toString());
301         //org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node
302         var roadmNode = createRoadmTapiNode(nodeUuid,
303             Map.of(nodeNames.key(), nodeNames, nameNodeType.key(), nameNodeType), layerProtocols, oneplist, "Full");
304         // TODO add states corresponding to device config
305         LOG.info("ROADM node {} should have {} NEPs and {} SIPs", TapiStringConstants.RDM_INFRA, numNeps, numSips);
306         LOG.info("ROADM node {} has {} NEPs and {} SIPs",
307             TapiStringConstants.RDM_INFRA,
308             roadmNode.nonnullOwnedNodeEdgePoint().values().size(),
309             roadmNode.nonnullOwnedNodeEdgePoint().values().stream()
310                 .filter(nep -> nep.getMappedServiceInterfacePoint() != null)
311                 .count());
312         tapiNodes.put(roadmNode.key(), roadmNode);
313     }
314
315     private void convertRoadmNodeAbstracted(Network openroadmTopo) {
316         Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> oneMap = new HashMap<>();
317         // 1. Get degree and srg nodes to map TPs into NEPs
318         if (openroadmTopo.getNode() == null) {
319             LOG.warn("Openroadm-topology is null.");
320             return;
321         }
322         int numNeps = 0;
323         int numSips = 0;
324         List<Node> nodeList = new ArrayList<Node>(openroadmTopo.getNode().values());
325         for (Node node:nodeList) {
326             if (node.augmentation(Node1.class) == null
327                     && node.augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
328                         .ietf.network.topology.rev180226.Node1.class) == null) {
329                 LOG.warn("Abstracted node {} doesnt have type of node or is not disaggregated",
330                     node.getNodeId().getValue());
331                 continue;
332             }
333             OpenroadmNodeType nodeType = node.augmentation(org.opendaylight.yang.gen.v1.http
334                 .org.openroadm.common.network.rev230526.Node1.class).getNodeType();
335             if (nodeType.getIntValue() != 11) {
336                 // Only consider ROADMS SRG Nodes
337                 continue;
338             }
339             org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Node1 node1 =
340                 node.augmentation(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
341                     .ietf.network.topology.rev180226.Node1.class);
342             LOG.debug("Handling SRG node in Topology abstraction {}", node.getNodeId().toString());
343             // Get only external TPs of the srg
344             List<TerminationPoint> srgPortList = node1.getTerminationPoint().values().stream()
345                 .filter(tp -> tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
346                         == OpenroadmTpType.SRGTXRXPP.getIntValue()
347                     || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
348                         == OpenroadmTpType.SRGRXPP.getIntValue()
349                     || tp.augmentation(TerminationPoint1.class).getTpType().getIntValue()
350                         == OpenroadmTpType.SRGTXPP.getIntValue())
351                 .collect(Collectors.toList());
352             // Convert TP List in NEPs and put it in onepl
353             LOG.debug("Srg port List: {}", srgPortList);
354             oneMap.putAll(populateNepsForRdmNode(node.getNodeId().getValue(), srgPortList, true,
355                 TapiStringConstants.PHTNC_MEDIA_OTS));
356             numNeps += srgPortList.size();
357             numSips += srgPortList.size();
358         }
359         // create a unique ROADM tapi Node
360         LOG.info("abstraction of the ROADM infrastructure towards a photonic node");
361         Uuid nodeUuid = new Uuid(UUID.nameUUIDFromBytes(
362             TapiStringConstants.RDM_INFRA.getBytes(Charset.forName("UTF-8"))).toString());
363         Name nodeName =  new NameBuilder().setValueName("roadm node name").setValue(TapiStringConstants.RDM_INFRA)
364             .build();
365         Name nameNodeType = new NameBuilder().setValueName("Node Type")
366             .setValue(OpenroadmNodeType.ROADM.getName()).build();
367
368         // Protocol Layer
369         Set<LayerProtocolName> layerProtocols = Set.of(LayerProtocolName.PHOTONICMEDIA);
370         // Build tapi node
371         org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node roadmNode =
372             createRoadmTapiNode(nodeUuid, Map.of(nodeName.key(), nodeName, nameNodeType.key(), nameNodeType),
373             layerProtocols, oneMap, "Abstracted");
374         // TODO add states corresponding to device config
375         LOG.info("ROADM node {} should have {} NEPs and {} SIPs", TapiStringConstants.RDM_INFRA, numNeps, numSips);
376         LOG.info("ROADM node {} has {} NEPs and {} SIPs", TapiStringConstants.RDM_INFRA,
377             roadmNode.nonnullOwnedNodeEdgePoint().values().size(),
378             roadmNode.nonnullOwnedNodeEdgePoint().values().stream()
379                 .filter(nep -> nep.getMappedServiceInterfacePoint() != null).count());
380
381         tapiNodes.put(roadmNode.key(), roadmNode);
382     }
383
384     private org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node
385              createRoadmTapiNode(Uuid nodeUuid, Map<NameKey, Name> nameMap, Set<LayerProtocolName> layerProtocols,
386              Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> onepMap, String topoMode) {
387         // Empty random creation of mandatory fields for avoiding errors....
388         CostCharacteristic costCharacteristic = new CostCharacteristicBuilder()
389             .setCostAlgorithm("Restricted Shortest Path - RSP")
390             .setCostName("HOP_COUNT")
391             .setCostValue(TapiStringConstants.COST_HOP_VALUE)
392             .build();
393         LatencyCharacteristic latencyCharacteristic = new LatencyCharacteristicBuilder()
394             .setFixedLatencyCharacteristic(TapiStringConstants.FIXED_LATENCY_VALUE)
395             .setQueuingLatencyCharacteristic(TapiStringConstants.QUEING_LATENCY_VALUE)
396             .setJitterCharacteristic(TapiStringConstants.JITTER_VALUE)
397             .setWanderCharacteristic(TapiStringConstants.WANDER_VALUE)
398             .setTrafficPropertyName("FIXED_LATENCY")
399             .build();
400         RiskCharacteristic riskCharacteristic = new RiskCharacteristicBuilder()
401             .setRiskCharacteristicName("risk characteristic")
402             .setRiskIdentifierList(Set.of("risk identifier1", "risk identifier2"))
403             .build();
404
405         var tapiFactory = new ConvertORToTapiTopology(this.tapiTopoUuid);
406         Map<NodeRuleGroupKey, NodeRuleGroup> nodeRuleGroupMap
407             = tapiFactory.createAllNodeRuleGroupForRdmNode(
408                 topoMode.equals("Full")
409                     ? "Full"
410                     : "Abstracted",
411                 nodeUuid, this.ietfNodeId, onepMap.values());
412         Map<InterRuleGroupKey, InterRuleGroup> interRuleGroupMap
413             = tapiFactory.createInterRuleGroupForRdmNode(
414                 topoMode.equals("Full")
415                     ? "Full"
416                     : "Abstracted",
417                 nodeUuid, this.ietfNodeId,
418                 nodeRuleGroupMap.entrySet().stream().map(e -> e.getKey()).collect(Collectors.toList()));
419         return new NodeBuilder()
420             .setUuid(nodeUuid)
421             .setName(nameMap)
422             .setLayerProtocolName(layerProtocols)
423             .setAdministrativeState(AdministrativeState.UNLOCKED)
424             .setOperationalState(OperationalState.ENABLED)
425             .setLifecycleState(LifecycleState.INSTALLED)
426             .setOwnedNodeEdgePoint(onepMap)
427             .setNodeRuleGroup(nodeRuleGroupMap)
428             .setInterRuleGroup(interRuleGroupMap)
429             .setCostCharacteristic(Map.of(costCharacteristic.key(), costCharacteristic))
430             .setLatencyCharacteristic(Map.of(latencyCharacteristic.key(), latencyCharacteristic))
431             .setRiskParameterPac(
432                 new RiskParameterPacBuilder()
433                     .setRiskCharacteristic(Map.of(riskCharacteristic.key(), riskCharacteristic))
434                     .build())
435             .setErrorCharacteristic("error")
436             .setLossCharacteristic("loss")
437             .setRepeatDeliveryCharacteristic("repeat delivery")
438             .setDeliveryOrderCharacteristic("delivery order")
439             .setUnavailableTimeCharacteristic("unavailable time")
440             .setServerIntegrityProcessCharacteristic("server integrity process")
441             .build();
442     }
443
444     public Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> populateNepsForRdmNode(
445             String nodeId, List<TerminationPoint> tpList, boolean withSip, String nepPhotonicSublayer) {
446         // create neps for MC and and Photonic Media OTS/OMS
447         Map<OwnedNodeEdgePointKey, OwnedNodeEdgePoint> onepMap = new HashMap<>();
448         for (TerminationPoint tp:tpList) {
449             String tpId = tp.getTpId().getValue();
450             // Admin and oper state common for all tps
451             OpenroadmTpType tpType = tp.augmentation(TerminationPoint1.class).getTpType();
452             // PHOTONIC MEDIA nep
453             LOG.debug("PHOTO NEP = {}", String.join("+", this.ietfNodeId, nepPhotonicSublayer, tpId));
454             SupportedCepLayerProtocolQualifierInstancesBuilder sclpqiBd =
455                 new SupportedCepLayerProtocolQualifierInstancesBuilder()
456                     .setNumberOfCepInstances(Uint64.valueOf(1));
457             switch (nepPhotonicSublayer) {
458                 case TapiStringConstants.PHTNC_MEDIA_OMS:
459                     sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROMS.VALUE);
460                     break;
461                 case TapiStringConstants.PHTNC_MEDIA_OTS:
462                     sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTS.VALUE);
463                     break;
464                 case TapiStringConstants.MC:
465                     sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIERMC.VALUE);
466                     break;
467                 case TapiStringConstants.OTSI_MC:
468                     sclpqiBd.setLayerProtocolQualifier(PHOTONICLAYERQUALIFIEROTSiMC.VALUE);
469                     break;
470                 default:
471                     break;
472             }
473             //List<SupportedCepLayerProtocolQualifierInstances> sclpqiList = new ArrayList<>(List.of(sclpqiBd.build()));
474
475 //          OwnedNodeEdgePointBuilder onepBd = new OwnedNodeEdgePointBuilder();
476
477
478             AdminStates admin = tp.augmentation(TerminationPoint1.class).getAdministrativeState();
479             State oper = tp.augmentation(TerminationPoint1.class).getOperationalState();
480             Name nepName = new NameBuilder()
481                 .setValueName(nepPhotonicSublayer + "NodeEdgePoint")
482                 .setValue(String.join("+", this.ietfNodeId, nepPhotonicSublayer, tpId))
483                 .build();
484             OwnedNodeEdgePointBuilder onepBdd = new OwnedNodeEdgePointBuilder()
485                 .setUuid(new Uuid(UUID.nameUUIDFromBytes((String.join("+", this.ietfNodeId, nepPhotonicSublayer, tpId))
486                     .getBytes(Charset.forName("UTF-8"))).toString()))
487                 .setLayerProtocolName(LayerProtocolName.PHOTONICMEDIA)
488                 .setName(Map.of(nepName.key(), nepName))
489                 .setSupportedCepLayerProtocolQualifierInstances(
490                     new ArrayList<>(List.of(
491                         new SupportedCepLayerProtocolQualifierInstancesBuilder()
492                             .setLayerProtocolQualifier(
493                                 TapiStringConstants.PHTNC_MEDIA_OMS.equals(nepPhotonicSublayer)
494                                     ? PHOTONICLAYERQUALIFIEROMS.VALUE
495                                     : PHOTONICLAYERQUALIFIEROTS.VALUE)
496                             .setNumberOfCepInstances(Uint64.valueOf(1))
497                             .build())))
498                 .setDirection(Direction.BIDIRECTIONAL)
499                 .setLinkPortRole(PortRole.SYMMETRIC)
500                 .setAdministrativeState(this.tapiLink.setTapiAdminState(admin.getName()))
501                 .setOperationalState(this.tapiLink.setTapiOperationalState(oper.getName()))
502                 .setLifecycleState(LifecycleState.INSTALLED);
503
504             if (!nepPhotonicSublayer.equals(TapiStringConstants.MC)
505                     && !nepPhotonicSublayer.equals(TapiStringConstants.OTSI_MC)) {
506                 ConvertORToTapiTopology tapiFactory = new ConvertORToTapiTopology(this.tapiTopoUuid);
507                 Map<Double,Double> usedFreqMap = new HashMap<>();
508                 Map<Double,Double> availableFreqMap = new HashMap<>();
509                 switch (tpType) {
510                     // Whatever is the TP and its type we consider that it is handled in a bidirectional way :
511                     // same wavelength(s) used in both direction.
512                     case SRGRXPP:
513                     case SRGTXPP:
514                     case SRGTXRXPP:
515                         usedFreqMap = tapiFactory.getPPUsedWavelength(tp);
516                         if (usedFreqMap == null || usedFreqMap.isEmpty()) {
517                             availableFreqMap.put(GridConstant.START_EDGE_FREQUENCY * 1E12,
518                                 GridConstant.START_EDGE_FREQUENCY * 1E12
519                                 + GridConstant.GRANULARITY * GridConstant.EFFECTIVE_BITS * 1E09);
520                         } else {
521                             LOG.debug("EnteringLOOPcreateOTSiMC & MC with usedFreqMap non empty {} NEP {} for Node {}",
522                                 usedFreqMap, String.join("+", this.ietfNodeId, nepPhotonicSublayer, tpId), nodeId);
523                             onepMap.putAll(populateNepsForRdmNode(
524                                 nodeId, new ArrayList<>(List.of(tp)), true, TapiStringConstants.MC));
525                             onepMap.putAll(populateNepsForRdmNode(
526                                 nodeId, new ArrayList<>(List.of(tp)), true, TapiStringConstants.OTSI_MC));
527                         }
528                         break;
529                     case DEGREERXTTP:
530                     case DEGREETXTTP:
531                     case DEGREETXRXTTP:
532                         usedFreqMap = tapiFactory.getTTPUsedFreqMap(tp);
533                         availableFreqMap = tapiFactory.getTTPAvailableFreqMap(tp);
534                         break;
535                     default:
536                         break;
537                 }
538                 LOG.debug("calling add Photonic NEP spec for Roadm");
539                 onepBdd = tapiFactory.addPhotSpecToRoadmOnep(
540                     nodeId, usedFreqMap, availableFreqMap, onepBdd, String.join("+", nodeId, nepPhotonicSublayer));
541             }
542
543             OwnedNodeEdgePoint onep = onepBdd.build();
544             LOG.debug("ConvertORToTapiTopology.populateNepsForRdmNode onep is {}", onep);
545             onepMap.put(onep.key(), onep);
546         }
547         return onepMap;
548     }
549
550     public void convertXpdrToRdmLinks(
551             List<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226
552                 .networks.network.Link> xpdrRdmLinkList) {
553         List<String> linksToNotConvert = new ArrayList<>();
554         LOG.info("creation of {} xpdr to roadm links", xpdrRdmLinkList.size() / 2);
555         LOG.debug("Link list = {}", xpdrRdmLinkList);
556         for (var link:xpdrRdmLinkList) {
557             if (linksToNotConvert.contains(link.getLinkId().getValue())) {
558                 continue;
559             }
560             var oppositeLink = xpdrRdmLinkList.stream()
561                 .filter(l -> l.getLinkId().equals(link.augmentation(Link1.class).getOppositeLink()))
562                 .findAny().orElse(null);
563             AdminStates oppLnkAdmState = null;
564             State oppLnkOpState = null;
565             if (oppositeLink != null) {
566                 oppLnkAdmState = oppositeLink.augmentation(Link1.class).getAdministrativeState();
567                 oppLnkOpState = oppositeLink.augmentation(Link1.class).getOperationalState();
568             }
569             String sourceNode =
570                 link.getSource().getSourceNode().getValue().contains("ROADM")
571                     ? getIdBasedOnModelVersion(link.getSource().getSourceNode().getValue())
572                     : link.getSource().getSourceNode().getValue();
573             String destNode =
574                 link.getDestination().getDestNode().getValue().contains("ROADM")
575                     ? getIdBasedOnModelVersion(link.getDestination().getDestNode().getValue())
576                     : link.getDestination().getDestNode().getValue();
577             Link tapLink = this.tapiLink.createTapiLink(
578                 sourceNode, link.getSource().getSourceTp().getValue(),
579                 destNode, link.getDestination().getDestTp().getValue(),
580                 TapiStringConstants.OMS_XPDR_RDM_LINK,
581                 sourceNode.contains("ROADM") ? TapiStringConstants.PHTNC_MEDIA : TapiStringConstants.XPDR,
582                 destNode.contains("ROADM") ? TapiStringConstants.PHTNC_MEDIA : TapiStringConstants.XPDR,
583                 TapiStringConstants.PHTNC_MEDIA_OTS, TapiStringConstants.PHTNC_MEDIA_OTS,
584                 //adminState,
585                 link.augmentation(Link1.class).getAdministrativeState() == null || oppLnkAdmState == null
586                     ? null
587                     : this.tapiLink.setTapiAdminState(
588                         link.augmentation(Link1.class).getAdministrativeState(), oppLnkAdmState).getName(),
589                 //operState,
590                 link.augmentation(Link1.class).getOperationalState() == null || oppLnkOpState == null
591                     ? null
592                     : this.tapiLink.setTapiOperationalState(
593                         link.augmentation(Link1.class).getOperationalState(), oppLnkOpState).getName(),
594                 Set.of(LayerProtocolName.PHOTONICMEDIA), Set.of(LayerProtocolName.PHOTONICMEDIA.getName()),
595                 this.tapiTopoUuid);
596             linksToNotConvert.add(link.augmentation(Link1.class).getOppositeLink().getValue());
597             this.tapiLinks.put(tapLink.key(), tapLink);
598         }
599     }
600
601     private String getIdBasedOnModelVersion(String linknodeid) {
602         if (linknodeid.matches("[A-Z]{5}-[A-Z0-9]{2}-.*")) {
603             LOG.info("OpenROADM version > 1.2.1 {}", linknodeid);
604             return String.join("-", linknodeid.split("-")[0], linknodeid.split("-")[1]);
605         } else {
606             LOG.info("OpenROADM version <= 1.2.1 {}", linknodeid);
607             return linknodeid.split("-")[0];
608         }
609     }
610
611     public void setTapiNodes(Map<NodeKey,
612             org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node> nodeMap) {
613         this.tapiNodes.putAll(nodeMap);
614     }
615
616     public Map<NodeKey, org.opendaylight.yang.gen.v1.urn.onf.otcc.yang.tapi.topology.rev221121.topology.Node>
617             getTapiNodes() {
618         return tapiNodes;
619     }
620
621     public Map<LinkKey, Link> getTapiLinks() {
622         return tapiLinks;
623     }
624
625     public void setTapiSips(Map<ServiceInterfacePointKey, ServiceInterfacePoint> tapiSip) {
626         this.tapiSips.putAll(tapiSip);
627     }
628
629     public Map<ServiceInterfacePointKey, ServiceInterfacePoint> getTapiSips() {
630         return tapiSips;
631     }
632
633     public static void setTopologicalMode(String topoMode) {
634         ConvertORTopoToTapiFullTopo.topologicalMode = topoMode;
635     }
636
637     public String getTopologicalMode() {
638         return topologicalMode;
639     }
640 }