61f288e00e26e0183d7862808509f82fa2b99f0e
[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.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
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
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.transportpce.common.NetworkUtils;
24 import org.opendaylight.transportpce.common.ResponseCodes;
25 import org.opendaylight.transportpce.common.network.NetworkTransactionService;
26 import org.opendaylight.transportpce.pce.constraints.PceConstraints;
27 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev190624.PathComputationRequestInput;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev181130.Node1;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmLinkType;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev181130.OpenroadmNodeType;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NodeId;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.LinkId;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 //import org.opendaylight.yangtools.yang.common.Decimal64;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class PceCalculation {
46     /* Logging. */
47     private static final Logger LOG = LoggerFactory.getLogger(PceCalculation.class);
48     private NetworkTransactionService networkTransactionService = null;
49
50     ///////////// data parsed from Input/////////////////
51     private PathComputationRequestInput input;
52     private String anodeId = "";
53     private String znodeId = "";
54     private String serviceFormatA = "";
55     private String serviceFormatZ = "";
56     private String serviceType = "";
57     private Long serviceRate = 0L;
58
59     private PceConstraints pceHardConstraints;
60
61     ///////////// Intermediate data/////////////////
62     private List<PceLink> addLinks = new ArrayList<PceLink>();
63     private List<PceLink> dropLinks = new ArrayList<PceLink>();
64     private HashSet<NodeId> azSrgs = new HashSet<NodeId>();
65
66     private PceNode aendPceNode = null;
67     private PceNode zendPceNode = null;
68
69     private List<Link> allLinks = null;
70     private List<Node> allNodes = null;
71
72     // this List serves graph calculation
73     private Map<NodeId, PceNode> allPceNodes = new HashMap<NodeId, PceNode>();
74     // this List serves calculation of ZtoA path description
75     // TODO maybe better solution is possible
76     private Map<LinkId, PceLink> allPceLinks = new HashMap<LinkId, PceLink>();
77     private Set<LinkId> linksToExclude = new HashSet<LinkId>();
78     private PceResult returnStructure;
79
80     private enum ConstraintTypes {
81         NONE, HARD_EXCLUDE, HARD_INCLUDE, HARD_DIVERSITY, SOFT_EXCLUDE, SOFT_INCLUDE, SOFT_DIVERSITY;
82     }
83
84     public PceCalculation(PathComputationRequestInput input, NetworkTransactionService networkTransactionService,
85             PceConstraints pceHardConstraints, PceConstraints pceSoftConstraints, PceResult rc) {
86         this.input = input;
87         this.networkTransactionService = networkTransactionService;
88         this.returnStructure = rc;
89
90         this.pceHardConstraints = pceHardConstraints;
91         parseInput();
92     }
93
94     public void retrievePceNetwork() {
95
96         LOG.info("In PceCalculation retrieveNetwork: ");
97
98         if (!readMdSal()) {
99             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
100             return;
101         }
102         MapUtils.mapDiversityConstraints(allNodes, allLinks, pceHardConstraints);
103
104         if (!analyzeNw()) {
105             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
106             return;
107         }
108         printNodesInfo(allPceNodes);
109
110         returnStructure.setRC(ResponseCodes.RESPONSE_OK);
111         return;
112     }
113
114     private boolean parseInput() {
115         anodeId = input.getServiceAEnd().getNodeId();
116         znodeId = input.getServiceZEnd().getNodeId();
117         serviceFormatA = input.getServiceAEnd().getServiceFormat().getName();
118         serviceFormatZ = input.getServiceZEnd().getServiceFormat().getName();
119         serviceRate = input.getServiceAEnd().getServiceRate();
120
121         LOG.info("parseInput: A and Z :[{}] and [{}]", anodeId, znodeId);
122         if (!(serviceFormatA.equals(serviceFormatZ))) {
123             LOG.info("parseInput: different service format for A and Z not handled, will use service format from Aend");
124         } else if (serviceRate == 100L) {
125             switch (serviceFormatA) {
126                 case "Ethernet":
127                 case "OC":
128                     serviceType = "100GE";
129                     break;
130                 case "OTU":
131                     serviceType = "OTU4";
132                     break;
133                 case "ODU":
134                     serviceType = "ODU4";
135                     break;
136                 default:
137                     LOG.debug("parseInput: unsupported service type: Format {} Rate 100L", serviceFormatA);
138                     break;
139             }
140             //switch(serviceRate) may seem a better option at first glance.
141             //But switching on Long or long is not directly possible in Java.
142             //And casting to int bumps the limit here.
143             //Passing by ENUM or String are possible alternatives.
144             //Maybe HashMap and similar options should also be considered here.
145         } else if (serviceFormatA == "Ethernet") {
146         //only rate 100L is currently supported except in Ethernet
147             if (serviceRate == 10L) {
148                 serviceType = "10GE";
149             } else if (serviceRate == 1L) {
150                 serviceType = "1GE";
151             } else {
152                 LOG.debug("parseInput: unsupported service type: Format Ethernet Rate {}", String.valueOf(serviceRate));
153             }
154         } else {
155             LOG.debug("parseInput: unsupported service type: Format {} Rate {}",
156                 serviceFormatA, String.valueOf(serviceRate));
157         }
158
159         returnStructure.setRate(input.getServiceAEnd().getServiceRate());
160         returnStructure.setServiceFormat(input.getServiceAEnd().getServiceFormat());
161         return true;
162     }
163
164     private boolean readMdSal() {
165         InstanceIdentifier<Network> nwInstanceIdentifier = null;
166         Network nw = null;
167         if (("OC".equals(serviceFormatA)) || ("OTU".equals(serviceFormatA)) || (("Ethernet".equals(serviceFormatA))
168             && (serviceRate == 100L))) {
169
170             LOG.info("readMdSal: network {}", NetworkUtils.OVERLAY_NETWORK_ID);
171             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
172                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
173         } else if ("ODU".equals(serviceFormatA)) {
174             LOG.info("readMdSal: network {}", NetworkUtils.OTN_NETWORK_ID);
175             nwInstanceIdentifier = InstanceIdentifier.builder(Networks.class)
176                 .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OTN_NETWORK_ID))).build();
177         } else {
178             LOG.info("readMdSal: service-rate {} / service-format not handled {}", serviceRate, serviceFormatA);
179             return false;
180         }
181
182         try {
183             Optional<Network> nwOptional =
184                 networkTransactionService.read(LogicalDatastoreType.CONFIGURATION, nwInstanceIdentifier).get();
185             if (nwOptional.isPresent()) {
186                 nw = nwOptional.get();
187                 LOG.debug("readMdSal: network nodes: nwOptional.isPresent = true {}", nw.toString());
188             }
189         } catch (InterruptedException | ExecutionException e) {
190             LOG.error("readMdSal: Error reading topology {}", nwInstanceIdentifier);
191             networkTransactionService.close();
192             returnStructure.setRC(ResponseCodes.RESPONSE_FAILED);
193             throw new RuntimeException(
194                 "readMdSal: Error reading from operational store, topology : " + nwInstanceIdentifier + " :" + e);
195         }
196         networkTransactionService.close();
197
198         if (nw == null) {
199             LOG.error("readMdSal: network is null: {}", nwInstanceIdentifier);
200             return false;
201         }
202         allNodes = nw.getNode().stream().sorted((n1, n2) -> n1.getNodeId().getValue().compareTo(n2.getNodeId()
203             .getValue())).collect(Collectors.toList());
204         Network1 nw1 = nw.augmentation(Network1.class);
205
206         allLinks = nw1.getLink().stream().sorted((l1, l2) -> l1.getSource().getSourceTp().toString().compareTo(l2
207             .getSource().getSourceTp().toString())).collect(Collectors.toList());
208         if (allNodes == null || allNodes.isEmpty()) {
209             LOG.error("readMdSal: no nodes ");
210             return false;
211         }
212         LOG.info("readMdSal: network nodes: {} nodes added", allNodes.size());
213         LOG.debug("readMdSal: network nodes: {} nodes added", allNodes.toString());
214
215         if (allLinks == null || allLinks.isEmpty()) {
216             LOG.error("readMdSal: no links ");
217             return false;
218         }
219         LOG.info("readMdSal: network links: {} links added", allLinks.size());
220         LOG.debug("readMdSal: network links: {} links added", allLinks.toString());
221
222         return true;
223     }
224
225     private boolean analyzeNw() {
226
227         LOG.debug("analyzeNw: allNodes size {}, allLinks size {}", allNodes.size(), allLinks.size());
228
229         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
230             // 100GE service and OTU4 service are handled at the openroadm-topology layer
231             for (Node node : allNodes) {
232                 validateNode(node);
233             }
234
235             LOG.debug("analyzeNw: allPceNodes size {}", allPceNodes.size());
236
237             if (aendPceNode == null || zendPceNode == null) {
238                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
239                 return false;
240             }
241             for (Link link : allLinks) {
242                 validateLink(link);
243             }
244             // debug prints
245             LOG.debug("analyzeNw: addLinks size {}, dropLinks size {}", addLinks.size(), dropLinks.size());
246             // debug prints
247             LOG.debug("analyzeNw: azSrgs size = {}", azSrgs.size());
248             for (NodeId srg : azSrgs) {
249                 LOG.debug("analyzeNw: A/Z Srgs SRG = {}", srg.getValue());
250             }
251             // debug prints
252             for (PceLink link : addLinks) {
253                 filteraddLinks(link);
254             }
255             for (PceLink link : dropLinks) {
256                 filterdropLinks(link);
257             }
258
259         } else {
260             // ODU4, 10GE/ODU2e or 1GE/ODU0 services are handled at openroadm-otn layer
261             OpenroadmNodeType typeOfNode = null;
262             for (Node node : allNodes) {
263                 String nodeId = node.getNodeId().getValue();
264                 if (this.anodeId.equals(nodeId) || (this.znodeId.equals(nodeId))) {
265                     typeOfNode = validateOtnNode(node, "AZ");
266                 }
267             }
268             if (typeOfNode == null) {
269                 LOG.error("analyzeNw: Error in reading nodes: A or Z do not present in the network");
270             } else if (typeOfNode == OpenroadmNodeType.MUXPDR) {
271                 LOG.debug("analyzeNw: A/Z end node are of muxponder type, no intermediate switch allowed on the path");
272             } else {
273                 LOG.debug("analyzeNw: A/Z end node are of switch type, searching for potential intermediate switch");
274                 for (Node node : allNodes) {
275                     String nodeId = node.getNodeId().getValue();
276                     if (!(this.anodeId.equals(nodeId) || (this.znodeId.equals(nodeId)))) {
277                         // A and Z node have been validated, then if A and Z end nodes are not muxponders
278                         // we allow intermediate switch on the path
279                         typeOfNode = validateOtnNode(node, "intermediate");
280                     }
281                     // else : typeOfNode is MUXPDR and we do not authorize any intermediate switch on the path
282                     // TODO : handle regens and authorize them on the path if needed
283                 }
284             }
285
286             for (Link link : allLinks) {
287                 validateLink(link);
288             }
289         }
290
291         LOG.info("analyzeNw: allPceNodes size {}, allPceLinks size {}", allPceNodes.size(), allPceLinks.size());
292
293         if ((allPceNodes.size() == 0) || (allPceLinks.size() == 0)) {
294             return false;
295         }
296
297         LOG.debug("analyzeNw: allPceNodes {}", allPceNodes.toString());
298         LOG.debug("analyzeNw: allPceLinks {}", allPceLinks.toString());
299
300         return true;
301     }
302
303     private boolean filteraddLinks(PceLink pcelink) {
304
305         NodeId nodeId = pcelink.getSourceId();
306
307         if (azSrgs.contains(nodeId)) {
308             allPceLinks.put(pcelink.getLinkId(), pcelink);
309             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
310             LOG.debug("analyzeNw: Add_LINK added to source and to allPceLinks {}", pcelink.getLinkId().toString());
311             return true;
312         }
313
314         // remove the SRG from PceNodes, as it is not directly connected to A/Z
315         allPceNodes.remove(nodeId);
316         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
317
318         return false;
319     }
320
321     private boolean filterdropLinks(PceLink pcelink) {
322
323         NodeId nodeId = pcelink.getDestId();
324
325         if (azSrgs.contains(nodeId)) {
326             allPceLinks.put(pcelink.getLinkId(), pcelink);
327             allPceNodes.get(nodeId).addOutgoingLink(pcelink);
328             LOG.debug("analyzeNw: Drop_LINK added to dest and to allPceLinks {}", pcelink.getLinkId().toString());
329             return true;
330         }
331
332         // remove the SRG from PceNodes, as it is not directly connected to A/Z
333         allPceNodes.remove(pcelink.getDestId());
334         LOG.debug("analyzeNw: SRG removed {}", nodeId.getValue());
335
336         return false;
337     }
338
339     private boolean validateLink(Link link) {
340
341         LOG.debug("validateLink: link {} ", link.toString());
342
343         if (linksToExclude.contains(link.getLinkId())) {
344             LOG.info("validateLink: Link is ignored due opposite link problem - {}", link.getLinkId().getValue());
345             return false;
346         }
347
348         NodeId sourceId = link.getSource().getSourceNode();
349         NodeId destId = link.getDestination().getDestNode();
350         PceNode source = allPceNodes.get(sourceId);
351         PceNode dest = allPceNodes.get(destId);
352
353         if (source == null) {
354             LOG.debug("validateLink: Link is ignored due source node is rejected by node validation - {}",
355                 link.getSource().getSourceNode().getValue());
356             return false;
357         }
358         if (dest == null) {
359             LOG.debug("validateLink: Link is ignored due dest node is rejected by node validation - {}",
360                 link.getDestination().getDestNode().getValue());
361             return false;
362         }
363
364         if (("100GE".equals(serviceType)) || ("OTU4".equals(serviceType))) {
365             // 100GE or OTU4 services are handled at WDM Layer
366             PceLink pcelink = new PceLink(link, source, dest);
367             if (!pcelink.isValid()) {
368                 dropOppositeLink(link);
369                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
370                 return false;
371             }
372             LinkId linkId = pcelink.getLinkId();
373             switch (validateLinkConstraints(pcelink)) {
374                 case HARD_EXCLUDE:
375                     dropOppositeLink(link);
376                     LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
377                     return false;
378                 default:
379                     break;
380             }
381             switch (pcelink.getlinkType()) {
382                 case ROADMTOROADM:
383                 case EXPRESSLINK:
384                     allPceLinks.put(linkId, pcelink);
385                     source.addOutgoingLink(pcelink);
386                     LOG.debug("validateLink: {}-LINK added to allPceLinks {}",
387                         pcelink.getlinkType(), pcelink.toString());
388                     break;
389                 case ADDLINK:
390                     pcelink.setClient(source.getRdmSrgClient(pcelink.getSourceTP().toString(), true));
391                     addLinks.add(pcelink);
392                     LOG.debug("validateLink: ADD-LINK saved  {}", pcelink.toString());
393                     break;
394                 case DROPLINK:
395                     pcelink.setClient(dest.getRdmSrgClient(pcelink.getDestTP().toString(), false));
396                     dropLinks.add(pcelink);
397                     LOG.debug("validateLink: DROP-LINK saved  {}", pcelink.toString());
398                     break;
399                 case XPONDERINPUT:
400                     // store separately all SRG links directly
401                     azSrgs.add(sourceId);
402                     // connected to A/Z
403                     if (!dest.checkTP(pcelink.getDestTP().toString())) {
404                         LOG.debug(
405                             "validateLink: XPONDER-INPUT is rejected as NW port is busy - {} ", pcelink.toString());
406                         return false;
407                     }
408                     pcelink.setClient(dest.getClient(pcelink.getDestTP().toString()));
409                     allPceLinks.put(linkId, pcelink);
410                     source.addOutgoingLink(pcelink);
411                     LOG.debug("validateLink: XPONDER-INPUT link added to allPceLinks {}", pcelink.toString());
412                     break;
413                 // does it mean XPONDER==>>SRG ?
414                 case XPONDEROUTPUT:
415                     // store separately all SRG links directly
416                     azSrgs.add(destId);
417                     // connected to A/Z
418                     if (!source.checkTP(pcelink.getSourceTP().toString())) {
419                         LOG.debug(
420                             "validateLink: XPONDER-OUTPUT is rejected as NW port is busy - {} ", pcelink.toString());
421                         return false;
422                     }
423                     pcelink.setClient(source.getClient(pcelink.getSourceTP().toString()));
424                     allPceLinks.put(linkId, pcelink);
425                     source.addOutgoingLink(pcelink);
426                     LOG.debug("validateLink: XPONDER-OUTPUT link added to allPceLinks {}", pcelink.toString());
427                     break;
428                 default:
429                     LOG.warn("validateLink: link type is not supported {}", pcelink.toString());
430             }
431             return true;
432
433         } else if (("ODU4".equals(serviceType)) || ("10GE".equals(serviceType)) || ("1GE".equals(serviceType))) {
434             // ODU4, 1GE and 10GE services relying on ODU2, ODU2e or ODU0 services are handled at OTN layer
435             PceLink pceOtnLink = new PceLink(link, source, dest);
436
437             if (!pceOtnLink.isOtnValid(link, serviceType)) {
438                 dropOppositeLink(link);
439                 LOG.error(" validateLink: Link is ignored due errors in network data or in opposite link");
440                 return false;
441             }
442
443             LinkId linkId = pceOtnLink.getLinkId();
444             switch (validateLinkConstraints(pceOtnLink)) {
445                 case HARD_EXCLUDE:
446                     dropOppositeLink(link);
447                     LOG.debug("validateLink: constraints : link is ignored == {}", linkId.getValue());
448                     return false;
449                 default:
450                     break;
451             }
452             switch (pceOtnLink.getlinkType()) {
453                 case OTNLINK:
454                     allPceLinks.put(linkId, pceOtnLink);
455                     source.addOutgoingLink(pceOtnLink);
456                     LOG.debug("validateLink: OTN-LINK added to allPceLinks {}", pceOtnLink.toString());
457                     break;
458                 default:
459                     LOG.warn("validateLink: link type is not supported {}", pceOtnLink.toString());
460             }
461             return true;
462
463         } else {
464             LOG.error(" validateLink: Unmanaged service type {}", serviceType);
465             return false;
466         }
467
468     }
469
470     private boolean validateNode(Node node) {
471         LOG.debug("validateNode: node {} ", node.toString());
472
473         // PceNode will be used in Graph algorithm
474         Node1 node1 = node.augmentation(Node1.class);
475         if (node1 == null) {
476             LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
477         }
478         OpenroadmNodeType nodeType = node1.getNodeType();
479
480         PceNode pceNode = new PceNode(node, nodeType, node.getNodeId());
481         pceNode.validateAZxponder(anodeId, znodeId);
482         pceNode.initWLlist();
483
484         if (!pceNode.isValid()) {
485             LOG.warn(" validateNode: Node is ignored");
486             return false;
487         }
488
489         switch (validateNodeConstraints(pceNode)) {
490             case HARD_EXCLUDE:
491                 return false;
492
493             default:
494                 break;
495         }
496         if ((pceNode.getSupNetworkNodeIdPceNode().equals(anodeId) && (this.aendPceNode == null))
497             && (endPceNode(nodeType, pceNode.getNodeId(), pceNode))) {
498             this.aendPceNode = pceNode;
499         }
500         if ((pceNode.getSupNetworkNodeIdPceNode().equals(znodeId) && (this.zendPceNode == null))
501             && (endPceNode(nodeType, pceNode.getNodeId(), pceNode))) {
502             this.zendPceNode = pceNode;
503         }
504
505         allPceNodes.put(pceNode.getNodeId(), pceNode);
506         LOG.debug("validateNode: node is saved {}", pceNode.getNodeId().getValue());
507         return true;
508     }
509
510     private OpenroadmNodeType validateOtnNode(Node node, String mode) {
511
512         LOG.debug("validateNode: node {} ", node.toString());
513         // PceOtnNode will be used in Graph algorithm
514         Node1 node1 = node.augmentation(Node1.class);
515         if (node1 == null) {
516             LOG.error("getNodeType: no Node1 (type) Augmentation for node: [{}]. Node is ignored", node.getNodeId());
517         }
518         OpenroadmNodeType nodeType = node1.getNodeType();
519
520         PceOtnNode pceOtnNode = new PceOtnNode(node, nodeType, node.getNodeId(), serviceType);
521         if (mode == "AZ") {
522             pceOtnNode.validateAZxponder(anodeId, znodeId);
523         } else if (mode == "intermediate") {
524             pceOtnNode.validateIntermediateSwitch();
525         } else {
526             LOG.error("validateOtnNode: unproper mode passed to the method : {} not supported", mode);
527             return null;
528         }
529
530         if (!pceOtnNode.isValid()) {
531             LOG.warn(" validateNode: Node is ignored");
532             return null;
533         }
534
535         switch (validateNodeConstraints(pceOtnNode)) {
536             case HARD_EXCLUDE:
537                 return null;
538
539             default:
540                 break;
541         }
542
543         if ((pceOtnNode.getNodeId().equals(anodeId))) {
544             this.aendPceNode = pceOtnNode;
545         }
546         if ((pceOtnNode.getNodeId().equals(znodeId))) {
547             this.zendPceNode = pceOtnNode;
548         }
549
550         allPceNodes.put(pceOtnNode.getNodeId(), pceOtnNode);
551         LOG.debug("validateNode: node is saved {}", pceOtnNode.getNodeId().getValue());
552         return nodeType;
553     }
554
555     private ConstraintTypes validateNodeConstraints(PceNode pcenode) {
556
557         if (pceHardConstraints.getExcludeSupNodes().isEmpty() && pceHardConstraints.getExcludeCLLI().isEmpty()) {
558             return ConstraintTypes.NONE;
559         }
560
561         if (pceHardConstraints.getExcludeSupNodes().contains(pcenode.getSupNetworkNodeIdPceNode())) {
562             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
563             return ConstraintTypes.HARD_EXCLUDE;
564         }
565         if (pceHardConstraints.getExcludeCLLI().contains(pcenode.getCLLI())) {
566             LOG.info("validateNodeConstraints: {}", pcenode.getNodeId().getValue());
567             return ConstraintTypes.HARD_EXCLUDE;
568         }
569
570         return ConstraintTypes.NONE;
571     }
572
573     private ConstraintTypes validateLinkConstraints(PceLink link) {
574         if (pceHardConstraints.getExcludeSRLG().isEmpty()) {
575             return ConstraintTypes.NONE;
576         }
577
578         // for now SRLG is the only constraint for link
579         if (link.getlinkType() != OpenroadmLinkType.ROADMTOROADM) {
580             return ConstraintTypes.NONE;
581         }
582
583         List<Long> constraints = new ArrayList<Long>(pceHardConstraints.getExcludeSRLG());
584         constraints.retainAll(link.getsrlgList());
585         if (!constraints.isEmpty()) {
586             LOG.info("validateLinkConstraints: {}", link.getLinkId().getValue());
587             return ConstraintTypes.HARD_EXCLUDE;
588         }
589
590         return ConstraintTypes.NONE;
591     }
592
593     private void dropOppositeLink(Link link) {
594         LinkId opplink = MapUtils.extractOppositeLink(link);
595
596         PceLink oppPceLink = allPceLinks.get(opplink);
597         if (oppPceLink != null) {
598             allPceLinks.remove(oppPceLink);
599         } else {
600             linksToExclude.add(opplink);
601         }
602     }
603
604     private Boolean endPceNode(OpenroadmNodeType openroadmNodeType, NodeId nodeId, PceNode pceNode) {
605         switch (openroadmNodeType) {
606             case SRG:
607                 pceNode.initSrgTps();
608                 this.azSrgs.add(nodeId);
609                 break;
610             case XPONDER:
611                 pceNode.initXndrTps();
612                 break;
613             default:
614                 LOG.warn("endPceNode: Node {} is not SRG or XPONDER !", nodeId);
615                 return false;
616         }
617
618         if (!pceNode.isValid()) {
619             LOG.error("validateNode : there are no availaible wavelengths in node {}", pceNode.getNodeId().getValue());
620             return false;
621         }
622         return true;
623     }
624
625     public PceNode getaendPceNode() {
626         return aendPceNode;
627     }
628
629     public PceNode getzendPceNode() {
630         return zendPceNode;
631     }
632
633     public Map<NodeId, PceNode> getAllPceNodes() {
634         return this.allPceNodes;
635     }
636
637     public Map<LinkId, PceLink> getAllPceLinks() {
638         return this.allPceLinks;
639     }
640
641     public String getServiceType() {
642         return serviceType;
643     }
644
645     public PceResult getReturnStructure() {
646         return returnStructure;
647     }
648
649     private static void printNodesInfo(Map<NodeId, PceNode> allpcenodes) {
650         Iterator<Map.Entry<NodeId, PceNode>> nodes = allpcenodes.entrySet().iterator();
651         while (nodes.hasNext()) {
652             PceNode pcenode = nodes.next().getValue();
653             List<PceLink> links = pcenode.getOutgoingLinks();
654             LOG.info("In printNodes in node {} : outgoing links {} ", pcenode.getNodeId().getValue(), links.toString());
655         }
656     }
657
658 }