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