e1d9b6d0cedf80eb05cd0b4556faf54056968f94
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / mapping / PortMappingVersion710.java
1 /*
2  * Copyright © 2020 AT&T, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
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.Collection;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.HashMap;
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.ReadTransaction;
28 import org.opendaylight.mdsal.binding.api.WriteTransaction;
29 import org.opendaylight.mdsal.common.api.CommitInfo;
30 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
31 import org.opendaylight.transportpce.common.StringConstants;
32 import org.opendaylight.transportpce.common.Timeouts;
33 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.Network;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.NetworkBuilder;
36 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.OpenroadmNodeVersion;
37 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.cp.to.degree.CpToDegree;
38 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.cp.to.degree.CpToDegreeBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.cp.to.degree.CpToDegreeKey;
40 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.Mapping;
41 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.MappingBuilder;
42 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mapping.MappingKey;
43 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mc.capabilities.McCapabilities;
44 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mc.capabilities.McCapabilitiesBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mc.capabilities.McCapabilitiesKey;
46 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.mpdr.restrictions.grp.MpdrRestrictionsBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.Nodes;
48 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.NodesBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.NodesKey;
50 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.nodes.NodeInfo;
51 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.network.nodes.NodeInfoBuilder;
52 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.SwitchingPoolLcp;
53 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.SwitchingPoolLcpBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.SwitchingPoolLcpKey;
55 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.switching.pool.lcp.NonBlockingList;
56 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.switching.pool.lcp.NonBlockingListBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210927.switching.pool.lcp.switching.pool.lcp.NonBlockingListKey;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.alarm.pm.types.rev191129.Direction;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyGHz;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.CircuitPack;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.pack.Ports;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.pack.PortsKey;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.packs.CircuitPacks;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.circuit.packs.CircuitPacksKey;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.degree.ConnectionPorts;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.Interface;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceKey;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.OrgOpenroadmDevice;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.ConnectionMap;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.Degree;
71 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.DegreeKey;
72 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.Info;
73 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.McCapabilityProfile;
74 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.McCapabilityProfileKey;
75 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.MuxpProfile;
76 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.MuxpProfileKey;
77 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.OduSwitchingPools;
78 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.Protocols;
79 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup;
80 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey;
81 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.Xponder;
82 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.connection.map.Destination;
83 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org.openroadm.device.odu.switching.pools.non.blocking.list.PortList;
84 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.port.Interfaces;
85 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.xponder.XpdrPort;
86 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
87 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.PortQual;
88 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes;
89 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.InterfaceType;
90 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OpenROADMOpticalMultiplex;
91 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OpticalTransport;
92 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtnOdu;
93 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev200529.Protocols1;
94 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev200529.lldp.container.Lldp;
95 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev200529.lldp.container.lldp.PortConfig;
96 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
97 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.capability.rev200529.Ports1;
98 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.capability.rev200529.port.capability.grp.port.capabilities.SupportedInterfaceCapability;
99 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
100 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
101 import org.opendaylight.yangtools.yang.common.Uint16;
102 import org.opendaylight.yangtools.yang.common.Uint32;
103 import org.slf4j.Logger;
104 import org.slf4j.LoggerFactory;
105
106
107 // FIXME: many common pieces of code between PortMapping Versions 121 and 221 and 710
108 // some mutualization would be helpful
109 @SuppressWarnings("CPD-START")
110 public class PortMappingVersion710 {
111
112     private static final Logger LOG = LoggerFactory.getLogger(PortMappingVersion710.class);
113     private static final Map<Direction, String> SUFFIX;
114     private static final Set<Integer> TXRX_SET = Set.of(Direction.Tx.getIntValue(), Direction.Rx.getIntValue());
115
116     private final DataBroker dataBroker;
117     private final DeviceTransactionManager deviceTransactionManager;
118
119     static {
120         SUFFIX =  Map.of(
121             Direction.Tx, "TX",
122             Direction.Rx, "RX",
123             Direction.Bidirectional, "TXRX");
124     }
125
126     public PortMappingVersion710(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager) {
127         this.dataBroker = dataBroker;
128         this.deviceTransactionManager = deviceTransactionManager;
129     }
130
131     public boolean createMappingData(String nodeId) {
132         LOG.info(PortMappingUtils.CREATE_MAPPING_DATA_LOGMSG, nodeId, "7.1");
133         List<Mapping> portMapList = new ArrayList<>();
134         Map<McCapabilitiesKey, McCapabilities> mcCapabilities = new HashMap<>();
135         InstanceIdentifier<Info> infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class);
136         Optional<Info> deviceInfoOptional = this.deviceTransactionManager.getDataFromDevice(
137                 nodeId, LogicalDatastoreType.OPERATIONAL, infoIID,
138                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
139         if (deviceInfoOptional.isEmpty()) {
140             LOG.warn(PortMappingUtils.DEVICE_HAS_LOGMSG, nodeId, "no info", "subtree");
141             return false;
142         }
143         Info deviceInfo = deviceInfoOptional.get();
144         NodeInfo nodeInfo = createNodeInfo(deviceInfo);
145         if (nodeInfo == null) {
146             return false;
147         }
148         postPortMapping(nodeId, nodeInfo, null, null, null, null);
149
150         switch (deviceInfo.getNodeType()) {
151
152             case Rdm:
153                 // Get TTP port mapping
154                 if (!createTtpPortMapping(nodeId, deviceInfo, portMapList)) {
155                     // return false if mapping creation for TTP's failed
156                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "TTP's");
157                     return false;
158                 }
159
160                 // Get PP port mapping
161                 if (!createPpPortMapping(nodeId, deviceInfo, portMapList)) {
162                     // return false if mapping creation for PP's failed
163                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "PP's");
164                     return false;
165                 }
166                 // Get MC capabilities
167                 if (!createMcCapabilitiesList(nodeId, deviceInfo, mcCapabilities)) {
168                     // return false if MC capabilites failed
169                     LOG.warn(PortMappingUtils.UNABLE_MC_CAPA_LOGMSG, nodeId);
170                     return false;
171                 }
172                 break;
173             case Xpdr:
174                 if (!createXpdrPortMapping(nodeId, portMapList)) {
175                     LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.CREATE, "Xponder");
176                     return false;
177                 }
178                 // In the case of 7.1 models, even XPDR advertizes mc-capabilities,
179                 // hence we need to populate this information into the port-mapping data
180                 // Get MC capabilities
181                 if (!createMcCapabilitiesList(nodeId, deviceInfo, mcCapabilities)) {
182                     // return false if MC capabilites failed
183                     LOG.warn(PortMappingUtils.UNABLE_MC_CAPA_LOGMSG, nodeId);
184                     return false;
185                 }
186                 break;
187             default:
188                 LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG,
189                     nodeId, PortMappingUtils.CREATE, deviceInfo.getNodeType() + " - unknown nodetype");
190                 break;
191
192         }
193         return postPortMapping(nodeId, nodeInfo, portMapList, null, null, mcCapabilities);
194     }
195
196     public boolean updateMapping(String nodeId, Mapping oldMapping) {
197         if (nodeId == null) {
198             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG, "node id null" , PortMappingUtils.UPDATE, "a null value");
199             return false;
200         }
201         if (oldMapping == null) {
202             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, PortMappingUtils.UPDATE, "a null value");
203             return false;
204         }
205         InstanceIdentifier<Ports> portId = InstanceIdentifier.create(OrgOpenroadmDevice.class)
206             .child(CircuitPacks.class, new CircuitPacksKey(oldMapping.getSupportingCircuitPackName()))
207             .child(Ports.class, new PortsKey(oldMapping.getSupportingPort()));
208         try {
209             Ports port = deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL,
210                 portId, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT).get();
211             Mapping newMapping = updateMappingObject(nodeId, port, oldMapping);
212             LOG.debug(PortMappingUtils.UPDATE_MAPPING_LOGMSG,
213                 nodeId, oldMapping, oldMapping.getLogicalConnectionPoint(), newMapping);
214             final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction();
215             InstanceIdentifier<Mapping> mapIID = InstanceIdentifier.create(Network.class)
216                 .child(Nodes.class, new NodesKey(nodeId))
217                 .child(Mapping.class, new MappingKey(oldMapping.getLogicalConnectionPoint()));
218             writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, mapIID, newMapping);
219             FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
220             commit.get();
221             return true;
222         } catch (InterruptedException | ExecutionException e) {
223             LOG.error(PortMappingUtils.UNABLE_MAPPING_LOGMSG,
224                 nodeId, PortMappingUtils.UPDATE, oldMapping.getLogicalConnectionPoint(), e);
225             return false;
226         }
227     }
228
229     public boolean updatePortMappingWithOduSwitchingPools(String nodeId, InstanceIdentifier<OduSwitchingPools> ospIID,
230             Map<Uint16, List<InstanceIdentifier<PortList>>> nbliidMap) {
231
232         KeyedInstanceIdentifier<Nodes, NodesKey> portMappingNodeIID =
233             InstanceIdentifier.create(Network.class).child(Nodes.class, new NodesKey(nodeId));
234         Nodes portmappingNode = null;
235         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
236             portmappingNode = readTx.read(LogicalDatastoreType.CONFIGURATION, portMappingNodeIID).get().get();
237         } catch (InterruptedException | ExecutionException ex) {
238             LOG.error("Unable to read the port-mapping for nodeId {}", nodeId, ex);
239         }
240         if (portmappingNode == null) {
241             return false;
242         }
243
244         OduSwitchingPools osp = deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL,
245             ospIID, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT).get();
246         Uint16 ospNumber = osp.getSwitchingPoolNumber();
247         Map<SwitchingPoolLcpKey, SwitchingPoolLcp> splMap =
248             new HashMap<SwitchingPoolLcpKey, SwitchingPoolLcp>(portmappingNode.nonnullSwitchingPoolLcp());
249         SwitchingPoolLcpBuilder splBldr = splMap.containsKey(new SwitchingPoolLcpKey(ospNumber))
250             ? new SwitchingPoolLcpBuilder(splMap.get(new SwitchingPoolLcpKey(ospNumber)))
251             : new SwitchingPoolLcpBuilder().setSwitchingPoolNumber(ospNumber)
252                 .setSwitchingPoolType(osp.getSwitchingPoolType());
253         Map<NonBlockingListKey, NonBlockingList> nblMap = new HashMap<>();
254         for (Entry<Uint16, List<InstanceIdentifier<PortList>>> entry : nbliidMap.entrySet()) {
255             NonBlockingList nbl = createNonBlockingList(
256                 splBldr,
257                 osp.getNonBlockingList()
258                     .get(new org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529
259                         .org.openroadm.device.container.org.openroadm.device.odu.switching.pools
260                         .NonBlockingListKey(entry.getKey()))
261                     .getInterconnectBandwidth(),
262                 entry,
263                 portmappingNode.nonnullMapping(),
264                 nodeId);
265             if (nbl == null) {
266                 return false;
267             }
268             nblMap.put(nbl.key(), nbl);
269         }
270         SwitchingPoolLcp switchingPoolLcp = splBldr.setNonBlockingList(nblMap).build();
271         splMap.put(switchingPoolLcp.key(), switchingPoolLcp);
272         postPortMapping(nodeId, null, null, null, new ArrayList<SwitchingPoolLcp>(splMap.values()), null);
273         return true;
274     }
275
276     private NonBlockingList createNonBlockingList(SwitchingPoolLcpBuilder splBldr, Uint32 interconnectBw,
277             Entry<Uint16, List<InstanceIdentifier<PortList>>> entry, Map<MappingKey, Mapping> mappings, String nodeId) {
278         NonBlockingListBuilder nblBldr = splBldr.getNonBlockingList() == null
279             || !splBldr.getNonBlockingList().containsKey(new NonBlockingListKey(entry.getKey()))
280                 ? new NonBlockingListBuilder().setNblNumber(entry.getKey()).setInterconnectBandwidth(interconnectBw)
281                 : new NonBlockingListBuilder(splBldr.getNonBlockingList().get(new NonBlockingListKey(entry.getKey())));
282         List<String> lcpList = nblBldr.getLcpList() != null ? nblBldr.getLcpList() : new ArrayList<>();
283         for (InstanceIdentifier<PortList> id : entry.getValue()) {
284             PortList portList = deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL,
285                 id, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT).get();
286             String lcp = getLcpFromCpAndPort(mappings, portList.getCircuitPackName(), portList.getPortName());
287             if (lcp == null || lcpList.contains(lcp)) {
288                 return null;
289             }
290             lcpList.add(lcp);
291         }
292         return nblBldr.setLcpList(lcpList).build();
293     }
294
295     private boolean createXpdrPortMapping(String nodeId, List<Mapping> portMapList) {
296         // Creating for Xponder Line and Client Ports
297         OrgOpenroadmDevice device = getXpdrDevice(nodeId);
298         if (device == null) {
299             return false;
300         }
301         Map<String, String> lcpMap = new HashMap<>();
302         Map<String, Mapping> mappingMap = new HashMap<>();
303         getXpdrMaps(device, nodeId, lcpMap, mappingMap);
304         if (device.getConnectionMap() == null) {
305             LOG.warn(PortMappingUtils.NO_CONMAP_LOGMSG, nodeId);
306         } else {
307             for (ConnectionMap cm : device.nonnullConnectionMap().values()) {
308                 String skey = cm.getSource().getCircuitPackName() + "+" + cm.getSource().getPortName();
309                 Destination destination0 = cm.nonnullDestination().values().iterator().next();
310                 String dkey = destination0.getCircuitPackName() + "+" + destination0.getPortName();
311                 if (!lcpMap.containsKey(skey)) {
312                     LOG.error(PortMappingUtils.CONMAP_ISSUE_LOGMSG, nodeId, skey, dkey);
313                     continue;
314                 }
315                 String slcp = lcpMap.get(skey);
316                 Mapping mapping = mappingMap.get(slcp);
317                 mappingMap.remove(slcp);
318                 portMapList.add(createXpdrMappingObject(nodeId, null, null, null, null, mapping,
319                         //dlcp
320                         lcpMap.containsKey(dkey) ? lcpMap.get(dkey) : null,
321                         null));
322             }
323         }
324         if (device.getOduSwitchingPools() != null) {
325             postPortMapping(nodeId, null, null, null, getSwitchingPoolList(device, lcpMap, nodeId), null);
326         }
327         mappingMap.forEach((k,v) -> portMapList.add(v));
328         return true;
329     }
330
331     private OrgOpenroadmDevice getXpdrDevice(String nodeId) {
332         InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class);
333         Optional<OrgOpenroadmDevice> deviceObject = deviceTransactionManager.getDataFromDevice(nodeId,
334             LogicalDatastoreType.OPERATIONAL, deviceIID,
335             Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
336         if (deviceObject.isEmpty()) {
337             LOG.error(PortMappingUtils.CANNOT_GET_DEV_CONF_LOGMSG, nodeId);
338             return null;
339         }
340         OrgOpenroadmDevice device = deviceObject.get();
341         if (device.getCircuitPacks() == null) {
342             LOG.warn(PortMappingUtils.MISSING_CP_LOGMSG, nodeId, PortMappingUtils.FOUND);
343             return null;
344         }
345         return device;
346     }
347
348     private void getXpdrMaps(OrgOpenroadmDevice device, String nodeId,
349             Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
350         List<CircuitPacks> circuitPackList = new ArrayList<>(device.nonnullCircuitPacks().values());
351         circuitPackList.sort(Comparator.comparing(CircuitPack::getCircuitPackName));
352         if (device.getXponder() == null) {
353             LOG.warn(PortMappingUtils.XPDR_LIST_IN_CONF_LOGMSG, nodeId, "not found");
354             // Variables to keep track of number of line ports and client ports
355             int line = 1;
356             int client = 1;
357             // TODO the treatment here inside the 2 nested for-loop is very similar to the one
358             //     when device.getXponder() != null. Some code mutualization must be considered.
359             for (CircuitPacks cp : circuitPackList) {
360                 String circuitPackName = cp.getCircuitPackName();
361                 if (cp.getPorts() == null) {
362                     LOG.warn(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, PortMappingUtils.FOUND, circuitPackName);
363                     continue;
364                 }
365                 List<Ports> portList = new ArrayList<>(cp.nonnullPorts().values());
366                 portList.sort(Comparator.comparing(Ports::getPortName));
367                 for (Ports port : portList) {
368                     int[] counters = fillXpdrLcpsMaps(line, client, nodeId,
369                         1, XpdrNodeTypes.Tpdr, circuitPackName, port,
370                         circuitPackList, lcpMap, mappingMap);
371                     line = counters[0];
372                     client = counters[1];
373                 }
374             }
375         } else {
376             LOG.info(PortMappingUtils.XPDR_LIST_IN_CONF_LOGMSG, nodeId, PortMappingUtils.FOUND);
377             for (Xponder xponder : device.nonnullXponder().values()) {
378                 // Variables to keep track of number of line ports and client ports
379                 int line = 1;
380                 int client = 1;
381                 Integer xponderNb = xponder.getXpdrNumber().toJava();
382                 XpdrNodeTypes xponderType = xponder.getXpdrType();
383                 for (XpdrPort xpdrPort : xponder.nonnullXpdrPort().values().stream()
384                         .sorted((xp1, xp2) -> xp1.getIndex().compareTo(xp2.getIndex())).collect(Collectors.toList())) {
385                     Ports port = getXpdrPorts(device, xpdrPort, nodeId);
386                     if (port == null) {
387                         continue;
388                     }
389                     int[] counters = fillXpdrLcpsMaps(line, client, nodeId,
390                         xponderNb, xponderType, xpdrPort.getCircuitPackName(), port,
391                         circuitPackList, lcpMap, mappingMap);
392                     line = counters[0];
393                     client = counters[1];
394                 }
395             }
396         }
397     }
398
399     private Ports getXpdrPorts(OrgOpenroadmDevice device, XpdrPort xpdrPort, String nodeId) {
400         String circuitPackName = xpdrPort.getCircuitPackName();
401         String portName = xpdrPort.getPortName();
402         // If there xponder-subtree has missing circuit-packs or ports,
403         // This gives a null-pointer expection,
404         Optional<CircuitPacks> cpList = device.nonnullCircuitPacks().values().stream()
405                 .filter(cp -> cp.getCircuitPackName().equals(circuitPackName)).findFirst();
406         if (cpList.isEmpty()) {
407             LOG.warn(PortMappingUtils.MISSING_CP_LOGMSG + PortMappingUtils.PORTMAPPING_IGNORE_LOGMSG,
408                 nodeId, circuitPackName);
409             return null;
410         }
411         Optional<Ports> portsList = cpList.get().nonnullPorts().values().stream()
412                 .filter(p -> p.getPortName().equals(portName)).findFirst();
413         if (portsList.isEmpty()) {
414             LOG.warn(PortMappingUtils.NO_ASSOC_FOUND_LOGMSG + PortMappingUtils.PORTMAPPING_IGNORE_LOGMSG,
415                 nodeId, portName, circuitPackName, "in the device");
416             return null;
417         }
418         return portsList.get();
419     }
420
421     private List<SwitchingPoolLcp> getSwitchingPoolList(OrgOpenroadmDevice device,
422             Map<String, String> lcpMap, String nodeId) {
423         List<SwitchingPoolLcp> switchingPoolList = new ArrayList<>();
424         for (OduSwitchingPools odp : device.nonnullOduSwitchingPools().values()) {
425             Map<NonBlockingListKey,NonBlockingList> nbMap = new HashMap<>();
426             for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.org.openroadm.device.container.org
427                 .openroadm.device.odu.switching.pools.NonBlockingList nbl : odp.nonnullNonBlockingList().values()) {
428                 if (nbl.getPortList() == null) {
429                     continue;
430                 }
431                 List<String> lcpList = new ArrayList<>();
432                 for (PortList item : nbl.nonnullPortList().values()) {
433                     String key = item.getCircuitPackName() + "+" + item.getPortName();
434                     if (!lcpMap.containsKey(key)) {
435                         LOG.error(PortMappingUtils.NO_ASSOC_FOUND_LOGMSG,
436                             nodeId, item.getPortName(), item.getCircuitPackName(), "to a logical connection point");
437                         continue;
438                     }
439                     lcpList.add(lcpMap.get(key));
440                 }
441                 NonBlockingList nonBlockingList = new NonBlockingListBuilder()
442                     .setNblNumber(nbl.getNblNumber())
443                     .setInterconnectBandwidth(nbl.getInterconnectBandwidth())
444                     .setInterconnectBandwidthUnit(nbl.getInterconnectBandwidthUnit())
445                     .setLcpList(lcpList)
446                     .build();
447                 nbMap.put(nonBlockingList.key(), nonBlockingList);
448             }
449             switchingPoolList.add(
450                 new SwitchingPoolLcpBuilder()
451                     .setSwitchingPoolNumber(odp.getSwitchingPoolNumber())
452                     .setSwitchingPoolType(odp.getSwitchingPoolType())
453                     //TODO differs from 2.2.1 SwitchingPoolTypes.forValue(odp.getSwitchingPoolType().getIntValue())
454                     .setNonBlockingList(nbMap)
455                     .build());
456         }
457         return switchingPoolList;
458     }
459
460     private boolean checkPartnerPortNotNull(Ports port) {
461         return (port.getPartnerPort() != null
462             && port.getPartnerPort().getCircuitPackName() != null
463             && port.getPartnerPort().getPortName() != null);
464     }
465
466     private boolean checkPartnerPortNoDir(String circuitPackName, Ports port1, Ports port2) {
467         return (checkPartnerPortNotNull(port2)
468             && port2.getPartnerPort().getCircuitPackName().equals(circuitPackName)
469             && port2.getPartnerPort().getPortName().equals(port1.getPortName()));
470     }
471
472     private boolean checkPartnerPort(String circuitPackName, Ports port1, Ports port2) {
473         return checkPartnerPortNoDir(circuitPackName, port1, port2)
474             && Set.of(port1.getPortDirection().getIntValue(), port2.getPortDirection().getIntValue())
475                 .equals(TXRX_SET);
476     }
477
478
479     private HashMap<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.srg
480             .CircuitPacks>> getSrgCps(String deviceId, Info ordmInfo) {
481         HashMap<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.srg
482             .CircuitPacks>> cpPerSrg = new HashMap<>();
483         // Get value for max Srg from info subtree, required for iteration
484         // if not present assume to be 20 (temporary)
485         Integer maxSrg = ordmInfo.getMaxSrgs() == null ? 20 : ordmInfo.getMaxSrgs().toJava();
486         for (int srgCounter = 1; srgCounter <= maxSrg; srgCounter++) {
487             List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.srg.CircuitPacks> srgCps
488                 = new ArrayList<>();
489             LOG.debug(PortMappingUtils.GETTING_CP_LOGMSG, deviceId, srgCounter);
490             InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
491                 .child(SharedRiskGroup.class, new SharedRiskGroupKey(Uint16.valueOf(srgCounter)));
492             Optional<SharedRiskGroup> ordmSrgObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
493                 LogicalDatastoreType.OPERATIONAL, srgIID,
494                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
495             if (ordmSrgObject.isPresent()) {
496                 srgCps.addAll(ordmSrgObject.get().nonnullCircuitPacks().values());
497                 cpPerSrg.put(ordmSrgObject.get().getSrgNumber().toJava(), srgCps);
498             }
499         }
500         LOG.info(PortMappingUtils.DEVICE_HAS_LOGMSG, deviceId, cpPerSrg.size(), "SRG");
501         return cpPerSrg;
502     }
503
504     private boolean createPpPortMapping(String nodeId, Info deviceInfo, List<Mapping> portMapList) {
505         // Creating mapping data for SRG's PP
506         for (Entry<Integer, List<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.srg.CircuitPacks>>
507                 srgCpEntry : getSrgCps(nodeId, deviceInfo).entrySet()) {
508             List<String> keys = new ArrayList<>();
509             for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.srg.CircuitPacks
510                     cp : srgCpEntry.getValue()) {
511                 String circuitPackName = cp.getCircuitPackName();
512                 List<Ports> portList = getPortList(circuitPackName, nodeId);
513                 Collections.sort(portList, new SortPort710ByName());
514                 int portIndex = 1;
515                 for (Ports port : portList) {
516                     if (!checkPortQual(port, circuitPackName, nodeId)) {
517                         continue;
518                     }
519                     String currentKey = circuitPackName + "-" + port.getPortName();
520                     if (keys.contains(currentKey)) {
521                         LOG.debug(PortMappingUtils.PORT_ALREADY_HANDLED_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
522                             nodeId, port.getPortName(), circuitPackName);
523                         continue;
524                     }
525                     switch (port.getPortDirection()) {
526                         case Bidirectional:
527                             String lcp = createLogicalConnectionPort(port, srgCpEntry.getKey(), portIndex);
528                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
529                                 nodeId, port.getPortName(), circuitPackName, lcp);
530                             portMapList.add(createMappingObject(nodeId, port, circuitPackName, lcp));
531                             portIndex++;
532                             keys.add(currentKey);
533                             break;
534                         case Rx:
535                         case Tx:
536                             Ports port2 = getPartnerPort(port, circuitPackName, nodeId);
537                             if (port2 == null) {
538                                 continue;
539                             }
540                             String lcp1 = createLogicalConnectionPort(port, srgCpEntry.getKey(), portIndex);
541                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
542                                 nodeId, port.getPortName(), circuitPackName, lcp1);
543                             String lcp2 = createLogicalConnectionPort(port2, srgCpEntry.getKey(),portIndex);
544                             LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
545                                 nodeId, port2.getPortName(), circuitPackName, lcp2);
546                             portMapList.add(createMappingObject(nodeId, port, circuitPackName, lcp1));
547                             portMapList.add(
548                                 createMappingObject(nodeId ,port2, port.getPartnerPort().getCircuitPackName(), lcp2));
549                             portIndex++;
550                             keys.add(currentKey);
551                             keys.add(port.getPartnerPort().getCircuitPackName() + "-" + port2.getPortName());
552                             break;
553                         default:
554                             LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
555                                     nodeId, port.getPortName(), circuitPackName, port.getPortDirection());
556                     }
557                 }
558             }
559         }
560         return true;
561     }
562
563     private Ports getPartnerPort(Ports port, String circuitPackName, String nodeId) {
564         if (!checkPartnerPortNotNull(port)) {
565             LOG.info(PortMappingUtils.NO_VALID_PARTNERPORT_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
566                 nodeId, port.getPortName(), circuitPackName);
567             return null;
568         }
569         InstanceIdentifier<Ports> port2ID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
570             .child(CircuitPacks.class, new CircuitPacksKey(port.getPartnerPort().getCircuitPackName()))
571             .child(Ports.class, new PortsKey(port.getPartnerPort().getPortName()));
572         Optional<Ports> port2Object = this.deviceTransactionManager
573             .getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, port2ID,
574                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
575         if (port2Object.isEmpty()
576                 || port2Object.get().getPortQual().getIntValue() != PortQual.RoadmExternal.getIntValue()) {
577             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG + PortMappingUtils.PARTNERPORT_GET_ERROR_LOGMSG,
578                 nodeId, port.getPartnerPort().getPortName(), port.getPartnerPort().getCircuitPackName(),
579                 port.getPortName(), circuitPackName);
580             return null;
581         }
582         Ports port2 = port2Object.get();
583         if (!checkPartnerPort(circuitPackName, port, port2)) {
584             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG + PortMappingUtils.PARTNERPORT_CONF_ERROR_LOGMSG,
585                 nodeId, port2.getPortName(), port.getPartnerPort().getCircuitPackName(),
586                 port.getPortName(), circuitPackName);
587             //TODO check if we really needed to increment portIndex in this condition
588             //     if yes this block should not be in getPartnerPort and must move back to createPpPortMapping
589             return null;
590         }
591         return port2;
592     }
593
594     private List<Ports> getPortList(String circuitPackName, String nodeId) {
595         InstanceIdentifier<CircuitPacks> cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
596             .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName));
597         Optional<CircuitPacks> circuitPackObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
598              LogicalDatastoreType.OPERATIONAL, cpIID,
599              Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
600         if (circuitPackObject.isEmpty()) {
601             LOG.warn(PortMappingUtils.MISSING_CP_LOGMSG + PortMappingUtils.PORTMAPPING_IGNORE_LOGMSG,
602                 nodeId, circuitPackName);
603             return new ArrayList<>();
604         }
605         if (circuitPackObject.get().getPorts() == null) {
606             LOG.warn(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, PortMappingUtils.FOUND, circuitPackName);
607             return new ArrayList<>();
608         }
609         return new ArrayList<>(circuitPackObject.get().nonnullPorts().values());
610     }
611
612     private String createLogicalConnectionPort(Ports port, int index, int portIndex) {
613         if (SUFFIX.containsKey(port.getPortDirection())) {
614             return String.join("-", "SRG" + index, "PP" + portIndex, SUFFIX.get(port.getPortDirection()));
615         }
616         LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG,
617             "createLogicalConnectionPort", port, "SRG" + index + "-PP" + portIndex, port.getPortDirection());
618         return null;
619     }
620
621     private Map<McCapabilityProfileKey, McCapabilityProfile> getMcCapabilityProfiles(String deviceId, Info ordmInfo) {
622         Map<McCapabilityProfileKey, McCapabilityProfile>  mcCapabilityProfiles = new HashMap<>();
623         InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class);
624         Optional<OrgOpenroadmDevice> deviceObject = deviceTransactionManager.getDataFromDevice(deviceId,
625             LogicalDatastoreType.OPERATIONAL, deviceIID,
626             Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
627         OrgOpenroadmDevice device = null;
628         if (deviceObject.isEmpty()) {
629             LOG.error(PortMappingUtils.CANNOT_GET_DEV_CONF_LOGMSG, deviceId);
630             LOG.warn("MC-capabilities profile will be empty for node {}", deviceId);
631             return mcCapabilityProfiles;
632         }
633         device = deviceObject.get();
634         mcCapabilityProfiles = device.getMcCapabilityProfile();
635         return mcCapabilityProfiles;
636     }
637
638     private Map<Integer, Degree> getDegreesMap(String deviceId, Info ordmInfo) {
639         Map<Integer, Degree> degrees = new HashMap<>();
640
641         // Get value for max degree from info subtree, required for iteration
642         // if not present assume to be 20 (temporary)
643         Integer maxDegree = ordmInfo.getMaxDegrees() == null ? 20 : ordmInfo.getMaxDegrees().toJava();
644
645         for (int degreeCounter = 1; degreeCounter <= maxDegree; degreeCounter++) {
646             LOG.debug(PortMappingUtils.GETTING_CONPORT_LOGMSG, deviceId, degreeCounter);
647             InstanceIdentifier<Degree> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
648                 .child(Degree.class, new DegreeKey(Uint16.valueOf(degreeCounter)));
649             Optional<Degree> ordmDegreeObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
650                 LogicalDatastoreType.OPERATIONAL, deviceIID,
651                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
652             if (ordmDegreeObject.isPresent()) {
653                 degrees.put(degreeCounter, ordmDegreeObject.get());
654             }
655         }
656         LOG.info(PortMappingUtils.DEVICE_HAS_LOGMSG,
657             deviceId, degrees.size(), degrees.size() <= 1 ? "degree" : "degrees");
658         return degrees;
659     }
660
661     private Map<Integer, List<ConnectionPorts>> getPerDegreePorts(String deviceId, Info ordmInfo) {
662         Map<Integer, List<ConnectionPorts>> conPortMap = new HashMap<>();
663         getDegreesMap(deviceId, ordmInfo).forEach(
664             (index, degree) -> conPortMap.put(index, new ArrayList<>(degree.nonnullConnectionPorts().values())));
665         return conPortMap;
666     }
667
668     private List<SharedRiskGroup> getSrgs(String deviceId, Info ordmInfo) {
669         List<SharedRiskGroup> srgs = new ArrayList<>();
670
671         // Get value for max Srg from info subtree, required for iteration
672         // if not present assume to be 20 (temporary)
673         Integer maxSrg = ordmInfo.getMaxSrgs() == null ? 20 : ordmInfo.getMaxSrgs().toJava();
674         for (int srgCounter = 1; srgCounter <= maxSrg; srgCounter++) {
675             InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
676                 .child(SharedRiskGroup.class, new SharedRiskGroupKey(Uint16.valueOf(srgCounter)));
677             Optional<SharedRiskGroup> ordmSrgObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
678                 LogicalDatastoreType.OPERATIONAL, srgIID,
679                 Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
680             if (ordmSrgObject.isPresent()) {
681                 srgs.add(ordmSrgObject.get());
682
683             }
684         }
685         return srgs;
686     }
687
688     private Map<String, String> getEthInterfaceList(String nodeId) {
689         LOG.info(PortMappingUtils.GETTING_ETH_LIST_LOGMSG, nodeId);
690         InstanceIdentifier<Protocols> protocoliid = InstanceIdentifier.create(OrgOpenroadmDevice.class)
691             .child(Protocols.class);
692         Optional<Protocols> protocolObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
693             LogicalDatastoreType.OPERATIONAL, protocoliid, Timeouts.DEVICE_READ_TIMEOUT,
694             Timeouts.DEVICE_READ_TIMEOUT_UNIT);
695         if (protocolObject.isEmpty() || protocolObject.get().augmentation(Protocols1.class).getLldp() == null) {
696             LOG.warn(PortMappingUtils.PROCESSING_DONE_LOGMSG, nodeId, PortMappingUtils.CANNOT_GET_LLDP_CONF_LOGMSG);
697             return new HashMap<>();
698         }
699         Map<String, String> cpToInterfaceMap = new HashMap<>();
700         Lldp lldp = protocolObject.get().augmentation(Protocols1.class).getLldp();
701         for (PortConfig portConfig : lldp.nonnullPortConfig().values()) {
702             if (!portConfig.getAdminStatus().equals(PortConfig.AdminStatus.Txandrx)) {
703                 continue;
704             }
705             InstanceIdentifier<Interface> interfaceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
706                 .child(Interface.class, new InterfaceKey(portConfig.getIfName()));
707             Optional<Interface> interfaceObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
708                 LogicalDatastoreType.OPERATIONAL, interfaceIID, Timeouts.DEVICE_READ_TIMEOUT,
709                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
710             if (interfaceObject.isEmpty() || interfaceObject.get().getSupportingCircuitPackName() == null) {
711                 continue;
712             }
713             String supportingCircuitPackName = interfaceObject.get().getSupportingCircuitPackName();
714             cpToInterfaceMap.put(supportingCircuitPackName, portConfig.getIfName());
715             InstanceIdentifier<CircuitPacks> circuitPacksIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
716                 .child(CircuitPacks.class, new CircuitPacksKey(supportingCircuitPackName));
717             Optional<CircuitPacks> circuitPackObject = this.deviceTransactionManager.getDataFromDevice(
718                 nodeId, LogicalDatastoreType.OPERATIONAL, circuitPacksIID, Timeouts.DEVICE_READ_TIMEOUT,
719                 Timeouts.DEVICE_READ_TIMEOUT_UNIT);
720             if (circuitPackObject.isEmpty() || circuitPackObject.get().getParentCircuitPack() == null) {
721                 continue;
722             }
723             cpToInterfaceMap.put(circuitPackObject.get().getParentCircuitPack().getCircuitPackName(),
724                 portConfig.getIfName());
725         }
726         LOG.info(PortMappingUtils.PROCESSING_DONE_LOGMSG, nodeId, " - success");
727         return cpToInterfaceMap;
728     }
729
730     private List<CpToDegree> getCpToDegreeList(Map<Integer, Degree> degrees, Map<String, String> interfaceList) {
731         List<CpToDegree> cpToDegreeList = new ArrayList<>();
732         for (Degree degree : degrees.values()) {
733             cpToDegreeList.addAll(degree.nonnullCircuitPacks().values().stream()
734                 .map(cp -> createCpToDegreeObject(cp.getCircuitPackName(),
735                     degree.getDegreeNumber().toString(), interfaceList))
736                 .collect(Collectors.toList()));
737         }
738         return cpToDegreeList;
739     }
740
741     private Map<McCapabilitiesKey, McCapabilities> getMcCapabilities(Map<Integer, Degree> degrees,
742             List<SharedRiskGroup> srgs, Info deviceInfo, String nodeId) {
743         //TODO some divergences with 2.2.1 here
744         LOG.info(PortMappingUtils.GETTING_MC_CAPA_LOGMSG , nodeId, "degrees");
745         //Get all the mc-capability profiles from the device
746         Map<McCapabilityProfileKey, McCapabilityProfile> mcCapabilityProfiles =
747             getMcCapabilityProfiles(nodeId, deviceInfo);
748         // Add the DEG mc-capabilities
749         Map<McCapabilitiesKey, McCapabilities> mcCapabilities = createMcCapDegreeObject(degrees, mcCapabilityProfiles,
750             nodeId);
751         // Add the SRG mc-capabilities
752         LOG.info(PortMappingUtils.GETTING_MC_CAPA_LOGMSG , nodeId, "SRGs");
753         mcCapabilities.putAll(createMcCapSrgObject(srgs, mcCapabilityProfiles, nodeId));
754         return mcCapabilities;
755     }
756
757     private boolean postPortMapping(String nodeId, NodeInfo nodeInfo, List<Mapping> portMapList,
758             List<CpToDegree> cp2DegreeList, List<SwitchingPoolLcp> splList,
759             Map<McCapabilitiesKey, McCapabilities> mcCapMap) {
760         NodesBuilder nodesBldr = new NodesBuilder().withKey(new NodesKey(nodeId)).setNodeId(nodeId);
761         if (nodeInfo != null) {
762             nodesBldr.setNodeInfo(nodeInfo);
763         }
764         if (portMapList != null) {
765             Map<MappingKey, Mapping> mappingMap = new HashMap<>();
766             // No element in the list below should be null at this stage
767             for (Mapping mapping: portMapList) {
768                 mappingMap.put(mapping.key(), mapping);
769             }
770             nodesBldr.setMapping(mappingMap);
771         }
772         if (cp2DegreeList != null) {
773             Map<CpToDegreeKey, CpToDegree> cpToDegreeMap = new HashMap<>();
774             // No element in the list below should be null at this stage
775             for (CpToDegree cp2Degree: cp2DegreeList) {
776                 cpToDegreeMap.put(cp2Degree.key(), cp2Degree);
777             }
778             nodesBldr.setCpToDegree(cpToDegreeMap);
779         }
780
781         if (splList != null) {
782             Map<SwitchingPoolLcpKey,SwitchingPoolLcp> splMap = new HashMap<>();
783             // No element in the list below should be null at this stage
784             for (SwitchingPoolLcp spl: splList) {
785                 splMap.put(spl.key(), spl);
786             }
787             nodesBldr.setSwitchingPoolLcp(splMap);
788         }
789         if (mcCapMap != null) {
790             nodesBldr.setMcCapabilities(mcCapMap);
791         }
792         Map<NodesKey,Nodes> nodesList = new HashMap<>();
793         Nodes nodes = nodesBldr.build();
794         nodesList.put(nodes.key(),nodes);
795
796         Network network = new NetworkBuilder().setNodes(nodesList).build();
797
798         final WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
799         InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
800         writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, network);
801         FluentFuture<? extends @NonNull CommitInfo> commit = writeTransaction.commit();
802         try {
803             commit.get();
804             return true;
805         } catch (InterruptedException | ExecutionException e) {
806             LOG.warn(PortMappingUtils.PORTMAPPING_POST_FAIL_LOGMSG, nodeId, network, e);
807             return false;
808         }
809     }
810
811     private CpToDegree createCpToDegreeObject(String circuitPackName, String degreeNumber,
812             Map<String, String> interfaceList) {
813         return new CpToDegreeBuilder()
814             .withKey(new CpToDegreeKey(circuitPackName))
815             .setCircuitPackName(circuitPackName)
816             .setDegreeNumber(Uint32.valueOf(degreeNumber))
817             .setInterfaceName(interfaceList.get(circuitPackName)).build();
818     }
819
820     private Map<McCapabilitiesKey, McCapabilities> createMcCapDegreeObject(Map<Integer, Degree> degrees,
821             Map<McCapabilityProfileKey, McCapabilityProfile> mcCapabilityProfileMap, String nodeId) {
822         //TODO some divergences here with 2.2.1
823         Map<McCapabilitiesKey, McCapabilities> mcCapabilitiesMap = new HashMap<>();
824         for (Degree degree : degrees.values()) {
825
826             if ((degree.getMcCapabilityProfileName() == null) || (degree.getMcCapabilityProfileName().isEmpty())) {
827                 String mcNodeName =
828                     PortMappingUtils.degreeTtpNodeName(degree.getDegreeNumber().toString(), "default-profile");
829                 LOG.warn(PortMappingUtils.NO_MC_LOGMSG, nodeId, "degree",
830                     degree.getDegreeNumber() +  " - using " + mcNodeName + " as default MC profile name");
831                 McCapabilitiesBuilder mcCapabilitiesBuilder = new McCapabilitiesBuilder()
832                     .withKey(new McCapabilitiesKey(mcNodeName))
833                     .setMcNodeName(mcNodeName);
834                 mcCapabilitiesBuilder
835                     .setCenterFreqGranularity(FrequencyGHz.getDefaultInstance("50"))
836                     .setSlotWidthGranularity(FrequencyGHz.getDefaultInstance("50"));
837                 mcCapabilitiesMap.put(mcCapabilitiesBuilder.key(), mcCapabilitiesBuilder.build());
838                 continue;
839             }
840
841             for (String mcCapabilityProfileName : degree.getMcCapabilityProfileName()) {
842                 McCapabilityProfileKey mcKey = new McCapabilityProfileKey(mcCapabilityProfileName);
843                 McCapabilityProfile mcCapabilityProfile = mcCapabilityProfileMap.get(mcKey);
844                 String mcNodeName = PortMappingUtils.degreeTtpNodeName(degree.getDegreeNumber().toString(),
845                         mcCapabilityProfile.toString());
846                 McCapabilitiesBuilder mcCapabilitiesBuilder = new McCapabilitiesBuilder()
847                     .withKey(new McCapabilitiesKey(mcNodeName))
848                     .setMcNodeName(mcNodeName);
849                 mcCapabilitiesBuilder
850                     .setCenterFreqGranularity(mcCapabilityProfile.getCenterFreqGranularity())
851                     .setSlotWidthGranularity(mcCapabilityProfile.getSlotWidthGranularity());
852                 mcCapabilitiesMap.put(mcCapabilitiesBuilder.key(), mcCapabilitiesBuilder.build());
853             }
854
855         }
856         return mcCapabilitiesMap;
857     }
858
859     private Map<McCapabilitiesKey, McCapabilities> createMcCapSrgObject(List<SharedRiskGroup> srgs,
860             Map<McCapabilityProfileKey, McCapabilityProfile> mcCapabilityProfileMap, String nodeId) {
861
862         Map<McCapabilitiesKey, McCapabilities> mcCapabilitiesMap = new HashMap<>();
863         for (SharedRiskGroup srg : srgs) {
864
865             if ((srg.getMcCapabilityProfileName() == null) || (srg.getMcCapabilityProfileName().isEmpty())) {
866                 String mcNodeName = "SRG" + srg.getSrgNumber().toString() + "-PP-" + "default-profile";
867                 LOG.warn(PortMappingUtils.NO_MC_LOGMSG, nodeId, "SRG",
868                     srg.getSrgNumber() + " - using " + mcNodeName + " as default MC profile name");
869                 McCapabilitiesBuilder mcCapabilitiesBuilder = new McCapabilitiesBuilder()
870                     .withKey(new McCapabilitiesKey(mcNodeName))
871                     .setMcNodeName(mcNodeName);
872                 mcCapabilitiesBuilder
873                     .setCenterFreqGranularity(FrequencyGHz.getDefaultInstance("50"))
874                     .setSlotWidthGranularity(FrequencyGHz.getDefaultInstance("50"));
875                 mcCapabilitiesMap.put(mcCapabilitiesBuilder.key(), mcCapabilitiesBuilder.build());
876                 continue;
877             }
878
879             for (String mcCapabilityProfileName : srg.getMcCapabilityProfileName()) {
880                 McCapabilityProfileKey mcKey = new McCapabilityProfileKey(mcCapabilityProfileName);
881                 McCapabilityProfile mcCapabilityProfile = mcCapabilityProfileMap.get(mcKey);
882                 String mcNodeName = "SRG" + srg.getSrgNumber().toString() + "-PP-" + mcCapabilityProfile;
883                 McCapabilitiesBuilder mcCapabilitiesBuilder = new McCapabilitiesBuilder()
884                     .withKey(new McCapabilitiesKey(mcNodeName))
885                     .setMcNodeName(mcNodeName);
886                 mcCapabilitiesBuilder
887                     .setCenterFreqGranularity(mcCapabilityProfile.getCenterFreqGranularity())
888                     .setSlotWidthGranularity(mcCapabilityProfile.getSlotWidthGranularity());
889                 mcCapabilitiesMap.put(mcCapabilitiesBuilder.key(), mcCapabilitiesBuilder.build());
890             }
891         }
892         return mcCapabilitiesMap;
893     }
894
895     private Mapping createMappingObject(String nodeId, Ports port, String circuitPackName,
896             String logicalConnectionPoint) {
897         MappingBuilder mpBldr = new MappingBuilder()
898                 .withKey(new MappingKey(logicalConnectionPoint))
899                 .setLogicalConnectionPoint(logicalConnectionPoint)
900                 .setSupportingCircuitPackName(circuitPackName)
901                 .setSupportingPort(port.getPortName())
902                 .setPortDirection(port.getPortDirection().getName());
903         if (port.getAdministrativeState() != null) {
904             mpBldr.setPortAdminState(port.getAdministrativeState().name());
905         }
906         if (port.getOperationalState() != null) {
907             mpBldr.setPortOperState(port.getOperationalState().name());
908         }
909
910         if ((port.getInterfaces() == null)
911             || (!logicalConnectionPoint.contains(StringConstants.TTP_TOKEN)
912                 && !logicalConnectionPoint.contains(StringConstants.NETWORK_TOKEN))) {
913             return mpBldr.build();
914         }
915         mpBldr = updateMappingInterfaces(nodeId, mpBldr, port);
916         return mpBldr.build();
917     }
918
919     private Mapping updateMappingObject(String nodeId, Ports port, Mapping oldmapping) {
920         MappingBuilder mpBldr = new MappingBuilder(oldmapping);
921         updateMappingStates(mpBldr, port, oldmapping);
922         if ((port.getInterfaces() == null)
923             || (!oldmapping.getLogicalConnectionPoint().contains(StringConstants.TTP_TOKEN)
924                 && !oldmapping.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN))) {
925             return mpBldr.build();
926         }
927         // Get interfaces provisioned on the port
928         mpBldr = updateMappingInterfaces(nodeId, mpBldr, port);
929         return mpBldr.build();
930     }
931
932     private MappingBuilder updateMappingStates(MappingBuilder mpBldr, Ports port, Mapping oldmapping) {
933         if (port.getAdministrativeState() != null
934             && !port.getAdministrativeState().getName().equals(oldmapping.getPortAdminState())) {
935             mpBldr.setPortAdminState(port.getAdministrativeState().name());
936         }
937         if (port.getOperationalState() != null
938             && !port.getOperationalState().getName().equals(oldmapping.getPortOperState())) {
939             mpBldr.setPortOperState(port.getOperationalState().name());
940         }
941         return mpBldr;
942     }
943
944     private MappingBuilder updateMappingInterfaces(String nodeId, MappingBuilder mpBldr, Ports port) {
945         for (Interfaces interfaces : port.getInterfaces()) {
946             Optional<Interface> openRoadmInterface = getInterfaceFromDevice(nodeId,
947                 interfaces.getInterfaceName());
948             if (openRoadmInterface.isEmpty()) {
949                 LOG.warn(PortMappingUtils.INTF_ISSUE_LOGMSG,
950                     nodeId, interfaces.getInterfaceName() + "- empty interface");
951                 continue;
952             }
953             LOG.debug(PortMappingUtils.GOT_INTF_LOGMSG,
954                 nodeId, openRoadmInterface.get().getName(), openRoadmInterface.get().getType());
955             Class<? extends InterfaceType> interfaceType
956                 = (Class<? extends InterfaceType>) openRoadmInterface.get().getType();
957             // Check if interface type is OMS or OTS
958             if (interfaceType.equals(OpenROADMOpticalMultiplex.class)) {
959                 mpBldr.setSupportingOms(interfaces.getInterfaceName());
960             }
961             if (interfaceType.equals(OpticalTransport.class)) {
962                 mpBldr.setSupportingOts(interfaces.getInterfaceName());
963             }
964             String interfaceName = interfaces.getInterfaceName();
965             if (interfaceType.equals(OtnOdu.class)
966                 && (interfaceName.substring(interfaceName.lastIndexOf("-") + 1)
967                 .equals("ODU"))) {
968                 mpBldr.setSupportingOdu4(interfaces.getInterfaceName());
969             }
970             if ((interfaceType.equals(OtnOdu.class))
971                 && (interfaceName.substring(interfaceName.lastIndexOf("-") + 1)
972                 .equals("ODUC4"))) {
973                 mpBldr.setSupportingOduc4(interfaces.getInterfaceName());
974             }
975         }
976         return mpBldr;
977     }
978
979     private Mapping createXpdrMappingObject(String nodeId, Ports port, String circuitPackName,
980             String logicalConnectionPoint, String partnerLcp, Mapping mapping, String connectionMapLcp,
981             XpdrNodeTypes xpdrNodeType) {
982
983         //TODO some divergens here with 2.2.1
984         if (mapping != null && connectionMapLcp != null) {
985             // update existing mapping
986             return new MappingBuilder(mapping).setConnectionMapLcp(connectionMapLcp).build();
987         }
988         return createNewXpdrMapping(nodeId, port, circuitPackName, logicalConnectionPoint, partnerLcp, xpdrNodeType);
989     }
990
991     private Mapping createNewXpdrMapping(String nodeId, Ports port, String circuitPackName,
992             String logicalConnectionPoint, String partnerLcp, XpdrNodeTypes xpdrNodeType) {
993         MappingBuilder mpBldr = new MappingBuilder()
994                 .withKey(new MappingKey(logicalConnectionPoint))
995                 .setLogicalConnectionPoint(logicalConnectionPoint)
996                 .setSupportingCircuitPackName(circuitPackName)
997                 .setSupportingPort(port.getPortName())
998                 .setPortDirection(port.getPortDirection().getName())
999                 .setLcpHashVal(PortMappingUtils.fnv1size64(nodeId + "-" + logicalConnectionPoint));
1000         if (port.getPortQual() != null) {
1001             mpBldr.setPortQual(port.getPortQual().getName());
1002         }
1003         if (xpdrNodeType != null) {
1004             mpBldr.setXponderType(xpdrNodeType);
1005         }
1006         if (partnerLcp != null) {
1007             mpBldr.setPartnerLcp(partnerLcp);
1008         }
1009         Collection<SupportedInterfaceCapability> supIntfCapaList = getSupIntfCapaList(port);
1010         if (supIntfCapaList != null) {
1011             List<Class<? extends org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev200327
1012                 .SupportedIfCapability>> supportedIntf = new ArrayList<>();
1013             SupportedInterfaceCapability sic1 = null;
1014             for (SupportedInterfaceCapability sic : supIntfCapaList) {
1015                 supportedIntf.add(sic.getIfCapType());
1016                 sic1 = sic;
1017             }
1018             mpBldr.setSupportedInterfaceCapability(supportedIntf);
1019             if (port.getPortQual() == PortQual.SwitchClient
1020                 && !sic1.getOtnCapability().getMpdrClientRestriction().isEmpty()) {
1021                 // Here we assume all the supported-interfaces has the support same rates, and the
1022                 // trib-slot numbers are assumed to be the same
1023                 String mxpProfileName =
1024                     sic1.getOtnCapability().getMpdrClientRestriction().get(0).getMuxpProfileName().get(0);
1025                 // From this muxponder-profile get the min-trib-slot and the max-trib-slot
1026                 LOG.info("{}: Muxp-profile used for trib information {}", nodeId, mxpProfileName);
1027                 // This provides the tribSlot information from muxProfile
1028                 List<OpucnTribSlotDef> minMaxOpucnTribSlots = getOpucnTribSlots(nodeId, mxpProfileName);
1029                 mpBldr.setMpdrRestrictions(
1030                     new MpdrRestrictionsBuilder()
1031                         .setMinTribSlot(minMaxOpucnTribSlots.get(0))
1032                         .setMaxTribSlot(minMaxOpucnTribSlots.get(1))
1033                         .build());
1034             }
1035         }
1036         if (port.getAdministrativeState() != null) {
1037             mpBldr.setPortAdminState(port.getAdministrativeState().name());
1038         }
1039         if (port.getOperationalState() != null) {
1040             mpBldr.setPortOperState(port.getOperationalState().name());
1041         }
1042         return mpBldr.build();
1043     }
1044
1045     private Collection<SupportedInterfaceCapability> getSupIntfCapaList(Ports port) {
1046         return
1047             port.augmentation(Ports1.class) == null || port.augmentation(Ports1.class).getPortCapabilities() == null
1048                 ? null
1049                 : port.augmentation(Ports1.class).getPortCapabilities().nonnullSupportedInterfaceCapability().values();
1050     }
1051
1052     private ArrayList<OpucnTribSlotDef> getOpucnTribSlots(String deviceId, String mxpProfileName) {
1053         ArrayList<OpucnTribSlotDef> minMaxOpucnTribSlots = new ArrayList<>(2);
1054
1055         LOG.info("{} : Getting Min/Max Trib-slots from {}", deviceId, mxpProfileName);
1056         InstanceIdentifier<MuxpProfile> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
1057             .child(MuxpProfile.class, new MuxpProfileKey(mxpProfileName));
1058
1059         Optional<MuxpProfile> muxpProfileObject = this.deviceTransactionManager.getDataFromDevice(deviceId,
1060             LogicalDatastoreType.OPERATIONAL, deviceIID,
1061             Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
1062
1063         List<OpucnTribSlotDef> ntwHoOduOpucnTribSlots = muxpProfileObject.get().getNetworkHoOduOpucnTribSlots();
1064         // Sort the tib-slots in ascending order and pick min and max
1065         List<OpucnTribSlotDef> sortedNtwHoOduOpucnTribSlots = ntwHoOduOpucnTribSlots.stream().sorted(
1066             Comparator.comparingDouble(x -> Double.parseDouble(
1067                 x.getValue().substring(x.getValue().lastIndexOf('.') + 1))))
1068             .collect(Collectors.toList());
1069         minMaxOpucnTribSlots.add(sortedNtwHoOduOpucnTribSlots.get(0));
1070         minMaxOpucnTribSlots.add(sortedNtwHoOduOpucnTribSlots.get(sortedNtwHoOduOpucnTribSlots.size() - 1));
1071         LOG.debug("Min, Max trib slot list {}", minMaxOpucnTribSlots);
1072         return minMaxOpucnTribSlots;
1073     }
1074
1075     private Ports getPort2(Ports port, String nodeId, String circuitPackName, StringBuilder circuitPackName2,
1076             //circuitPackName2 will be updated by reference contrary to circuitPackName
1077             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap) {
1078         if (!checkPartnerPortNotNull(port)) {
1079             LOG.warn(PortMappingUtils.NO_VALID_PARTNERPORT_LOGMSG, nodeId, port.getPortName(), circuitPackName);
1080             return null;
1081         }
1082         if (lcpMap.containsKey(circuitPackName + '+' + port.getPortName())) {
1083             return null;
1084         }
1085         Optional<CircuitPacks> cpOpt = circuitPackList.stream()
1086             .filter(
1087                 cP -> cP.getCircuitPackName().equals(port.getPartnerPort().getCircuitPackName()))
1088             .findFirst();
1089         if (cpOpt.isEmpty()) {
1090             LOG.error(PortMappingUtils.MISSING_CP_LOGMSG, nodeId, port.getPartnerPort().getCircuitPackName());
1091             return null;
1092         }
1093         Optional<Ports> poOpt = cpOpt.get().nonnullPorts().values().stream()
1094             .filter(p -> p.getPortName().equals(port.getPartnerPort().getPortName()))
1095             .findFirst();
1096         if (poOpt.isEmpty()) {
1097             LOG.error(PortMappingUtils.NO_PORT_ON_CP_LOGMSG,
1098                 nodeId, port.getPartnerPort().getPortName(), port.getPartnerPort().getCircuitPackName());
1099             return null;
1100         }
1101         Ports port2 = poOpt.get();
1102         circuitPackName2.append(cpOpt.get().getCircuitPackName());
1103         if (!checkPartnerPort(circuitPackName, port, port2)) {
1104             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
1105                 nodeId, port2.getPortName(), circuitPackName2, port.getPortName(), circuitPackName);
1106             return null;
1107         }
1108         return port2;
1109     }
1110
1111
1112     private void putXpdrLcpsInMaps(int line, String nodeId,
1113             Integer xponderNb, XpdrNodeTypes xponderType,
1114             String circuitPackName, String circuitPackName2, Ports port, Ports port2,
1115             Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
1116         String lcp1 =
1117             PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line, StringConstants.NETWORK_TOKEN);
1118         if (lcpMap.containsKey(lcp1)) {
1119             LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, "add", lcp1 + " - already exist");
1120             return;
1121         }
1122         String lcp2 =
1123             PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line + 1, StringConstants.NETWORK_TOKEN);
1124         if (lcpMap.containsKey(lcp2)) {
1125             LOG.warn(PortMappingUtils.UNABLE_MAPPING_LOGMSG, nodeId, "add", lcp2 + " - already exist");
1126             return;
1127         }
1128         lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp1);
1129         lcpMap.put(circuitPackName2 + '+' + port2.getPortName(), lcp2);
1130         mappingMap.put(lcp1,
1131                 createXpdrMappingObject(nodeId, port, circuitPackName, lcp1, lcp2, null, null, xponderType));
1132         mappingMap.put(lcp2,
1133                 createXpdrMappingObject(nodeId, port2, circuitPackName2, lcp2, lcp1, null, null, xponderType));
1134         return;
1135     }
1136
1137     private int[] fillXpdrLcpsMaps(int line, int client, String nodeId,
1138             Integer xponderNb, XpdrNodeTypes xponderType,
1139             String circuitPackName,  Ports port,
1140             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
1141
1142         if (port.getPortQual() == null) {
1143             LOG.warn(PortMappingUtils.PORTQUAL_LOGMSG, nodeId, port.getPortName(), circuitPackName, "not found");
1144             return new int[] {line, client};
1145         }
1146
1147         switch (port.getPortQual()) {
1148
1149             case XpdrClient:
1150             case SwitchClient:
1151                 String lcp0 =
1152                     PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, client, StringConstants.CLIENT_TOKEN);
1153                 lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp0);
1154                 mappingMap.put(lcp0,
1155                     createXpdrMappingObject(nodeId, port, circuitPackName, lcp0, null, null, null, xponderType));
1156                 client++;
1157                 break;
1158
1159             case XpdrNetwork:
1160             case SwitchNetwork:
1161                 line = fillXpdrNetworkLcpsMaps(line, nodeId,
1162                         xponderNb, xponderType,
1163                         circuitPackName,  port,
1164                         circuitPackList,  lcpMap, mappingMap);
1165                 break;
1166
1167             default:
1168                 LOG.error(PortMappingUtils.PORTQUAL_LOGMSG,
1169                     nodeId, port.getPortName(), circuitPackName, port.getPortQual() + " not supported");
1170         }
1171         return new int[] {line, client};
1172     }
1173
1174     private int fillXpdrNetworkLcpsMaps(int line, String nodeId,
1175             Integer xponderNb, XpdrNodeTypes xponderType,
1176             String circuitPackName,  Ports port,
1177             List<CircuitPacks> circuitPackList, Map<String, String> lcpMap, Map<String, Mapping> mappingMap) {
1178
1179         switch (port.getPortDirection()) {
1180
1181             case Bidirectional:
1182                 String lcp =
1183                     PortMappingUtils.createXpdrLogicalConnectionPort(xponderNb, line, StringConstants.NETWORK_TOKEN);
1184                 lcpMap.put(circuitPackName + '+' + port.getPortName(), lcp);
1185                 mappingMap.put(lcp,
1186                     createXpdrMappingObject(nodeId, port, circuitPackName, lcp, null, null, null, xponderType));
1187                 line++;
1188                 break;
1189
1190             case Rx:
1191             case Tx:
1192                 StringBuilder circuitPackName2 = new StringBuilder();
1193                 Ports port2 = getPort2(port, nodeId, circuitPackName, circuitPackName2,
1194                         circuitPackList, lcpMap);
1195
1196                 if (port2 == null) {
1197                      //key already present or an error occured and was logged
1198                     return line;
1199                 }
1200
1201                 putXpdrLcpsInMaps(line, nodeId, xponderNb, xponderType,
1202                         circuitPackName, circuitPackName2.toString(), port, port2,
1203                         lcpMap, mappingMap);
1204                 line += 2;
1205                 break;
1206
1207             default:
1208                 LOG.error(PortMappingUtils.UNSUPPORTED_DIR_LOGMSG,
1209                      nodeId, port.getPortName(), circuitPackName, port.getPortDirection());
1210         }
1211
1212         return line;
1213     }
1214
1215     private boolean createMcCapabilitiesList(String nodeId, Info deviceInfo,
1216             Map<McCapabilitiesKey, McCapabilities> mcCapabilitiesMap) {
1217         if (deviceInfo.getNodeType() == NodeTypes.Rdm) {
1218             Map<Integer, Degree> degrees = getDegreesMap(nodeId, deviceInfo);
1219             List<SharedRiskGroup> srgs = getSrgs(nodeId, deviceInfo);
1220             mcCapabilitiesMap.putAll(getMcCapabilities(degrees, srgs, deviceInfo, nodeId));
1221         } else if ((deviceInfo.getNodeType() == NodeTypes.Xpdr)) {
1222             Map<McCapabilityProfileKey, McCapabilityProfile> mcProfileXpdr = getMcCapabilityProfiles(nodeId,
1223                 deviceInfo);
1224             if (mcProfileXpdr.size() > 1) {
1225                 LOG.warn("Re-check the mc-capability-profiles for XPDR port-mapping");
1226             }
1227             // Typically for a XPDR there will be only one mc-capability-profile
1228             for (Map.Entry<McCapabilityProfileKey, McCapabilityProfile> mcCapProfile : mcProfileXpdr.entrySet()) {
1229                 String mcNodeName = "XPDR" + "-" + "mcprofile";
1230                 McCapabilitiesBuilder mcCapabilitiesBuilder = new McCapabilitiesBuilder()
1231                     .withKey(new McCapabilitiesKey(mcNodeName))
1232                     .setMcNodeName(mcNodeName);
1233                 mcCapabilitiesBuilder
1234                     .setCenterFreqGranularity(mcCapProfile.getValue().getCenterFreqGranularity())
1235                     .setSlotWidthGranularity(mcCapProfile.getValue().getSlotWidthGranularity());
1236                 // Build and add to the Map
1237                 mcCapabilitiesMap.put(mcCapabilitiesBuilder.key(), mcCapabilitiesBuilder.build());
1238                 LOG.info("Finished building mc-capability profile for XPDR {}", nodeId);
1239                 // Since we only have one mc-profile for XPDR, we can break the for-loop
1240                 break;
1241             }
1242
1243         }
1244         return true;
1245     }
1246
1247     private boolean createTtpPortMapping(String nodeId, Info deviceInfo, List<Mapping> portMapList) {
1248         // Creating mapping data for degree TTP's
1249         Map<Integer, Degree> degrees = getDegreesMap(nodeId, deviceInfo);
1250         Map<String, String> interfaceList = getEthInterfaceList(nodeId);
1251         List<CpToDegree> cpToDegreeList = getCpToDegreeList(degrees, interfaceList);
1252         LOG.info(PortMappingUtils.MAP_LOOKS_LOGMSG, nodeId, interfaceList);
1253         postPortMapping(nodeId, null, null, cpToDegreeList, null, null);
1254
1255         for (Entry<Integer, List<ConnectionPorts>> cpMapEntry : getPerDegreePorts(nodeId, deviceInfo).entrySet()) {
1256             List<ConnectionPorts> cpMapValue = cpMapEntry.getValue();
1257             ConnectionPorts cp1 = cpMapValue.get(0);
1258             String cp1Name = cp1.getCircuitPackName();
1259             switch (cpMapValue.size()) {
1260                 case 1:
1261                     // port is bidirectional
1262                     Ports port = getTtpPort(cp1, cp1Name, nodeId);
1263                     if (port == null) {
1264                         return false;
1265                     }
1266                     if (!checkTtpPort(port, cp1Name, nodeId, true)) {
1267                         continue;
1268                     }
1269                     String logicalConnectionPoint =
1270                             PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(), "TXRX");
1271                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
1272                         nodeId, port.getPortName(), cp1Name, logicalConnectionPoint);
1273                     portMapList.add(createMappingObject(nodeId, port, cp1Name, logicalConnectionPoint));
1274                     break;
1275                 case 2:
1276                     // ports are unidirectionals
1277                     Ports port1 = getTtpPort(cp1, cp1Name, nodeId);
1278                     if (port1 == null) {
1279                         return false;
1280                     }
1281                     ConnectionPorts cp2 = cpMapValue.get(1);
1282                     String cp2Name = cp2.getCircuitPackName();
1283                     Ports port2 = getTtpPort(cp2, cp2Name, nodeId);
1284                     if (port2 == null) {
1285                         return false;
1286                     }
1287                     if (!checkTtpPortsUnidir(port1, port2, cp1Name, cp2Name, nodeId)) {
1288                         continue;
1289                     }
1290                     String logicalConnectionPoint1 = PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(),
1291                             port1.getPortDirection().getName().toUpperCase(Locale.getDefault()));
1292                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
1293                         nodeId, port1.getPortName(), cp1Name, logicalConnectionPoint1);
1294                     portMapList.add(createMappingObject(nodeId, port1, cp1Name, logicalConnectionPoint1));
1295                     String logicalConnectionPoint2 = PortMappingUtils.degreeTtpNodeName(cpMapEntry.getKey().toString(),
1296                             port2.getPortDirection().getName().toUpperCase(Locale.getDefault()));
1297                     LOG.info(PortMappingUtils.ASSOCIATED_LCP_LOGMSG,
1298                         nodeId, port2.getPortName(), cp2Name, logicalConnectionPoint2);
1299                     portMapList.add(createMappingObject(nodeId, port2, cp2Name, logicalConnectionPoint2));
1300                     break;
1301                 default:
1302                     LOG.error(PortMappingUtils.NOT_CORRECT_CONPORT_LOGMSG, nodeId, cpMapEntry.getKey());
1303                     continue;
1304                     //TODO should it be continue or return false ?
1305             }
1306         }
1307         return true;
1308     }
1309
1310     private Ports getTtpPort(ConnectionPorts cp, String cpName, String nodeId) {
1311         InstanceIdentifier<Ports> portID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
1312             .child(CircuitPacks.class, new CircuitPacksKey(cpName))
1313             .child(Ports.class, new PortsKey(cp.getPortName()));
1314         LOG.debug(PortMappingUtils.FETCH_CONNECTIONPORT_LOGMSG, nodeId, cp.getPortName(), cpName);
1315         Optional<Ports> portObject = this.deviceTransactionManager.getDataFromDevice(nodeId,
1316             LogicalDatastoreType.OPERATIONAL, portID, Timeouts.DEVICE_READ_TIMEOUT,
1317             Timeouts.DEVICE_READ_TIMEOUT_UNIT);
1318         if (portObject.isEmpty()) {
1319             LOG.error(PortMappingUtils.NO_PORT_ON_CP_LOGMSG, nodeId, cp.getPortName(), cpName);
1320             return null;
1321         }
1322         return portObject.get();
1323     }
1324
1325     private boolean checkPortQual(Ports port, String cpName, String nodeId) {
1326         if (port.getPortQual() == null) {
1327             return false;
1328         }
1329         if (PortQual.RoadmExternal.getIntValue() != port.getPortQual().getIntValue()) {
1330             //used to be LOG.error when called from createTtpPortMapping
1331             LOG.debug(PortMappingUtils.PORT_NOT_RDMEXT_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
1332                 nodeId, port.getPortName(), cpName);
1333             return false;
1334         }
1335         return true;
1336     }
1337
1338     private boolean checkTtpPort(Ports port, String cpName, String nodeId, boolean bidirectional) {
1339         if (!checkPortQual(port, cpName, nodeId)) {
1340             return false;
1341         }
1342         if (Direction.Bidirectional.getIntValue() == port.getPortDirection().getIntValue() ^ bidirectional) {
1343         // (a ^ b) makes more sense than (!a && b) here since it can also work for unidirectional links
1344             LOG.error(PortMappingUtils.PORTDIR_ERROR_LOGMSG + PortMappingUtils.CANNOT_AS_LCP_LOGMSG,
1345                 nodeId, port.getPortName(), cpName);
1346             return false;
1347         }
1348         return true;
1349     }
1350
1351     private boolean checkTtpPortsUnidir(Ports port1, Ports port2, String cp1Name, String cp2Name, String nodeId) {
1352         if (!checkTtpPort(port1, cp1Name, nodeId, false)) {
1353             return false;
1354         }
1355         if (!checkTtpPort(port2, cp2Name, nodeId, false)) {
1356             return false;
1357         }
1358         if (!checkPartnerPort(cp1Name, port1, port2)) {
1359             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
1360                 nodeId, port2.getPortName(), cp2Name, port1.getPortName(), cp1Name);
1361             return false;
1362         }
1363         // Directions checks are the same for cp1 and cp2, no need to check them twice.
1364         if (!checkPartnerPortNoDir(cp2Name, port2, port1)) {
1365             LOG.error(PortMappingUtils.NOT_CORRECT_PARTNERPORT_LOGMSG,
1366                 nodeId, port1.getPortName(), cp1Name, port2.getPortName(), cp2Name);
1367             return false;
1368         }
1369         return true;
1370     }
1371
1372     private NodeInfo createNodeInfo(Info deviceInfo) {
1373         if (deviceInfo.getNodeType() == null) {
1374             // TODO make mandatory in yang
1375             LOG.error(PortMappingUtils.NODE_TYPE_LOGMSG, deviceInfo.getNodeId(), "field missing");
1376             return null;
1377         }
1378         NodeInfoBuilder nodeInfoBldr = new NodeInfoBuilder()
1379                 .setOpenroadmVersion(OpenroadmNodeVersion._71)
1380                 .setNodeClli(
1381                     deviceInfo.getClli() == null || deviceInfo.getClli().isEmpty()
1382                         ? "defaultCLLI"
1383                         : deviceInfo.getClli())
1384                 .setNodeType(deviceInfo.getNodeType());
1385         // TODO: 221 versions expects an int value - need to check whether it is bug or an evolution here
1386         if (deviceInfo.getModel() != null) {
1387             nodeInfoBldr.setNodeModel(deviceInfo.getModel());
1388         }
1389         if (deviceInfo.getVendor() != null) {
1390             nodeInfoBldr.setNodeVendor(deviceInfo.getVendor());
1391         }
1392         if (deviceInfo.getIpAddress() != null) {
1393             nodeInfoBldr.setNodeIpAddress(deviceInfo.getIpAddress());
1394         }
1395         return nodeInfoBldr.build();
1396     }
1397
1398     private String getLcpFromCpAndPort(Map<MappingKey, Mapping> mappings, String cpName, String portName) {
1399         for (Mapping mapping : mappings.values()) {
1400             if (cpName.equals(mapping.getSupportingCircuitPackName())
1401                 && portName.equals(mapping.getSupportingPort())) {
1402                 return mapping.getLogicalConnectionPoint();
1403             }
1404         }
1405         return null;
1406     }
1407
1408     private Optional<Interface> getInterfaceFromDevice(String nodeId, String interfaceName) {
1409         InstanceIdentifier<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
1410             .child(Interface.class, new InterfaceKey(interfaceName));
1411         return deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.CONFIGURATION,
1412             interfacesIID, Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
1413     }
1414 }