Move serviceType affectation to common
[transportpce.git] / pce / src / main / java / org / opendaylight / transportpce / pce / networkanalyzer / PceCalculation.java
1 /*
2  * Copyright © 2017 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.pce.networkanalyzer;
10
11 import java.math.BigDecimal;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.Set;
19 import java.util.concurrent.ExecutionException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.transportpce.common.NetworkUtils;
23 import org.opendaylight.transportpce.common.ResponseCodes;
24 import org.opendaylight.transportpce.common.StringConstants;
25 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
26 import org.opendaylight.transportpce.common.mapping.MappingUtils;
27 import org.opendaylight.transportpce.common.mapping.MappingUtilsImpl;
28 import org.opendaylight.transportpce.common.mapping.PortMapping;
29 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
30 import org.opendaylight.transportpce.common.service.ServiceTypes;
31 import org.opendaylight.transportpce.pce.PceComplianceCheck;
32 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
33 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.PathComputationRequestInput;
34 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.mapping.Mapping;
35 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev210426.mc.capabilities.McCapabilities;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Node1;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.state.types.rev191129.State;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.NodeTypes;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmNodeType;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.common.Uint32;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class PceCalculation {
57     /* Logging. */
58     private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
59     private NetworkTransactionService networkTransactionService = null;
60
61     ///////////// data parsed from Input/////////////////
62     private PathComputationRequestInput input;
63     private String anodeId = "";
64     private String znodeId = "";
65     private String serviceFormatA = "";
66     private String serviceFormatZ = "";
67     private String serviceType = "";
68     private Uint32 serviceRate = Uint32.valueOf(0);
69
70     private PceConstraints pceHardConstraints;
71
72     ///////////// Intermediate data/////////////////
73     private List<PceLink> addLinks = new ArrayList<>();
74     private List<PceLink> dropLinks = new ArrayList<>();
75     private HashSet<NodeId> azSrgs = new HashSet<>();
76
77     private PceNode aendPceNode = null;
78     private PceNode zendPceNode = null;
79
80     private List<Link> allLinks = null;
81     private List<Node> allNodes = null;
82
83     // this List serves graph calculation
84     private Map<NodeId, PceNode> allPceNodes = new HashMap<>();
85     // this List serves calculation of ZtoA path description
86     // TODO maybe better solution is possible
87     private Map<LinkId, PceLink> allPceLinks = new HashMap<>();
88     private Set<LinkId> linksToExclude = new HashSet<>();
89     private PceResult returnStructure;
90     private PortMapping portMapping;
91
92     private enum ConstraintTypes {
93         NONE, HARD_EXCLUDE, HARD_INCLUDE, HARD_DIVERSITY, SOFT_EXCLUDE, SOFT_INCLUDE, SOFT_DIVERSITY;
94     }
95
96     private MappingUtils mappingUtils;
97
98     public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService,
99             PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc,
100             PortMapping portMapping) {
101         this.input = input;
102         this.networkTransactionService = networkTransactionService;
103         this.returnStructure = rc;
104
105         this.pceHardConstraints = pceHardConstraints;
106         this.mappingUtils = new MappingUtilsImpl(networkTransactionService.getDataBroker());
107         this.portMapping = portMapping;
108         parseInput();
109     }
110
111     public void retrievePceNetwork() {
112
113         LOG.info("In PceCalculation retrieveNetwork: ");
114
115         if (!readMdSal()) {
116             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
117             return;
118         }
119         MapUtils.mapDiversityConstraints(allNodes, allLinks, pceHardConstraints);
120
121         if (!analyzeNw()) {
122             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
123             return;
124         }
125         printNodesInfo(allPceNodes);
126
127         returnStructure.setRC(ResponseCodes.RESPONSE_OK);
128         return;
129     }
130
131     private boolean parseInput() {
132         if (!PceComplianceCheck.checkString(input.getServiceAEnd().getServiceFormat().getName())
133                 || !PceComplianceCheck.checkString(input.getServiceZEnd().getServiceFormat().getName())
134                 || !PceComplianceCheck.checkString(input.getServiceAEnd().getServiceRate().toString())) {
135             LOG.error("Service Format and Service Rate are required for a path calculation");
136             return false;
137         }
138         serviceFormatA = input.getServiceAEnd().getServiceFormat().getName();
139         serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName();
140         serviceRate = input.getServiceAEnd().getServiceRate();
141         if (NodeTypes.Xpdr.equals(portMapping.getNode(input.getServiceAEnd().getNodeId()).getNodeInfo().getNodeType())
142             && input.getServiceAEnd().getTxDirection() != null
143             && input.getServiceAEnd().getTxDirection().getPort() != null
144             && input.getServiceAEnd().getTxDirection().getPort().getPortName() != null) {
145             Mapping mapping = portMapping.getMapping(input.getServiceAEnd().getNodeId(),
146                 input.getServiceAEnd().getTxDirection().getPort().getPortName());
147             serviceType = ServiceTypes.getServiceType(serviceFormatA, serviceRate, mapping);
148         } else {
149             serviceType = ServiceTypes.getServiceType(serviceFormatA, serviceRate, null);
150         }
151
152         LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId);
153
154         getAZnodeId();
155
156         returnStructure.setRate(input.getServiceAEnd().getServiceRate().toJava());
157         returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat());
158         return true;
159     }
160
161     private void getAZnodeId() {
162         if (StringConstants.SERVICE_TYPE_ODU4.equals(serviceType)
163                 || StringConstants.SERVICE_TYPE_ODUC4.equals(serviceType)
164                 || StringConstants.SERVICE_TYPE_100GE_M.equals(serviceType)
165                 || StringConstants.SERVICE_TYPE_10GE.equals(serviceType)
166                 || StringConstants.SERVICE_TYPE_1GE.equals(serviceType)) {
167             anodeId = input.getServiceAEnd().getTxDirection().getPort().getPortDeviceName();
168             znodeId = input.getServiceZEnd().getTxDirection().getPort().getPortDeviceName();
169         } else {
170             anodeId = input.getServiceAEnd().getNodeId();
171             znodeId = input.getServiceZEnd().getNodeId();
172         }
173     }
174
175     private boolean readMdSal() {
176         InstanceIdentifier<Network> nwInstanceIdentifier = null;
177         switch (serviceType) {
178             case StringConstants.SERVICE_TYPE_100GE_T:
179             case StringConstants.SERVICE_TYPE_400GE:
180             case StringConstants.SERVICE_TYPE_OTU4:
181             case StringConstants.SERVICE_TYPE_OTUC4:
182                 LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
183                 nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
184                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
185                 break;
186             case StringConstants.SERVICE_TYPE_100GE_M:
187             case StringConstants.SERVICE_TYPE_ODU4:
188             case StringConstants.SERVICE_TYPE_ODUC4:
189             case StringConstants.SERVICE_TYPE_10GE:
190             case StringConstants.SERVICE_TYPE_1GE:
191                 LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID);
192                 nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
193                     .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build();
194                 break;
195             default:
196                 LOG.warn("readMdSal: unknown service-type for service-rate {} and service-format {}", serviceRate,
197                     serviceFormatA);
198                 break;
199         }
200
201         if (readTopology(nwInstanceIdentifier) != null) {
202             allNodes = readTopology(nwInstanceIdentifier).nonnullNode().values().stream().sorted((n1, n2)
203                 -> n1.getNodeId().getValue().compareTo(n2.getNodeId().getValue())).collect(Collectors.toList());
204             Network1 nw1 = readTopology(nwInstanceIdentifier).augmentation(Network1.class);
205             if (nw1 != null) {
206                 allLinks = nw1.nonnullLink().values().stream().sorted((l1, l2)
207                     -> l1.getSource().getSourceTp().toString().compareTo(l2.getSource().getSourceTp().toString()))
208                         .collect(Collectors.toList());
209             } else {
210                 LOG.warn("no otn links in otn-topology");
211             }
212             if (allNodes == null || allNodes.isEmpty()) {
213                 LOG.error("readMdSal: no nodes ");
214                 return false;
215             }
216             LOG.info("readMdSal: network nodes: {} nodes added", allNodes.size());
217             LOG.debug("readMdSal: network nodes: {} nodes added", allNodes);
218
219             if (allLinks == null || allLinks.isEmpty()) {
220                 LOG.error("readMdSal: no links ");
221                 return false;
222             }
223             LOG.info("readMdSal: network links: {} links added", allLinks.size());
224             LOG.debug("readMdSal: network links: {} links added", allLinks);
225
226             return true;
227         } else {
228             LOG.error("readMdSal: network is null: {}", nwInstanceIdentifier);
229             return false;
230         }
231     }
232
233     private Network readTopology(InstanceIdentifier<Network> nwInstanceIdentifier) {
234         Network nw = null;
235         try {
236             Optional<Network> nwOptional =
237                 networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get();
238             if (nwOptional.isPresent()) {
239                 nw = nwOptional.get();
240                 LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw);
241                 networkTransactionService.close();
242             }
243         } catch (InterruptedException | ExecutionException e) {
244             LOG.error("readMdSal: Error reading topology {}", nwInstanceIdentifier);
245             networkTransactionService.close();
246             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
247             throw new RuntimeException(
248                 "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
249         }
250         return nw;
251     }
252
253     private boolean analyzeNw() {
254
255         LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size());
256
257         if (StringConstants.SERVICE_TYPE_100GE_T.equals(serviceType)
258                 || StringConstants.SERVICE_TYPE_OTU4.equals(serviceType)
259                 || StringConstants.SERVICE_TYPE_400GE.equals(serviceType)
260                 || StringConstants.SERVICE_TYPE_OTUC4.equals(serviceType)) {
261             // 100GE service and OTU4 service are handled at the openroadm-topology layer
262             for (Node node : allNodes) {
263                 validateNode(node);
264             }
265
266             LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
267
268             if (aendPceNode == null || zendPceNode == null) {
269                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
270                 return false;
271             }
272             for (Link link : allLinks) {
273                 validateLink(link);
274             }
275             // debug prints
276             LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
277             // debug prints
278             LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
279             for (NodeId srg : azSrgs) {
280                 LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
281             }
282             // debug prints
283             for (PceLink link : addLinks) {
284                 filteraddLinks(link);
285             }
286             for (PceLink link : dropLinks) {
287                 filterdropLinks(link);
288             }
289
290         } else {
291             // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer
292
293             for (Node node : allNodes) {
294                 validateOtnNode(node);
295             }
296
297             LOG.info("analyzeNw: allPceNodes {}", allPceNodes);
298
299             if (aendPceNode == null || zendPceNode == null) {
300                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
301                 return false;
302             }
303             for (Link link : allLinks) {
304                 validateLink(link);
305             }
306         }
307
308         LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size());
309
310         if ((allPceNodes.size() == 0) || (allPceLinks.size() == 0)) {
311             return false;
312         }
313
314         LOG.debug("analyzeNw: allPceNodes {}", allPceNodes);
315         LOG.debug("analyzeNw: allPceLinks {}", allPceLinks);
316
317         return true;
318     }
319
320     private boolean filteraddLinks(PceLink pcelink) {
321
322         NodeId nodeId = pcelink.getSourceId();
323
324         if (azSrgs.contains(nodeId)) {
325             allPceLinks.put(pcelink.getLinkId(), pcelink);
326             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
327             LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId());
328             return true;
329         }
330
331         // remove the SRG from PceNodes, as it is not directly connected to A/Z
332         allPceNodes.remove(nodeId);
333         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
334
335         return false;
336     }
337
338     private boolean filterdropLinks(PceLink pcelink) {
339
340         NodeId nodeId = pcelink.getDestId();
341
342         if (azSrgs.contains(nodeId)) {
343             allPceLinks.put(pcelink.getLinkId(), pcelink);
344             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
345             LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId());
346             return true;
347         }
348
349         // remove the SRG from PceNodes, as it is not directly connected to A/Z
350         allPceNodes.remove(pcelink.getDestId());
351         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
352
353         return false;
354     }
355
356     private boolean validateLink(Link link) {
357         LOG.info("validateLink: link {} ", link);
358
359         NodeId sourceId = link.getSource().getSourceNode();
360         NodeId destId = link.getDestination().getDestNode();
361         PceNode source = allPceNodes.get(sourceId);
362         PceNode dest = allPceNodes.get(destId);
363         State state = link.augmentation(Link1.class).getOperationalState();
364
365         if (source == null) {
366             LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}",
367                 link.getSource().getSourceNode().getValue());
368             return false;
369         }
370         if (dest == null) {
371             LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}",
372                 link.getDestination().getDestNode().getValue());
373             return false;
374         }
375
376         if (State.OutOfService.equals(state)) {
377             LOG.debug("validateLink: Link is ignored due operational state - {}",
378                     state.getName());
379             return false;
380         }
381
382         switch (serviceType) {
383             case StringConstants.SERVICE_TYPE_100GE_T:
384             case StringConstants.SERVICE_TYPE_OTU4:
385             case StringConstants.SERVICE_TYPE_OTUC4:
386             case StringConstants.SERVICE_TYPE_400GE:
387                 return processPceLink(link, sourceId, destId, source, dest);
388             case StringConstants.SERVICE_TYPE_ODU4:
389             case StringConstants.SERVICE_TYPE_10GE:
390             case StringConstants.SERVICE_TYPE_100GE_M:
391             case StringConstants.SERVICE_TYPE_ODUC4:
392             case StringConstants.SERVICE_TYPE_1GE:
393                 return processPceOtnLink(link, source, dest);
394             default:
395                 LOG.error(" validateLink: Unmanaged service type {}", serviceType);
396                 return false;
397         }
398     }
399
400     private void validateNode(Node node) {
401         LOG.debug("validateNode: node {} ", node);
402         // PceNode will be used in Graph algorithm
403         Node1 node1 = node.augmentation(Node1.class);
404         if (node1 == null) {
405             LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
406             return;
407         }
408         if (State.OutOfService.equals(node1.getOperationalState())) {
409             LOG.error("getNodeType: node is ignored due to operational state - {}", node1.getOperationalState()
410                     .getName());
411             return;
412         }
413         OpenroadmNodeType nodeType = node1.getNodeType();
414         String deviceNodeId = MapUtils.getSupNetworkNode(node);
415         // Should never happen but because of existing topology test files
416         // we have to manage this case
417         if (deviceNodeId == null || deviceNodeId.isBlank()) {
418             deviceNodeId = node.getNodeId().getValue();
419         }
420
421         LOG.info("Device node id {} for {}", deviceNodeId, node);
422         PceOpticalNode pceNode = new PceOpticalNode(deviceNodeId, this.serviceType, portMapping, node, nodeType,
423             mappingUtils.getOpenRoadmVersion(deviceNodeId), getSlotWidthGranularity(deviceNodeId, node.getNodeId()),
424             getCentralFreqGranularity(deviceNodeId, node.getNodeId()));
425         pceNode.validateAZxponder(anodeId, znodeId, input.getServiceAEnd().getServiceFormat());
426         pceNode.initFrequenciesBitSet();
427
428         if (!pceNode.isValid()) {
429             LOG.warn(" validateNode: Node is ignored");
430             return;
431         }
432         if (validateNodeConstraints(pceNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
433             return;
434         }
435         if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.aendPceNode == null
436             && isAZendPceNode(this.serviceFormatA, pceNode, anodeId, "A")) {
437             this.aendPceNode = pceNode;
438         }
439         if (endPceNode(nodeType, pceNode.getNodeId(), pceNode) && this.zendPceNode == null
440             && isAZendPceNode(this.serviceFormatZ, pceNode, znodeId, "Z")) {
441             this.zendPceNode = pceNode;
442         }
443
444         allPceNodes.put(pceNode.getNodeId(), pceNode);
445         LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue());
446         return;
447     }
448
449     private boolean isAZendPceNode(String serviceFormat, PceOpticalNode pceNode, String azNodeId, String azEndPoint) {
450         switch (serviceFormat) {
451             case "Ethernet":
452             case "OC":
453                 if (pceNode.getSupNetworkNodeId().equals(azNodeId)) {
454                     return true;
455                 }
456                 return false;
457             case "OTU":
458                 if ("A".equals(azEndPoint) && pceNode.getNodeId().getValue()
459                     .equals(this.input.getServiceAEnd().getRxDirection().getPort().getPortDeviceName())) {
460                     return true;
461                 }
462                 if ("Z".equals(azEndPoint) && pceNode.getNodeId().getValue()
463                     .equals(this.input.getServiceZEnd().getRxDirection().getPort().getPortDeviceName())) {
464                     return true;
465                 }
466                 return false;
467             default:
468                 LOG.debug("Unsupported service Format {} for node {}", serviceFormat, pceNode.getNodeId().getValue());
469                 return false;
470         }
471     }
472
473     private void validateOtnNode(Node node) {
474         LOG.info("validateOtnNode: {} ", node.getNodeId().getValue());
475         // PceOtnNode will be used in Graph algorithm
476         if (node.augmentation(Node1.class) != null) {
477             OpenroadmNodeType nodeType = node.augmentation(Node1.class).getNodeType();
478
479             PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), "otn", serviceType);
480             pceOtnNode.validateXponder(anodeId, znodeId);
481
482             if (!pceOtnNode.isValid()) {
483                 LOG.warn(" validateOtnNode: Node {} is ignored", node.getNodeId().getValue());
484                 return;
485             }
486             if (validateNodeConstraints(pceOtnNode).equals(ConstraintTypes.HARD_EXCLUDE)) {
487                 return;
488             }
489             if (pceOtnNode.getNodeId().getValue().equals(anodeId) && this.aendPceNode == null) {
490                 this.aendPceNode = pceOtnNode;
491             }
492             if (pceOtnNode.getNodeId().getValue().equals(znodeId) && this.zendPceNode == null) {
493                 this.zendPceNode = pceOtnNode;
494             }
495             allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode);
496             LOG.info("validateOtnNode: node {} is saved", node.getNodeId().getValue());
497             return;
498         } else {
499             LOG.error("ValidateOtnNode: no node-type augmentation. Node {} is ignored", node.getNodeId().getValue());
500             return;
501         }
502     }
503
504     private ConstraintTypes validateNodeConstraints(PceNode pcenode) {
505         if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) {
506             return ConstraintTypes.NONE;
507         }
508         if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeId())) {
509             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
510             return ConstraintTypes.HARD_EXCLUDE;
511         }
512         if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getSupClliNodeId())) {
513             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
514             return ConstraintTypes.HARD_EXCLUDE;
515         }
516         return ConstraintTypes.NONE;
517     }
518
519     private ConstraintTypes validateLinkConstraints(PceLink link) {
520         if (pceHardConstraints.getExcludeSRLG().isEmpty()) {
521             return ConstraintTypes.NONE;
522         }
523
524         // for now SRLG is the only constraint for link
525         if (link.getlinkType() != OpenroadmLinkType.ROADMTOROADM) {
526             return ConstraintTypes.NONE;
527         }
528
529         List<Long> constraints = new ArrayList<>(pceHardConstraints.getExcludeSRLG());
530         constraints.retainAll(link.getsrlgList());
531         if (!constraints.isEmpty()) {
532             LOG.info("validateLinkConstraints: {}", link.getLinkId().getValue());
533             return ConstraintTypes.HARD_EXCLUDE;
534         }
535
536         return ConstraintTypes.NONE;
537     }
538
539     private void dropOppositeLink(Link link) {
540         LinkId opplink = MapUtils.extractOppositeLink(link);
541
542         if (allPceLinks.containsKey(opplink)) {
543             allPceLinks.remove(opplink);
544         } else {
545             linksToExclude.add(opplink);
546         }
547     }
548
549     private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceOpticalNode pceNode) {
550         switch (openroadmNodeType) {
551             case SRG:
552                 pceNode.initSrgTps();
553                 this.azSrgs.add(nodeId);
554                 break;
555             case XPONDER:
556                 pceNode.initXndrTps(input.getServiceAEnd().getServiceFormat());
557                 break;
558             default:
559                 LOG.warn("endPceNode: Node {} is not SRG or XPONDER !", nodeId);
560                 return false;
561         }
562
563         if (!pceNode.isValid()) {
564             LOG.error("validateNode : there are no available frequencies in node {}", pceNode.getNodeId().getValue());
565             return false;
566         }
567         return true;
568     }
569
570     private boolean processPceLink(Link link, NodeId sourceId, NodeId destId, PceNode source, PceNode dest) {
571         PceLink pcelink = new PceLink(link, source, dest);
572         if (!pcelink.isValid()) {
573             dropOppositeLink(link);
574             LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
575             return false;
576         }
577         LinkId linkId = pcelink.getLinkId();
578         if (validateLinkConstraints(pcelink).equals(ConstraintTypes.HARD_EXCLUDE)) {
579             dropOppositeLink(link);
580             LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
581             return false;
582         }
583         switch (pcelink.getlinkType()) {
584             case ROADMTOROADM:
585             case EXPRESSLINK:
586                 allPceLinks.put(linkId, pcelink);
587                 source.addOutgoingLink(pcelink);
588                 LOG.debug("validateLink: {}-LINK added to allPceLinks {}",
589                     pcelink.getlinkType(), pcelink);
590                 break;
591             case ADDLINK:
592                 pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString()));
593                 addLinks.add(pcelink);
594                 LOG.debug("validateLink: ADD-LINK saved  {}", pcelink);
595                 break;
596             case DROPLINK:
597                 pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString()));
598                 dropLinks.add(pcelink);
599                 LOG.debug("validateLink: DROP-LINK saved  {}", pcelink);
600                 break;
601             case XPONDERINPUT:
602                 // store separately all SRG links directly
603                 azSrgs.add(sourceId);
604                 // connected to A/Z
605                 if (!dest.checkTP(pcelink.getDestTP().toString())) {
606                     LOG.debug(
607                         "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink);
608                     return false;
609                 }
610                 if (dest.getXpdrClient(pcelink.getDestTP().toString()) != null) {
611                     pcelink.setClient(dest.getXpdrClient(pcelink.getDestTP().toString()));
612                 }
613                 allPceLinks.put(linkId, pcelink);
614                 source.addOutgoingLink(pcelink);
615                 LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink);
616                 break;
617             // does it mean XPONDER==>>SRG ?
618             case XPONDEROUTPUT:
619                 // store separately all SRG links directly
620                 azSrgs.add(destId);
621                 // connected to A/Z
622                 if (!source.checkTP(pcelink.getSourceTP().toString())) {
623                     LOG.debug(
624                         "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink);
625                     return false;
626                 }
627                 if (source.getXpdrClient(pcelink.getSourceTP().toString()) != null) {
628                     pcelink.setClient(source.getXpdrClient(pcelink.getSourceTP().toString()));
629                 }
630                 allPceLinks.put(linkId, pcelink);
631                 source.addOutgoingLink(pcelink);
632                 LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink);
633                 break;
634             default:
635                 LOG.warn("validateLink: link type is not supported {}", pcelink);
636         }
637         return true;
638     }
639
640     private boolean processPceOtnLink(Link link, PceNode source, PceNode dest) {
641         PceLink pceOtnLink = new PceLink(link, source, dest);
642
643         if (!pceOtnLink.isOtnValid(link, serviceType)) {
644             dropOppositeLink(link);
645             LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
646             return false;
647         }
648
649         LinkId linkId = pceOtnLink.getLinkId();
650         if (validateLinkConstraints(pceOtnLink).equals(ConstraintTypes.HARD_EXCLUDE)) {
651             dropOppositeLink(link);
652             LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
653             return false;
654         }
655
656         switch (pceOtnLink.getlinkType()) {
657             case OTNLINK:
658                 if (dest.getXpdrClient(pceOtnLink.getDestTP().toString()) != null) {
659                     pceOtnLink.setClient(dest.getXpdrClient(pceOtnLink.getDestTP().toString()));
660                 }
661
662                 allPceLinks.put(linkId, pceOtnLink);
663                 source.addOutgoingLink(pceOtnLink);
664                 LOG.info("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink);
665                 break;
666             default:
667                 LOG.warn("validateLink: link type is not supported {}", pceOtnLink);
668         }
669         return true;
670     }
671
672     public PceNode getaendPceNode() {
673         return aendPceNode;
674     }
675
676     public PceNode getzendPceNode() {
677         return zendPceNode;
678     }
679
680     public Map<NodeId, PceNode> getAllPceNodes() {
681         return this.allPceNodes;
682     }
683
684     public Map<LinkId, PceLink> getAllPceLinks() {
685         return this.allPceLinks;
686     }
687
688     public String getServiceType() {
689         return serviceType;
690     }
691
692     public PceResult getReturnStructure() {
693         return returnStructure;
694     }
695
696     private static void printNodesInfo(Map<NodeId, PceNode> allPceNodes) {
697         allPceNodes.forEach(((nodeId, pceNode) -> {
698             LOG.info("In printNodes in node {} : outgoing links {} ", pceNode.getNodeId().getValue(),
699                     pceNode.getOutgoingLinks());
700         }));
701     }
702
703     /**
704      * Get mc capability slot width granularity for device.
705      * @param deviceNodeId String
706      * @param nodeId NodeId
707      * @return slot width granularity
708      */
709     private BigDecimal getSlotWidthGranularity(String deviceNodeId, NodeId nodeId) {
710         // nodeId: openroadm-topology level node
711         // deviceNodeId: openroadm-network level node
712         List<McCapabilities> mcCapabilities = mappingUtils.getMcCapabilitiesForNode(deviceNodeId);
713         String[] params = nodeId.getValue().split("-");
714         // DEGx or SRGx or XPDRx
715         String moduleName = params[params.length - 1];
716         for (McCapabilities mcCapabitility : mcCapabilities) {
717             if (mcCapabitility.getMcNodeName().contains("XPDR")
718                 && mcCapabitility.getSlotWidthGranularity() != null) {
719                 return mcCapabitility.getSlotWidthGranularity().getValue();
720             }
721             if (mcCapabitility.getMcNodeName().contains(moduleName)
722                     && mcCapabitility.getSlotWidthGranularity() != null) {
723                 return mcCapabitility.getSlotWidthGranularity().getValue();
724             }
725         }
726         return GridConstant.SLOT_WIDTH_50;
727     }
728
729     /**
730      * Get mc capability central-width granularity for device.
731      * @param deviceNodeId String
732      * @param nodeId NodeId
733      * @return center-freq granularity
734      */
735     private BigDecimal getCentralFreqGranularity(String deviceNodeId, NodeId nodeId) {
736         // nodeId: openroadm-topology level node
737         // deviceNodeId: openroadm-network level node
738         List<McCapabilities> mcCapabilities = mappingUtils.getMcCapabilitiesForNode(deviceNodeId);
739         String[] params = nodeId.getValue().split("-");
740         // DEGx or SRGx or XPDRx
741         String moduleName = params[params.length - 1];
742         for (McCapabilities mcCapabitility : mcCapabilities) {
743             if (mcCapabitility.getMcNodeName().contains("XPDR")
744                 && mcCapabitility.getCenterFreqGranularity() != null) {
745                 return mcCapabitility.getCenterFreqGranularity().getValue();
746             }
747             if (mcCapabitility.getMcNodeName().contains(moduleName)
748                 && mcCapabitility.getCenterFreqGranularity() != null) {
749                 return mcCapabitility.getCenterFreqGranularity().getValue();
750             }
751         }
752         return GridConstant.SLOT_WIDTH_50;
753     }
754 }