Use version 13.1.0 of openroadm-service models
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / mapping / PortMappingVersion121.java
1 /*
2  * Copyright © 2017 AT&T 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
9 package org.opendaylight.transportpce.common.mapping;
10
11 import com.google.common.util.concurrent.FluentFuture;
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Locale;
20 import java.util.Map;
21 import java.util.Map.Entry;
22 import java.util.Optional;
23 import java.util.Set;
24 import java.util.concurrent.ExecutionException;
25 import java.util.stream.Collectors;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.api.WriteTransaction;
29 import org.opendaylight.mdsal.common.api.CommitInfo;
30 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
31 import org.opendaylight.transportpce.common.StringConstants;
32 import org.opendaylight.transportpce.common.Timeouts;
33 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.Network;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.NetworkBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.OpenroadmNodeVersion;
37 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.cp.to.degree.CpToDegree;
38 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.cp.to.degree.CpToDegreeBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.cp.to.degree.CpToDegreeKey;
40 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.Mapping;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.MappingBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.mapping.MappingKey;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.Nodes;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.NodesBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.NodesKey;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.nodes.NodeInfo;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220922.network.nodes.NodeInfoBuilder;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.Direction;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.CircuitPack;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceData;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.Port;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.PortsKey;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.degree.ConnectionPorts;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.ConnectionMap;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Degree;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.DegreeKey;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Protocols;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.connection.map.Destination;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.port.Interfaces;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes;
71 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.EthernetCsmacd;
72 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.InterfaceType;
73 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpenROADMOpticalMultiplex;
74 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpticalTransport;
75 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOdu;
76 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOtu;
77 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.Protocols1;
78 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.lldp.container.Lldp;
79 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.lldp.container.lldp.PortConfig;
80 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev161014.SupportedIfCapability;
81 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
82 import org.opendaylight.yangtools.yang.common.Uint16;
83 import org.opendaylight.yangtools.yang.common.Uint32;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
86
87 // FIXME: many common pieces of code between PortMapping Versions 121 and 221 and 710
88 // some mutualization would be helpful
89 @SuppressWarnings("CPD-START")
90 public class PortMappingVersion121 {
91
92     private static final Logger LOG = LoggerFactory.getLogger(PortMappingVersion121.class);
93     private static final Map<Direction, String> SUFFIX;
94     private static final Set<Integer> TXRX_SET = Set.of(Direction.Tx.getIntValue(), Direction.Rx.getIntValue());
95
96     private final DataBroker dataBroker;
97     private final DeviceTransactionManager deviceTransactionManager;
98
99     static {
100         SUFFIX =  Map.of(
101             Direction.Tx, "TX",
102             Direction.Rx, "RX",
103             Direction.Bidirectional, "TXRX");
104     }
105
106
107     public PortMappingVersion121(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager) {
108         this.dataBroker = dataBroker;
109         this.deviceTransactionManager = deviceTransactionManager;
110     }
111
112     public boolean createMappingData(String nodeId) {
113         LOG.info(PortMappingUtils.CREATE_MAPPING_DATA_LOGMSG, nodeId, "1.2.1");
114         List<Mapping> portMapList = new ArrayList<>();
115         InstanceIdentifier<Info> infoIID = InstanceIdentifier
116             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class).child(Info.class).build();
117         Optional<Info> deviceInfoOptional = this.deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType
118             .OPERATIONAL, infoIID, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
119         if (deviceInfoOptional.isEmpty()) {
120             LOG.warn(PortMappingUtils.DEVICE_HAS_LOGMSG, nodeId, "no info", "subtree");
121             return false;
122         }
123         Info deviceInfo = deviceInfoOptional.orElseThrow();
124         NodeInfo nodeInfo = createNodeInfo(deviceInfo);
125         if (nodeInfo == null) {
126             return false;
127         }
128         postPortMapping(nodeId, nodeInfo, null, null);
129
130         switch (deviceInfo.getNodeType()) {
131
132             case Rdm:
133                 // Get TTP port mapping
134                 if (!createTtpPortMapping(nodeId, deviceInfo, portMapList)) {
135                     // return false if mapping creation for TTP's failed
136                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "TTP's");
137                     return false;
138                 }
139
140                 // Get PP port mapping
141                 if (!createPpPortMapping(nodeId, deviceInfo, portMapList)) {
142                     // return false if mapping creation for PP's failed
143                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "PP's");
144                     return false;
145                 }
146                 break;
147             case Xpdr:
148                 if (!createXpdrPortMapping(nodeId, portMapList)) {
149                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "Xponder");
150                     return false;
151                 }
152                 break;
153             default:
154                 LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG,
155                     nodeId, PortMappingUtils.CREATE, deviceInfo.getNodeType() + " - unknown nodetype");
156                 break;
157
158         }
159         return postPortMapping(nodeId, nodeInfo, portMapList, null);
160     }
161
162     public boolean updateMapping(String nodeId, Mapping oldMapping) {
163         if (nodeId == null) {
164             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG, "node id null" , PortMappingUtils.UPDATE, "a null value");
165             return false;
166         }
167         if (oldMapping == null) {
168             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.UPDATE, "a null value");
169             return false;
170         }
171         InstanceIdentifier<Ports> portId = InstanceIdentifier
172             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
173             .child(CircuitPacks.class, new CircuitPacksKey(oldMapping.getSupportingCircuitPackName()))
174             .child(Ports.class, new PortsKey(oldMapping.getSupportingPort()))
175             .build();
176         try {
177             Ports port = deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL,
178                 portId, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT).orElseThrow();
179             Mapping newMapping = updateMappingObject(nodeId, port, oldMapping);
180             LOG.debug(PortMappingUtils.UPDATE_MAPPING_LOGMSG,
181                 nodeId, oldMapping, oldMapping.getLogicalConnectionPoint(), newMapping);
182             final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
183             InstanceIdentifier<Mapping> mapIID = InstanceIdentifier.create(Network.class)
184                 .child(Nodes.class, new NodesKey(nodeId))
185                 .child(Mapping.class, new MappingKey(oldMapping.getLogicalConnectionPoint()));
186             writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, mapIID, newMapping);
187             FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
188             commit.get();
189             return true;
190         } catch (InterruptedException | ExecutionException e) {
191             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG,
192                 nodeId, PortMappingUtils.UPDATE, oldMapping.getLogicalConnectionPoint(), e);
193             return false;
194         }
195     }
196
197     private boolean createXpdrPortMapping(String nodeId, List<Mapping> portMapList) {
198         // Creating for Xponder Line and Client Ports
199         InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier
200             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class).build();
201         Optional<OrgOpenroadmDevice> deviceObject = deviceTransactionManager.getDataFromDevice(nodeId,
202             LogicalDatastoreType.OPERATIONAL, deviceIID,
203             Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
204         if (deviceObject.isEmpty()) {
205             LOG.error(PortMappingUtils.CANNOT_GET_DEV_CONF_LOGMSG, nodeId);
206             return false;
207         }
208         OrgOpenroadmDevice device = deviceObject.orElseThrow();
209         if (device.getCircuitPacks() == null) {
210             LOG.warn(PortMappingUtils.MISSING_CP_LOGMSG, nodeId, PortMappingUtils.FOUND);
211             return false;
212         }
213         // Variable to keep track of number of line ports
214         int line = 1;
215         // Variable to keep track of number of client ports
216         int client = 1;
217         Map<String, String> lcpMap = new HashMap<>();
218         Map<String, Mapping> mappingMap = new HashMap<>();
219         List<CircuitPacks> circuitPackList = new ArrayList<>(device.nonnullCircuitPacks().values());
220         circuitPackList.sort(Comparator.comparing(CircuitPack::getCircuitPackName));
221
222         for (CircuitPacks cp : circuitPackList) {
223             String circuitPackName = cp.getCircuitPackName();
224             if (cp.getPorts() == null) {
225                 LOG.warn(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, PortMappingUtils.FOUND, circuitPackName);
226                 continue;
227             }
228             List<Ports> portList = new ArrayList<>(cp.nonnullPorts().values());
229             portList.sort(Comparator.comparing(Ports::getPortName));
230             for (Ports port : portList) {
231                 int[] counters = fillXpdrLcpsMaps(line, client, nodeId,
232                     1, circuitPackName, port,
233                     circuitPackList, lcpMap, mappingMap);
234                 line = counters[0];
235                 client = counters[1];
236             }
237         }
238
239         for (ConnectionMap cm : deviceObject.orElseThrow().nonnullConnectionMap().values()) {
240             String skey = cm.getSource().getCircuitPackName() + "+" + cm.getSource().getPortName();
241             Destination destination0 = cm.nonnullDestination().values().iterator().next();
242             String dkey = destination0.getCircuitPackName() + "+" + destination0.getPortName();
243             if (!lcpMap.containsKey(skey)) {
244                 LOG.error(PortMappingUtils.CONMAP_ISSUE_LOGMSG, nodeId, skey, dkey);
245                 continue;
246             }
247             String slcp = lcpMap.get(skey);
248             Mapping mapping = mappingMap.get(slcp);
249             mappingMap.remove(slcp);
250             portMapList.add(createXpdrMappingObject(nodeId, null, null, null, null, mapping,
251                 //dlcp
252                 lcpMap.containsKey(dkey) ? lcpMap.get(dkey) : null));
253         }
254
255         mappingMap.forEach((k,v) -> portMapList.add(v));
256         return true;
257     }
258
259     private boolean checkPartnerPortNotNull(Ports port) {
260         return (port.getPartnerPort() != null
261             && port.getPartnerPort().getCircuitPackName() != null
262             && port.getPartnerPort().getPortName() != null);
263     }
264
265     private boolean checkPartnerPortNoDir(String circuitPackName, Ports port1, Ports port2) {
266         return (checkPartnerPortNotNull(port2)
267             && port2.getPartnerPort().getCircuitPackName().equals(circuitPackName)
268             && port2.getPartnerPort().getPortName().equals(port1.getPortName()));
269     }
270
271     private boolean checkPartnerPort(String circuitPackName, Ports port1, Ports port2) {
272         return checkPartnerPortNoDir(circuitPackName, port1, port2)
273             && Set.of(port1.getPortDirection().getIntValue(), port2.getPortDirection().getIntValue())
274                 .equals(TXRX_SET);
275     }
276
277     private HashMap<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg
278             .CircuitPacks>> getSrgCps(String deviceId, Info ordmInfo) {
279         HashMap<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg
280             .CircuitPacks>> cpPerSrg = new HashMap<>();
281         // Get value for max Srg from info subtree, required for iteration
282         // if not present assume to be 20 (temporary)
283         Integer maxSrg = ordmInfo.getMaxSrgs() == null ? 20 : ordmInfo.getMaxSrgs().toJava();
284         for (int srgCounter = 1; srgCounter <= maxSrg; srgCounter++) {
285             List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks> srgCps
286                 = new ArrayList<>();
287             LOG.debug(PortMappingUtils.GETTING_CP_LOGMSG, deviceId, srgCounter);
288             InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier
289                 .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
290                 .child(SharedRiskGroup.class, new SharedRiskGroupKey(Uint16.valueOf(srgCounter)))
291                 .build();
292             Optional<SharedRiskGroup> ordmSrgObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
293                 LogicalDatastoreType.OPERATIONAL, srgIID,
294                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
295             if (ordmSrgObject.isPresent()) {
296                 srgCps.addAll(ordmSrgObject.orElseThrow().nonnullCircuitPacks().values());
297                 cpPerSrg.put(ordmSrgObject.orElseThrow().getSrgNumber().toJava(), srgCps);
298             }
299         }
300         LOG.info(PortMappingUtils.DEVICE_HAS_LOGMSG, deviceId, cpPerSrg.size(), "SRG");
301         return cpPerSrg;
302     }
303
304     private boolean createPpPortMapping(String nodeId, Info deviceInfo, List<Mapping> portMapList) {
305         // Creating mapping data for SRG's PP
306         for (Entry<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks>>
307                 srgCpEntry : getSrgCps(nodeId, deviceInfo).entrySet()) {
308             List<String> keys = new ArrayList<>();
309             int portIndex = 1;
310             for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks
311                     cp : srgCpEntry.getValue()) {
312                 String circuitPackName = cp.getCircuitPackName();
313                 List<Ports> portList = getPortList(circuitPackName, nodeId);
314                 Collections.sort(portList, new SortPort121ByName());
315                 for (Ports port : portList) {
316                     if (!checkPortQual(port, circuitPackName, nodeId)) {
317                         continue;
318                     }
319                     String currentKey = circuitPackName + "-" + port.getPortName();
320                     if (keys.contains(currentKey)) {
321                         LOG.debug(PortMappingUtils.PORT_ALREADY_HANDLED_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
322                             nodeId, port.getPortName(), circuitPackName);
323                         continue;
324                     }
325                     switch (port.getPortDirection()) {
326                         case Bidirectional:
327                             String lcp = createLogicalConnectionPort(port, srgCpEntry.getKey(), portIndex);
328                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
329                                 nodeId, port.getPortName(), circuitPackName, lcp);
330                             portMapList.add(createMappingObject(nodeId, port, circuitPackName, lcp));
331                             portIndex++;
332                             keys.add(currentKey);
333                             break;
334                         case Rx:
335                         case Tx:
336                             Ports port2 = getPartnerPort(port, circuitPackName, nodeId);
337                             if (port2 == null) {
338                                 continue;
339                             }
340                             String lcp1 = createLogicalConnectionPort(port, srgCpEntry.getKey(), portIndex);
341                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
342                                 nodeId, port.getPortName(), circuitPackName, lcp1);
343                             String lcp2 = createLogicalConnectionPort(port2, srgCpEntry.getKey(),portIndex);
344                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
345                                 nodeId, port2.getPortName(), circuitPackName, lcp2);
346                             portMapList.add(createMappingObject(nodeId, port, circuitPackName, lcp1));
347                             portMapList.add(
348                                 createMappingObject(nodeId ,port2, port.getPartnerPort().getCircuitPackName(), lcp2));
349                             portIndex++;
350                             keys.add(currentKey);
351                             keys.add(port.getPartnerPort().getCircuitPackName() + "-" + port2.getPortName());
352                             break;
353                         default:
354                             LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
355                                 nodeId, port.getPortName(), circuitPackName, port.getPortDirection());
356                     }
357                 }
358             }
359         }
360         return true;
361     }
362
363     private Ports getPartnerPort(Ports port, String circuitPackName, String nodeId) {
364         if (!checkPartnerPortNotNull(port)) {
365             LOG.info(PortMappingUtils.NO_VALID_PARTNERPORT_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
366                 nodeId, port.getPortName(), circuitPackName);
367             return null;
368         }
369         InstanceIdentifier<Ports> port2ID = InstanceIdentifier
370             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
371             .child(CircuitPacks.class, new CircuitPacksKey(port.getPartnerPort().getCircuitPackName()))
372             .child(Ports.class, new PortsKey(port.getPartnerPort().getPortName()))
373             .build();
374         Optional<Ports> port2Object = this.deviceTransactionManager
375             .getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, port2ID,
376                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
377         if (port2Object.isEmpty()
378                 || port2Object.orElseThrow().getPortQual().getIntValue() != Port.PortQual.RoadmExternal.getIntValue()) {
379             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG + PortMappingUtils.PARTNERPORT_GET_ERROR_LOGMSG,
380                 nodeId, port.getPartnerPort().getPortName(), port.getPartnerPort().getCircuitPackName(),
381                 port.getPortName(), circuitPackName);
382             return null;
383         }
384         Ports port2 = port2Object.orElseThrow();
385         if (!checkPartnerPort(circuitPackName, port, port2)) {
386             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG + PortMappingUtils.PARTNERPORT_CONF_ERROR_LOGMSG,
387                 nodeId, port2.getPortName(), port.getPartnerPort().getCircuitPackName(),
388                 port.getPortName(), circuitPackName);
389             //TODO check if we really needed to increment portIndex in this condition
390             //     if yes this block should not be in getPartnerPort and must move back to createPpPortMapping
391             return null;
392         }
393         return port2;
394     }
395
396     private List<Ports> getPortList(String circuitPackName, String nodeId) {
397         InstanceIdentifier<CircuitPacks> cpIID = InstanceIdentifier
398             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
399             .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName))
400             .build();
401         Optional<CircuitPacks> circuitPackObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
402              LogicalDatastoreType.OPERATIONAL, cpIID,
403              Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
404         if (circuitPackObject.isEmpty()) {
405             LOG.warn(PortMappingUtils.MISSING_CP_LOGMSG + PortMappingUtils.PORTMAPPING_IGNORE_LOGMSG,
406                 nodeId, circuitPackName);
407             return new ArrayList<>();
408         }
409         if (circuitPackObject.orElseThrow().getPorts() == null) {
410             LOG.warn(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, PortMappingUtils.FOUND, circuitPackName);
411             return new ArrayList<>();
412         }
413         return new ArrayList<>(circuitPackObject.orElseThrow().nonnullPorts().values());
414     }
415
416     private String createLogicalConnectionPort(Ports port, int index, int portIndex) {
417         if (SUFFIX.containsKey(port.getPortDirection())) {
418             return String.join("-", "SRG" + index, "PP" + portIndex, SUFFIX.get(port.getPortDirection()));
419         }
420         LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG,
421             "createLogicalConnectionPort", port, "SRG" + index + "-PP" + portIndex, port.getPortDirection());
422         return null;
423     }
424
425     @SuppressFBWarnings(
426         value = "SLF4J_UNKNOWN_ARRAY",
427         justification = "False positive")
428     private Map<Integer, Degree> getDegreesMap(String deviceId, Info ordmInfo) {
429         Map<Integer, Degree> degrees = new HashMap<>();
430
431         // Get value for max degree from info subtree, required for iteration
432         // if not present assume to be 20 (temporary)
433         Integer maxDegree = ordmInfo.getMaxDegrees() == null ? 20 : ordmInfo.getMaxDegrees().toJava();
434
435         for (int degreeCounter = 1; degreeCounter <= maxDegree; degreeCounter++) {
436             LOG.debug(PortMappingUtils.GETTING_CONPORT_LOGMSG, deviceId, degreeCounter);
437             InstanceIdentifier<Degree> deviceIID = InstanceIdentifier
438                 .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
439                 .child(Degree.class, new DegreeKey(Uint16.valueOf(degreeCounter)))
440                 .build();
441             Optional<Degree> ordmDegreeObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
442                 LogicalDatastoreType.OPERATIONAL, deviceIID,
443                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
444             if (ordmDegreeObject.isPresent()) {
445                 degrees.put(degreeCounter, ordmDegreeObject.orElseThrow());
446             }
447         }
448         LOG.info(PortMappingUtils.DEVICE_HAS_LOGMSG,
449                 deviceId, degrees.size(), degrees.size() <= 1 ? "degree" : "degrees");
450         return degrees;
451     }
452
453     private Map<Integer, List<ConnectionPorts>> getPerDegreePorts(String deviceId, Info ordmInfo) {
454         Map<Integer, List<ConnectionPorts>> conPortMap = new HashMap<>();
455         getDegreesMap(deviceId, ordmInfo).forEach(
456             (index, degree) -> conPortMap.put(index, new ArrayList<>(degree.nonnullConnectionPorts().values())));
457         return conPortMap;
458     }
459
460     private Map<String, String> getEthInterfaceList(String nodeId) {
461         LOG.info(PortMappingUtils.GETTING_ETH_LIST_LOGMSG, nodeId);
462         InstanceIdentifier<Protocols> protocoliid = InstanceIdentifier
463             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
464             .child(Protocols.class)
465             .build();
466         Optional<Protocols> protocolObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
467             LogicalDatastoreType.OPERATIONAL, protocoliid, Timeouts.DEVICE_READ_TIMEOUT,
468             Timeouts.DEVICE_READ_TIMEOUT_UNIT);
469         if (protocolObject.isEmpty() || protocolObject.orElseThrow().augmentation(Protocols1.class).getLldp() == null) {
470             LOG.warn(PortMappingUtils.PROCESSING_DONE_LOGMSG, nodeId, PortMappingUtils.CANNOT_GET_LLDP_CONF_LOGMSG);
471             return new HashMap<>();
472         }
473         Map<String, String> cpToInterfaceMap = new HashMap<>();
474         Lldp lldp = protocolObject.orElseThrow().augmentation(Protocols1.class).getLldp();
475         for (PortConfig portConfig : lldp.nonnullPortConfig().values()) {
476             if (!portConfig.getAdminStatus().equals(PortConfig.AdminStatus.Txandrx)) {
477                 continue;
478             }
479             InstanceIdentifier<Interface> interfaceIID = InstanceIdentifier
480                 .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
481                 .child(Interface.class, new InterfaceKey(portConfig.getIfName()))
482                 .build();
483             Optional<Interface> interfaceObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
484                 LogicalDatastoreType.OPERATIONAL, interfaceIID, Timeouts.DEVICE_READ_TIMEOUT,
485                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
486             if (interfaceObject.isEmpty() || interfaceObject.orElseThrow().getSupportingCircuitPackName() == null) {
487                 continue;
488             }
489             String supportingCircuitPackName = interfaceObject.orElseThrow().getSupportingCircuitPackName();
490             cpToInterfaceMap.put(supportingCircuitPackName, portConfig.getIfName());
491             InstanceIdentifier<CircuitPacks> circuitPacksIID = InstanceIdentifier
492                 .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
493                 .child(CircuitPacks.class, new CircuitPacksKey(supportingCircuitPackName))
494                 .build();
495             Optional<CircuitPacks> circuitPackObject = this.deviceTransactionManager.getDataFromDevice(
496                 nodeId, LogicalDatastoreType.OPERATIONAL, circuitPacksIID, Timeouts.DEVICE_READ_TIMEOUT,
497                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
498             if (circuitPackObject.isEmpty() || circuitPackObject.orElseThrow().getParentCircuitPack() == null) {
499                 continue;
500             }
501             cpToInterfaceMap.put(circuitPackObject.orElseThrow().getParentCircuitPack().getCircuitPackName(),
502                 portConfig.getIfName());
503         }
504         LOG.info(PortMappingUtils.PROCESSING_DONE_LOGMSG, nodeId, " - success");
505         return cpToInterfaceMap;
506     }
507
508     private List<CpToDegree> getCpToDegreeList(Map<Integer, Degree> degrees, Map<String, String> interfaceList) {
509         List<CpToDegree> cpToDegreeList = new ArrayList<>();
510         for (Degree degree : degrees.values()) {
511             cpToDegreeList.addAll(degree.nonnullCircuitPacks().values().stream()
512                 .map(cp -> createCpToDegreeObject(cp.getCircuitPackName(),
513                     degree.getDegreeNumber().toString(), interfaceList))
514                 .collect(Collectors.toList()));
515         }
516         return cpToDegreeList;
517     }
518
519     private boolean postPortMapping(String nodeId, NodeInfo nodeInfo, List<Mapping> portMapList,
520             List<CpToDegree> cp2DegreeList) {
521         NodesBuilder nodesBldr = new NodesBuilder().withKey(new NodesKey(nodeId)).setNodeId(nodeId);
522         if (nodeInfo != null) {
523             nodesBldr.setNodeInfo(nodeInfo);
524         }
525         if (portMapList != null) {
526             Map<MappingKey, Mapping> mappingMap = new HashMap<>();
527             // No element in the list below should be null at this stage
528             for (Mapping mapping: portMapList) {
529                 mappingMap.put(mapping.key(), mapping);
530             }
531             nodesBldr.setMapping(mappingMap);
532         }
533         if (cp2DegreeList != null) {
534             Map<CpToDegreeKey, CpToDegree> cpToDegreeMap = new HashMap<>();
535             // No element in the list below should be null at this stage
536             for (CpToDegree cp2Degree: cp2DegreeList) {
537                 cpToDegreeMap.put(cp2Degree.key(), cp2Degree);
538             }
539             nodesBldr.setCpToDegree(cpToDegreeMap);
540         }
541
542         Map<NodesKey,Nodes> nodesList = new HashMap<>();
543         Nodes nodes = nodesBldr.build();
544         nodesList.put(nodes.key(),nodes);
545
546         Network network = new NetworkBuilder().setNodes(nodesList).build();
547
548         final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
549         InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
550         writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, network);
551         FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
552         try {
553             commit.get();
554             return true;
555         } catch (InterruptedException | ExecutionException e) {
556             LOG.warn(PortMappingUtils.PORTMAPPING_POST_FAIL_LOGMSG, nodeId, network, e);
557             return false;
558         }
559     }
560
561     private CpToDegree createCpToDegreeObject(String circuitPackName, String degreeNumber,
562             Map<String, String> interfaceList) {
563         return new CpToDegreeBuilder()
564             .withKey(new CpToDegreeKey(circuitPackName))
565             .setCircuitPackName(circuitPackName)
566             .setDegreeNumber(Uint32.valueOf(degreeNumber))
567             .setInterfaceName(interfaceList.get(circuitPackName)).build();
568     }
569
570     private Mapping createMappingObject(String nodeId, Ports port, String circuitPackName,
571             String logicalConnectionPoint) {
572         MappingBuilder mpBldr = new MappingBuilder()
573                 .withKey(new MappingKey(logicalConnectionPoint))
574                 .setLogicalConnectionPoint(logicalConnectionPoint)
575                 .setSupportingCircuitPackName(circuitPackName)
576                 .setSupportingPort(port.getPortName())
577                 .setPortDirection(port.getPortDirection().getName());
578         if (port.getAdministrativeState() != null) {
579             mpBldr.setPortAdminState(port.getAdministrativeState().name());
580         }
581         if (port.getOperationalState() != null) {
582             mpBldr.setPortOperState(port.getOperationalState().name());
583         }
584         if (!logicalConnectionPoint.contains(StringConstants.TTP_TOKEN) || (port.getInterfaces() == null)) {
585             return mpBldr.build();
586         }
587         mpBldr = updateMappingInterfaces(nodeId, mpBldr, port);
588         return mpBldr.build();
589     }
590
591     private Mapping updateMappingObject(String nodeId, Ports port, Mapping oldmapping) {
592         MappingBuilder mpBldr = new MappingBuilder(oldmapping);
593         updateMappingStates(mpBldr, port, oldmapping);
594         if (port.getInterfaces() == null) {
595             return mpBldr.build();
596         }
597         // Get interfaces provisioned on the port
598         mpBldr = updateMappingInterfaces(nodeId, mpBldr, port);
599         return mpBldr.build();
600     }
601
602     private MappingBuilder updateMappingStates(MappingBuilder mpBldr, Ports port, Mapping oldmapping) {
603         if (port.getAdministrativeState() != null
604             && !port.getAdministrativeState().getName().equals(oldmapping.getPortAdminState())) {
605             mpBldr.setPortAdminState(port.getAdministrativeState().name());
606         }
607         if (port.getOperationalState() != null
608             && !port.getOperationalState().getName().equals(oldmapping.getPortOperState())) {
609             mpBldr.setPortOperState(port.getOperationalState().name());
610         }
611         return mpBldr;
612     }
613
614     private MappingBuilder updateMappingInterfaces(String nodeId, MappingBuilder mpBldr, Ports port) {
615         mpBldr.setSupportingOtu4(null).setSupportingOdu4(null);
616         for (Interfaces interfaces : port.getInterfaces()) {
617             Optional<Interface> openRoadmInterface = getInterfaceFromDevice(nodeId, interfaces.getInterfaceName());
618             if (openRoadmInterface.isEmpty()) {
619                 LOG.warn(PortMappingUtils.INTF_ISSUE_LOGMSG,
620                     nodeId, interfaces.getInterfaceName() + "- empty interface");
621                 continue;
622             }
623             InterfaceType interfaceType = openRoadmInterface.orElseThrow().getType();
624             LOG.debug(PortMappingUtils.GOT_INTF_LOGMSG, nodeId, openRoadmInterface.orElseThrow().getName(),
625                     interfaceType);
626             // Switch/Case might be more indicated here but is not possible in jdk17 w/o enable-preview
627             if (interfaceType.equals(OpenROADMOpticalMultiplex.VALUE)) {
628                 mpBldr.setSupportingOms(interfaces.getInterfaceName());
629             } else if (interfaceType.equals(OpticalTransport.VALUE)) {
630                 mpBldr.setSupportingOts(interfaces.getInterfaceName());
631             } else if (interfaceType.equals(OtnOtu.VALUE)) {
632                 mpBldr.setSupportingOtu4(interfaces.getInterfaceName());
633             } else if (interfaceType.equals(OtnOdu.VALUE)) {
634                 mpBldr.setSupportingOdu4(interfaces.getInterfaceName());
635             } else if (interfaceType.equals(EthernetCsmacd.VALUE)) {
636                 mpBldr.setSupportingEthernet(interfaces.getInterfaceName());
637             }
638         }
639         return mpBldr;
640     }
641
642     private Mapping createXpdrMappingObject(String nodeId, Ports port, String circuitPackName,
643             String logicalConnectionPoint, String partnerLcp, Mapping mapping, String assoLcp) {
644
645         if (mapping != null && assoLcp != null) {
646             // update existing mapping
647             return new MappingBuilder(mapping).setConnectionMapLcp(assoLcp).build();
648         }
649         return createNewXpdrMapping(nodeId, port, circuitPackName, logicalConnectionPoint, partnerLcp);
650     }
651
652     private Mapping createNewXpdrMapping(String nodeId, Ports port, String circuitPackName,
653             String logicalConnectionPoint, String partnerLcp) {
654         Set<org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev230526.SupportedIfCapability> supportedIntf =
655             new HashSet<>();
656         for (String sup: getSupIfCapList(port)) {
657             if (MappingUtilsImpl.convertSupIfCapa(sup) != null) {
658                 supportedIntf.add(MappingUtilsImpl.convertSupIfCapa(sup));
659             }
660         }
661         MappingBuilder mpBldr = new MappingBuilder()
662                 .withKey(new MappingKey(logicalConnectionPoint))
663                 .setLogicalConnectionPoint(logicalConnectionPoint)
664                 .setSupportingCircuitPackName(circuitPackName)
665                 .setSupportingPort(port.getPortName())
666                 .setPortDirection(port.getPortDirection().getName())
667                 .setXpdrType(XpdrNodeTypes.Tpdr)
668                 .setLcpHashVal(PortMappingUtils.fnv1size64(nodeId + "-" + logicalConnectionPoint))
669                 .setSupportedInterfaceCapability(supportedIntf);
670         if (port.getPortQual() != null) {
671             mpBldr.setPortQual(port.getPortQual().getName());
672         }
673         if (partnerLcp != null) {
674             mpBldr.setPartnerLcp(partnerLcp);
675         }
676         if (port.getAdministrativeState() != null) {
677             mpBldr.setPortAdminState(port.getAdministrativeState().name());
678         }
679         if (port.getOperationalState() != null) {
680             mpBldr.setPortOperState(port.getOperationalState().name());
681         }
682         return mpBldr.build();
683     }
684
685     private List<String> getSupIfCapList(Ports port) {
686         Set<SupportedIfCapability> supIfCapClassList = port.getSupportedInterfaceCapability();
687         return
688             supIfCapClassList == null
689                 ? Collections.emptyList()
690                 : supIfCapClassList
691                     .stream().map(e -> e.toString())
692                     .collect(Collectors.toList());
693     }
694
695     private Ports getPort2(Ports port, String nodeId, String circuitPackName, StringBuilder circuitPackName2,
696             //circuitPackName2 will be updated by reference contrary to circuitPackName
697             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap) {
698         if (!checkPartnerPortNotNull(port)) {
699             LOG.warn(PortMappingUtils.NO_VALID_PARTNERPORT_LOGMSG, nodeId, port.getPortName(), circuitPackName);
700             return null;
701         }
702         if (lcpMap.containsKey(circuitPackName + '+' + port.getPortName())) {
703             return null;
704         }
705         Optional<CircuitPacks> cpOpt = circuitPackList.stream()
706             .filter(cP -> cP.getCircuitPackName().equals(port.getPartnerPort().getCircuitPackName()))
707             .findFirst();
708         if (cpOpt.isEmpty()) {
709             LOG.error(PortMappingUtils.MISSING_CP_LOGMSG, nodeId, port.getPartnerPort().getCircuitPackName());
710             return null;
711         }
712         Optional<Ports> poOpt = cpOpt.orElseThrow().nonnullPorts().values().stream()
713             .filter(p -> p.getPortName().equals(port.getPartnerPort().getPortName()))
714             .findFirst();
715         if (poOpt.isEmpty()) {
716             LOG.error(PortMappingUtils.NO_PORT_ON_CP_LOGMSG,
717                 nodeId, port.getPartnerPort().getPortName(), port.getPartnerPort().getCircuitPackName());
718             return null;
719         }
720         Ports port2 = poOpt.orElseThrow();
721         circuitPackName2.append(cpOpt.orElseThrow().getCircuitPackName());
722         if (!checkPartnerPort(circuitPackName, port, port2)) {
723             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
724                 nodeId, port2.getPortName(), circuitPackName2, port.getPortName(), circuitPackName);
725             return null;
726         }
727         return port2;
728     }
729
730     private void putXpdrLcpsInMaps(int line, String nodeId,
731             Integer xponderNb,
732             String circuitPackName, String circuitPackName2, Ports port, Ports port2,
733             Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
734         String lcp1 =
735             PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line, StringConstants.NETWORK_TOKEN);
736         if (lcpMap.containsKey(lcp1)) {
737             LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, "add", lcp1 + " - already exist");
738             return;
739         }
740         String lcp2 =
741             PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line + 1, StringConstants.NETWORK_TOKEN);
742         if (lcpMap.containsKey(lcp2)) {
743             LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, "add", lcp2 + " - already exist");
744             return;
745         }
746         lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp1);
747         lcpMap.put(circuitPackName2 + '+' + port2.getPortName(), lcp2);
748         mappingMap.put(lcp1,
749                 createXpdrMappingObject(nodeId, port, circuitPackName, lcp1, lcp2, null, null));
750         mappingMap.put(lcp2,
751                 createXpdrMappingObject(nodeId, port2, circuitPackName2, lcp2, lcp1, null, null));
752         return;
753     }
754
755     private int[] fillXpdrLcpsMaps(int line, int client, String nodeId,
756             Integer xponderNb,
757             String circuitPackName,  Ports port,
758             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
759
760         if (port.getPortQual() == null) {
761             LOG.warn(PortMappingUtils.PORTQUAL_LOGMSG, nodeId, port.getPortName(), circuitPackName, "not found");
762             return new int[] {line, client};
763         }
764
765         switch (port.getPortQual()) {
766
767             case XpdrClient:
768                 String lcp0 =
769                     PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, client, StringConstants.CLIENT_TOKEN);
770                 lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp0);
771                 mappingMap.put(lcp0,
772                     createXpdrMappingObject(nodeId, port, circuitPackName, lcp0, null, null, null));
773                 client++;
774                 break;
775
776             case XpdrNetwork:
777                 line = fillXpdrNetworkLcpsMaps(line, nodeId,
778                         xponderNb,
779                         circuitPackName,  port,
780                         circuitPackList,  lcpMap, mappingMap);
781                 break;
782
783             default:
784                 LOG.error(PortMappingUtils.PORTQUAL_LOGMSG,
785                     nodeId, port.getPortName(), circuitPackName, port.getPortQual() + " not supported");
786         }
787         return new int[] {line, client};
788     }
789
790     private int fillXpdrNetworkLcpsMaps(int line, String nodeId,
791             Integer xponderNb,
792             String circuitPackName,  Ports port,
793             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
794
795         switch (port.getPortDirection()) {
796
797             case Bidirectional:
798                 String lcp =
799                     PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line, StringConstants.NETWORK_TOKEN);
800                 lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp);
801                 mappingMap.put(lcp,
802                     createXpdrMappingObject(nodeId, port, circuitPackName, lcp, null, null, null));
803                 line++;
804                 break;
805
806             case Rx:
807             case Tx:
808                 StringBuilder circuitPackName2 = new StringBuilder();
809                 Ports port2 = getPort2(port, nodeId, circuitPackName, circuitPackName2,
810                         circuitPackList, lcpMap);
811
812                 if (port2 == null) {
813                      //key already present or an error occured and was logged
814                     return line;
815                 }
816
817                 putXpdrLcpsInMaps(line, nodeId, xponderNb,
818                         circuitPackName, circuitPackName2.toString(), port, port2,
819                         lcpMap, mappingMap);
820
821                 line += 2;
822                 break;
823
824             default:
825                 LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG,
826                      nodeId, port.getPortName(), circuitPackName, port.getPortDirection());
827         }
828
829         return line;
830     }
831
832     private boolean createTtpPortMapping(String nodeId, Info deviceInfo, List<Mapping> portMapList) {
833         // Creating mapping data for degree TTP's
834         Map<Integer, Degree> degrees = getDegreesMap(nodeId, deviceInfo);
835         Map<String, String> interfaceList = getEthInterfaceList(nodeId);
836         List<CpToDegree> cpToDegreeList = getCpToDegreeList(degrees, interfaceList);
837         LOG.info(PortMappingUtils.MAP_LOOKS_LOGMSG, nodeId, interfaceList);
838         postPortMapping(nodeId, null, null, cpToDegreeList);
839
840         Map<Integer, List<ConnectionPorts>> connectionPortMap = getPerDegreePorts(nodeId, deviceInfo);
841         for (Entry<Integer, List<ConnectionPorts>> cpMapEntry : connectionPortMap.entrySet()) {
842             List<ConnectionPorts> cpMapValue = cpMapEntry.getValue();
843             ConnectionPorts cp1 = cpMapValue.get(0);
844             String cp1Name = cp1.getCircuitPackName();
845             switch (cpMapValue.size()) {
846                 case 1:
847                     // port is bidirectional
848                     Ports port = getTtpPort(cp1, cp1Name, nodeId);
849                     if (port == null) {
850                         return false;
851                     }
852                     if (!checkTtpPort(port, cp1Name, nodeId, true)) {
853                         continue;
854                     }
855                     String logicalConnectionPoint =
856                             PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(), "TXRX");
857                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
858                         nodeId, port.getPortName(), cp1Name, logicalConnectionPoint);
859                     portMapList.add(createMappingObject(nodeId, port, cp1Name, logicalConnectionPoint));
860                     break;
861                 case 2:
862                     // ports are unidirectionals
863                     Ports port1 = getTtpPort(cp1, cp1Name, nodeId);
864                     if (port1 == null) {
865                         return false;
866                     }
867                     ConnectionPorts cp2 = cpMapValue.get(1);
868                     String cp2Name = cp2.getCircuitPackName();
869                     Ports port2 = getTtpPort(cp2, cp2Name, nodeId);
870                     if (port2 == null) {
871                         return false;
872                     }
873                     if (!checkTtpPortsUnidir(port1, port2, cp1Name, cp2Name, nodeId)) {
874                         continue;
875                     }
876                     String logicalConnectionPoint1 = PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(),
877                             port1.getPortDirection().getName().toUpperCase(Locale.getDefault()));
878                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
879                         nodeId, port1.getPortName(), cp1Name, logicalConnectionPoint1);
880                     portMapList.add(createMappingObject(nodeId, port1, cp1Name, logicalConnectionPoint1));
881                     String logicalConnectionPoint2 = PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(),
882                             port2.getPortDirection().getName().toUpperCase(Locale.getDefault()));
883                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
884                         nodeId, port2.getPortName(), cp2Name, logicalConnectionPoint2);
885                     portMapList.add(createMappingObject(nodeId, port2, cp2Name, logicalConnectionPoint2));
886                     break;
887                 default:
888                     LOG.error(PortMappingUtils.NOT_CORRECT_CONPORT_LOGMSG, nodeId, cpMapEntry.getKey());
889                     continue;
890                     //TODO should it be continue or return false ?
891             }
892         }
893         return true;
894     }
895
896     private Ports getTtpPort(ConnectionPorts cp, String cpName, String nodeId) {
897         InstanceIdentifier<Ports> portID = InstanceIdentifier
898             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
899             .child(CircuitPacks.class, new CircuitPacksKey(cpName))
900             .child(Ports.class, new PortsKey(cp.getPortName()))
901             .build();
902         LOG.debug(PortMappingUtils.FETCH_CONNECTIONPORT_LOGMSG, nodeId, cp.getPortName(), cpName);
903         Optional<Ports> portObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
904             LogicalDatastoreType.OPERATIONAL, portID, Timeouts.DEVICE_READ_TIMEOUT,
905             Timeouts.DEVICE_READ_TIMEOUT_UNIT);
906         if (portObject.isEmpty()) {
907             LOG.error(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, cp.getPortName(), cpName);
908             return null;
909         }
910         return portObject.orElseThrow();
911     }
912
913     private boolean checkPortQual(Ports port, String cpName, String nodeId) {
914         if (port.getPortQual() == null) {
915             return false;
916         }
917         if (Port.PortQual.RoadmExternal.getIntValue() != port.getPortQual().getIntValue()) {
918             //used to be LOG.error when called from createTtpPortMapping
919             LOG.debug(PortMappingUtils.PORT_NOT_RDMEXT_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
920                 nodeId, port.getPortName(), cpName);
921             return false;
922         }
923         return true;
924     }
925
926     private boolean checkTtpPort(Ports port, String cpName, String nodeId, boolean bidirectional) {
927         if (!checkPortQual(port, cpName, nodeId)) {
928             return false;
929         }
930         if (Direction.Bidirectional.getIntValue() == port.getPortDirection().getIntValue() ^ bidirectional) {
931         // (a ^ b) makes more sense than (!a && b) here since it can also work for unidirectional links
932             LOG.error(PortMappingUtils.PORTDIR_ERROR_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
933                 nodeId, port.getPortName(), cpName);
934             return false;
935         }
936         return true;
937     }
938
939     private boolean checkTtpPortsUnidir(Ports port1, Ports port2, String cp1Name, String cp2Name, String nodeId) {
940         if (!checkTtpPort(port1, cp1Name, nodeId, false)) {
941             return false;
942         }
943         if (!checkTtpPort(port2, cp2Name, nodeId, false)) {
944             return false;
945         }
946         if (!checkPartnerPort(cp1Name, port1, port2)) {
947             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
948                 nodeId, port2.getPortName(), cp2Name, port1.getPortName(), cp1Name);
949             return false;
950         }
951         // Directions checks are the same for cp1 and cp2, no need to check them twice.
952         if (!checkPartnerPortNoDir(cp2Name, port2, port1)) {
953             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
954                 nodeId, port1.getPortName(), cp1Name, port2.getPortName(), cp2Name);
955             return false;
956         }
957         return true;
958     }
959
960     private NodeInfo createNodeInfo(Info deviceInfo) {
961         if (deviceInfo.getNodeType() == null) {
962             // TODO make mandatory in yang
963             LOG.error(PortMappingUtils.NODE_TYPE_LOGMSG, deviceInfo.getNodeId(), "field missing");
964             return null;
965         }
966         NodeInfoBuilder nodeInfoBldr = new NodeInfoBuilder()
967                 .setOpenroadmVersion(OpenroadmNodeVersion._121)
968                 .setNodeClli(
969                     deviceInfo.getClli() == null || deviceInfo.getClli().isEmpty()
970                         ? "defaultCLLI"
971                         : deviceInfo.getClli());
972         // TODO check if we can use here .setNodeType(NodeTypes.forValue(..) such as with 221
973         switch (deviceInfo.getNodeType().getIntValue()) {
974             case 1:
975             case 2:
976                 nodeInfoBldr.setNodeType(NodeTypes.forValue(deviceInfo.getNodeType().getIntValue()));
977                 break;
978             default:
979                 LOG.error(PortMappingUtils.NODE_TYPE_LOGMSG, deviceInfo.getNodeId(), "value not supported");
980                 // TODO: is this protection useful ? it is not present in Portmapping 221
981         }
982         if (deviceInfo.getModel() != null) {
983             nodeInfoBldr.setNodeModel(deviceInfo.getModel());
984         }
985         if (deviceInfo.getVendor() != null) {
986             nodeInfoBldr.setNodeVendor(deviceInfo.getVendor());
987         }
988         if (deviceInfo.getIpAddress() != null) {
989             nodeInfoBldr.setNodeIpAddress(deviceInfo.getIpAddress());
990         }
991         return nodeInfoBldr.build();
992     }
993
994     private Optional<Interface> getInterfaceFromDevice(String nodeId, String interfaceName) {
995         InstanceIdentifier<Interface> interfacesIID = InstanceIdentifier
996             .builderOfInherited(OrgOpenroadmDeviceData.class, OrgOpenroadmDevice.class)
997             .child(Interface.class, new InterfaceKey(interfaceName))
998             .build();
999         return deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.CONFIGURATION,
1000             interfacesIID, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
1001     }
1002 }