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