2 * Copyright © 2017 Orange, Inc. and others. All rights reserved.
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
9 package org.opendaylight.transportpce.stubpce.topology;
11 import com.google.common.collect.Lists;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.ListIterator;
15 import java.util.SortedSet;
16 import java.util.TreeSet;
17 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.stubpce.rev170426.path.description.list.PathDescriptionsBuilder;
18 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.AToZDirection;
19 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.AToZDirectionBuilder;
20 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ZToADirection;
21 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ZToADirectionBuilder;
22 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZ;
23 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZBuilder;
24 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZKey;
25 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToA;
26 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToABuilder;
27 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToAKey;
28 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.Resource;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.ResourceBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.Link;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.LinkBuilder;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.link.LinkIdentifierBuilder;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
38 * Class to build Path between
41 * @author <a href="mailto:martial.coulibaly@gfi.com">Martial Coulibaly</a> on
44 public class SuperNodePath {
46 private static final Logger LOG = LoggerFactory.getLogger(SuperNodePath.class);
47 /** List of NodeLinkNode. */
48 private List<NodeLinkNode> paths;
49 /** Supernode topology. */
50 private Network network;
53 * SuperNodePath constructor.
55 * @param network Supernode topology
57 public SuperNodePath(Network network) {
58 setPaths(new ArrayList<NodeLinkNode>());
59 this.network = network;
63 * test if Supernode is an
64 * extremity of path to build.
66 * @param end extremity node Id
67 * @param supernodes Supernodes list to build path
68 * @return true if link extremity, false else
70 private Boolean endNode(String end, List<String> supernodes) {
71 Boolean result = false;
72 if ((end != null) && (end.compareTo(" ") != 0)) {
73 for (String node : supernodes) {
74 if (node.compareTo(end) == 0) {
87 * @param nodeId supernode id to get
88 * @return SuperNode supernode gets
90 public SuperNode getSuperNode(String nodeId) {
91 SuperNode result = null;
92 if (this.network != null) {
93 for (SuperNode tmp : this.network.getSuperNodes()) {
94 if (tmp.getSuperNodeId().compareTo(nodeId) == 0) {
107 * @param aend begin extremity
108 * @param zend end extremity
109 * @param links Roadm to Roadm links
110 * @param direct determine if link is direct or not
111 * @return String list of links name
113 private List<String> findLinks(String aend, String zend, List<String> links, boolean direct) {
114 List<String> result = new ArrayList<String>();
115 if (links.size() > 0) {
116 aend = aend.replace("Node", "ROADM");
117 zend = zend.replace("Node", "ROADM");
118 String atozlink = null;
119 String ztoalink = null;
120 for (String tmp : links) {
121 if (tmp.contains(aend)
122 && tmp.contains(zend)) {
123 LOG.info("direct path found for : {} / {}", aend, zend);
124 if (tmp.startsWith(aend)) {
127 if (tmp.startsWith(zend)) {
130 if ((atozlink != null) && (ztoalink != null)) {
131 result.add(atozlink.concat("/").concat(ztoalink));
138 LOG.info("no roadm-to-roadm links !");
144 *find next Supernode hop.
146 * @param link roadm to roadm link
147 * @param aend begin supernode
148 * @param node list of supernode id
149 * @return String supernodeId next hop
151 private String findHop(String link, String aend, List<String> node) {
152 String result = null;
153 aend = aend.replace("Node", "ROADM");
154 for (String tmp : node) {
155 tmp = tmp.replace("Node", "ROADM");
156 if (tmp.compareTo(aend) != 0) {
157 if (link.contains(aend) && link.contains(tmp)) {
158 LOG.info("hop : {}", tmp);
167 *get all Supernode in
170 * @return String list of Supernode Id
172 private List<String> getSuperNodeId() {
173 List<String> result = new ArrayList<String>();
174 if (this.network.getSuperNodes().size() > 0) {
175 for (SuperNode tmp : this.network.getSuperNodes()) {
176 result.add(tmp.getSuperNodeId());
183 * get all roadm to roadm
186 * @return String list of roadm to roadm links
188 private List<String> getRoadmLinks() {
189 List<String> result = new ArrayList<String>();
190 if (this.network.getRoadmToroadm().getLinks().size() > 0) {
191 for (String tmp : this.network.getRoadmToroadm().getLinks()) {
199 * create NodeLinkNode
202 * @param links String list of roadm to roadm links
203 * @param aend beginning Supernode
204 * @param zend ending Supernode
205 * @param direct determine if link is direct or not
207 private void fill(List<String> links,String aend, String zend, boolean direct) {
208 String term = "indirect";
212 if (!links.isEmpty()) {
213 List<String> atoz = new ArrayList<String>();
214 List<String> ztoa = new ArrayList<String>();
215 for (String tmp : links) {
216 String [] split = tmp.split("/");
217 if (split.length == 2) {
222 if (!atoz.isEmpty() && (atoz.size() == ztoa.size())) {
223 NodeLinkNode node = new NodeLinkNode(aend, zend, atoz,ztoa,direct);
224 this.paths.add(node);
228 LOG.info("{} links not found !", term);
233 * launch SupernodePath process
234 * to build NodeLinkNode.
236 * @param aend beginning extremity path
237 * @param zend ending extremity path
239 public void run(String aend, String zend) {
240 if (this.network != null) {
241 List<String> supernodes = getSuperNodeId();
242 List<String> roadmLinks = getRoadmLinks();
243 if ((aend != null) && (zend != null)) {
244 int size = supernodes.size();
246 List<String> links = null;
248 if (endNode(aend, supernodes) && endNode(zend, supernodes)) {
249 LOG.info("Getting direct links ...");
250 links = new ArrayList<String>();
251 links = findLinks(aend,zend,roadmLinks,true);
252 fill(links, aend, zend, true);
253 LOG.info("Getting indirect links ..");
254 links = new ArrayList<String>();
255 for (String tmp : roadmLinks) {
256 hop = findHop(tmp, aend, supernodes);
258 if (hop.compareTo(zend.replace("Node", "ROADM")) != 0) {
259 LOG.info("next hop found : {}", hop);
260 links.addAll(findLinks(aend,hop,roadmLinks,false));
261 links.addAll(findLinks(hop,zend,roadmLinks,false));
267 fill(links, aend, zend, false);
269 LOG.info("aend or/and zend not exists !");
273 LOG.info("aend or/and is null !");
276 LOG.info("network is null !!");
282 * in AToZ List containing
285 * @param order beginning order
286 * @param atozDirection AToZdirection List
287 * @return AToZdirection List
289 public List<AToZDirection> modifyOrder(int order, List<AToZDirection> atozDirection) {
290 List<AToZDirection> result = new ArrayList<AToZDirection>();
291 for (AToZDirection tmp : atozDirection) {
292 List<AToZ> atozList = tmp.getAToZ();
293 int size = atozList.size();
295 for (ListIterator<AToZ> it = atozList.listIterator(); it.hasNext();) {
296 AToZ atoz = it.next();
297 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription
298 .rev170426.pce.resource.resource.Resource res = atoz.getResource().getResource();
299 int tmpkey = order + Integer.parseInt(atoz.key().getId());
300 AToZKey atozKey = new AToZKey(Integer.toString(tmpkey));
301 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
302 .pathdescription.rev170426.pce.resource.Resource resource = new ResourceBuilder()
303 .setResource(res).build();
304 AToZ hop = new AToZBuilder().setId(atozKey.getId()).withKey(atozKey).setResource(resource).build();
316 * merge two AToZdirection List.
318 * @param cleanInterA first AToZdirection List
319 * @param cleanInterZ second AToZdirection List
320 * @param first boolean to determine if it is the first time merge is done
321 * @return AToZDirection List
323 public List<AToZDirection> merge(List<AToZDirection> cleanInterA, List<AToZDirection> cleanInterZ,
325 List<AToZDirection> result = new ArrayList<AToZDirection>();
326 if (!cleanInterA.isEmpty()) {
327 int order = cleanInterA.get(0).getAToZ().size();
329 List<AToZDirection> modify = modifyOrder(order, cleanInterZ);
330 if (!modify.isEmpty()) {
331 for (AToZDirection tmp : cleanInterA) {
332 List<AToZ> atozList = new ArrayList<AToZ>(tmp.getAToZ());
333 for (AToZDirection add : modify) {
334 ListIterator<AToZ> it = atozList.listIterator();
335 /** on va a la fin de la liste */
336 while (it.hasNext()) {
339 List<AToZ> addList = add.getAToZ();
340 for (AToZ atoz : addList) {
343 AToZDirectionBuilder newDirection = new AToZDirectionBuilder();
344 newDirection.setRate((long) 100).setAToZWavelengthNumber((long) 200).setAToZ(atozList);
345 result.add(newDirection.build());
346 atozList = new ArrayList<AToZ>(tmp.getAToZ());
350 LOG.info("modify List is empty ! ");
353 LOG.info("order is not superior to 0");
356 if (first && !cleanInterZ.isEmpty()) {
357 LOG.info("first merge so result is a copy of second AToZDirection List !");
358 result = new ArrayList<AToZDirection>(cleanInterZ);
360 LOG.info("cleanInterA is empty !");
370 * @param atozLink atoz roadm link
371 * @param ztoaLink ztoa roadm link
372 * @return String list of degree
374 public List<String> getDeg(String atozLink, String ztoaLink) {
375 List<String> result = new ArrayList<String>();
376 if ((atozLink != null) && (ztoaLink != null)) {
377 String [] split = atozLink.split("-", 4);
378 if (split.length == 4) {
379 result = Lists.newArrayList(split[1],split[3]);
382 LOG.info("atozlink and/or ztoalink is null !");
389 * (ROADMA-DEG1-ROADMZ-DEG2
391 * ROADMZ-DEG2-ROADMA-DEG1).
393 * @param linkId Link name
394 * @return String link name reversed
396 public String reverseLinkId(String linkId) {
397 StringBuilder builder = new StringBuilder();
398 String [] split = linkId.split("-");
399 int size = split.length;
402 if (linkId.contains("XPDR")) {
403 if (linkId.startsWith("XPDR")) {
404 builder.append(split[1]).append("-")
405 .append(split[2]).append("-")
408 builder.append(split[2]).append("-")
409 .append(split[0]).append("-")
416 builder.append(split[2]).append("-")
417 .append(split[3]).append("-")
418 .append(split[0]).append("-")
425 return builder.toString();
429 * convert AToAdirection to
432 * @param atozDirection AToZdirection to convert
433 * @return ZToAdirection
435 public ZToADirection convertToZtoaDirection(AToZDirection atozDirection) {
436 ZToADirectionBuilder ztoaDirection = new ZToADirectionBuilder();
437 if (atozDirection != null) {
438 List<AToZ> atozList = atozDirection.getAToZ();
439 List<ZToA> ztoaList = new ArrayList<ZToA>();
440 if (!atozList.isEmpty()) {
441 List<AToZ> reverse = Lists.reverse(atozList);
442 /** Building path. */
443 ZToAKey ztoaKey = null;
444 Resource resource = null;
445 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription
446 .rev170426.pce.resource.resource.Resource resLink = null;
449 for (AToZ atoz : reverse) {
450 ztoaKey = new ZToAKey(Integer.toString(odr));
451 resLink = atoz.getResource().getResource();
452 if (resLink != null) {
453 if (resLink instanceof Link) {
454 Link link = (Link) resLink;
455 String newLinkId = reverseLinkId(link.getLinkIdentifier().getLinkId());
456 if (newLinkId != null) {
457 resource = new ResourceBuilder().setResource(new LinkBuilder()
458 .setLinkIdentifier(new LinkIdentifierBuilder()
459 .setLinkId(newLinkId)
466 resource = new ResourceBuilder().setResource(resLink).build();
469 if (resource != null) {
470 hop = new ZToABuilder()
472 .setResource(resource)
477 LOG.info("resource is null ");
480 if (!ztoaList.isEmpty()) {
481 ztoaDirection.setRate((long) 100).setZToAWavelengthNumber((long) 200).setZToA(ztoaList);
483 LOG.info("ztoaList is empty !");
487 return ztoaDirection.build();
491 *build Pathdescritions ordered List
492 *to be loaded in Pathdescriptions
495 * @param atozDirection AToZdirection List
496 * @param term direct ou indirect
497 * @return PathDescriptionsOrdered List
499 private SortedSet<PathDescriptionsOrdered> buildPathDescription(List<AToZDirection> atozDirection, String term) {
500 SortedSet<PathDescriptionsOrdered> result = new TreeSet<PathDescriptionsOrdered>();
501 PathDescriptionsBuilder pathDescr = new PathDescriptionsBuilder();
502 int size = atozDirection.size();
503 if (!atozDirection.isEmpty()) {
504 LOG.info("result list AToZDirection size : {}", atozDirection.size());
505 List<ZToADirection> ztoadirList = new ArrayList<ZToADirection>();
506 for (AToZDirection atozdir : atozDirection) {
507 ZToADirection ztodir = convertToZtoaDirection(atozdir);
508 if (ztodir != null) {
509 ztoadirList.add(ztodir);
512 if (!ztoadirList.isEmpty() && (size == ztoadirList.size())) {
513 LOG.info("building PathDescriptions ...");
515 String pathName = null;
516 for (int indexPath = 0 ; indexPath < size ; indexPath++) {
517 pathName = term.concat(Integer.toString(index));
518 LOG.info("pathName : {}", pathName);
519 pathDescr.setAToZDirection(atozDirection.get(indexPath))
520 .setZToADirection(ztoadirList.get(indexPath)).setPathName(pathName);
521 LOG.info("pathdesciption : {}", pathDescr.build().toString());
522 result.add(new PathDescriptionsOrdered(pathDescr.build(),index));
526 LOG.info("Something wrong happen during atodir conversion...");
530 LOG.info("atozDirection is empty");
536 * gets link extremity.
539 * @return Supernode List of extremities
541 public List<SuperNode> getSuperNodeEndLink(String link) {
542 List<SuperNode> result = new ArrayList<SuperNode>();
544 String [] split = link.split("-");
545 if (split.length == 4) {
546 String aend = split[0].replaceAll("ROADM", "Node");
547 String zend = split[2].replaceAll("ROADM", "Node");
548 if ((aend != null) && (zend != null)) {
549 LOG.info("getting super node for : {} and {}", aend, zend);
550 SuperNode aendSp = getSuperNode(aend);
551 SuperNode zendSp = getSuperNode(zend);
552 if ((aendSp != null) && (zendSp != null)) {
563 * build all direct paths.
565 * @param aend beginning extremity path
566 * @param zend ending extremity path
567 * @param paths NodeLinkNode list paths
568 * @return PathDescriptionsOrdered List of direct paths
570 public SortedSet<PathDescriptionsOrdered> getDirectPathDesc(String aend, String zend,List<NodeLinkNode> paths) {
571 List<AToZDirection> atozdirectionPaths = new ArrayList<AToZDirection>();
572 SortedSet<PathDescriptionsOrdered> result = new TreeSet<PathDescriptionsOrdered>();
573 SuperNode aendSp = getSuperNode(aend);
574 SuperNode zendSp = getSuperNode(zend);
575 if (!paths.isEmpty()) {
576 for (NodeLinkNode tmp : paths) {
577 if (tmp.getDirect()) {
578 LOG.info("Direct NodeLinkNode : {}", tmp.toString());
579 String atozLink = null;
580 String ztoaLink = null;
581 atozLink = tmp.getAtozLink().get(0);
582 ztoaLink = tmp.getZtoaLink().get(0);
583 if ((atozLink != null) && (ztoaLink != null)) {
584 LOG.info("atozlink : {}", atozLink);
585 LOG.info("ztoalink : {}", ztoaLink);
586 InterNodePath interAend = new InterNodePath(aendSp);
587 interAend.buildPath(zend);
588 InterNodePath interZend = new InterNodePath(zendSp);
589 interZend.buildPath(zend);
590 List<String> deg = getDeg(atozLink,ztoaLink);
591 LOG.info("deg : {}", deg.toString());
592 if (deg.size() == 2) {
593 List<AToZDirection> cleanInterA =
594 interAend.replaceOrRemoveAToZDirectionEndLink(deg.get(0),"",atozLink,
595 interAend.getAtoz(),false);
596 List<AToZDirection> cleanInterZ =
597 interZend.replaceOrRemoveAToZDirectionEndLink("TAIL-LINKS",deg.get(1),"",
598 interZend.getAtoz(),true);
599 if (!cleanInterA.isEmpty() && !cleanInterZ.isEmpty()) {
600 atozdirectionPaths.addAll(merge(cleanInterA,cleanInterZ,false));
602 LOG.info("cleanInterA ad/or cleanInterZ is empty !");
605 LOG.info("deg size is not correct, must be 2 ! ");
608 LOG.info("atozlink and / or ztoalink is null");
614 LOG.info("List of direct path is empty !");
616 if (!atozdirectionPaths.isEmpty()) {
617 LOG.info("result size : {}", result.size());
618 result = buildPathDescription(atozdirectionPaths,aend.concat("To").concat(zend).concat("_direct_"));
620 LOG.info("result is empty");
626 * build all indirect paths.
628 * @param aend beginning extremity path
629 * @param zend ending extremity path
630 * @param paths NodeLinkNode list paths
631 * @return PathDescriptionsOrdered List of indirect paths
633 public SortedSet<PathDescriptionsOrdered> getIndirectPathDesc(String aend, String zend,List<NodeLinkNode> paths) {
634 List<AToZDirection> atozdirectionPaths = new ArrayList<AToZDirection>();
635 SortedSet<PathDescriptionsOrdered> result = new TreeSet<PathDescriptionsOrdered>();
636 SuperNode aendSp = getSuperNode(aend);
637 SuperNode zendSp = getSuperNode(zend);
638 if (!paths.isEmpty()) {
639 for (NodeLinkNode tmp : paths) {
640 if (!tmp.getDirect()) {
641 LOG.info("Indirect NodeLinkNode : {}", tmp.toString());
642 int size = tmp.getAtozLink().size();
643 /** must be two for now just one hop. */
644 LOG.info("number of links : {}", size);
645 boolean first = true;
647 List<String> atozLinks = tmp.getAtozLink();
648 List<String> ztoaLinks = tmp.getZtoaLink();
649 if (!atozLinks.isEmpty() && !ztoaLinks.isEmpty()) {
650 LOG.info("atozlink : {}", atozLinks.toString());
651 LOG.info("ztoalink : {}", ztoaLinks.toString());
654 List<SuperNode> hop = getSuperNodeEndLink(atozLinks.get(loop));
655 if (!hop.isEmpty() && (hop.size() == 2)) {
658 InterNodePath interAend = new InterNodePath(aendSp);
659 interAend.buildPath(zend);
660 LOG.info("interAend : {}", interAend.getAtoz().toString());
661 InterNodePath interZend = new InterNodePath(zendSp);
662 interZend.buildPath(zend);
663 LOG.info("interZend : {}", interZend.getAtoz().toString());
664 List<String> deg1 = getDeg(atozLinks.get(loop),ztoaLinks.get(loop));
665 LOG.info("deg1 : {}", deg1.toString());
666 if (!deg1.isEmpty() && (deg1.size() == 2)) {
667 List<AToZDirection> cleanInterA = null;
668 List<AToZDirection> cleanInterZ = null;
669 if (zendSp.getSuperNodeId().compareTo(zend) == 0) {
670 cleanInterA = interAend.replaceOrRemoveAToZDirectionEndLink(deg1.get(0),
671 "",atozLinks.get(loop),interAend.getAtoz(),false);
672 LOG.info("next hop is zend");
673 cleanInterZ = interZend.replaceOrRemoveAToZDirectionEndLink("TAIL-LINKS",
674 deg1.get(1),"",interZend.getAtoz(),true);
675 } else if (loop < 1) {
676 cleanInterA = interAend.replaceOrRemoveAToZDirectionEndLink(deg1.get(0),
677 "",atozLinks.get(loop),interAend.getAtoz(),false);
678 cleanInterZ = interZend.getAToZDirectionEndBy(deg1.get(1),
679 interZend.getAtoz(), 1);
681 if (!cleanInterA.isEmpty() && !cleanInterZ.isEmpty()) {
682 atozdirectionPaths = merge(atozdirectionPaths,cleanInterA,first);
683 atozdirectionPaths = merge(atozdirectionPaths, cleanInterZ,false);
686 LOG.info("cleanInterA ad/or cleanInterZ is empty !");
691 LOG.info("Hop list is empty");
697 LOG.info("Link size is not supported , must be two !");
702 LOG.info("List of indirect path is empty !");
704 if (!atozdirectionPaths.isEmpty()) {
705 LOG.info("result size : {}", result.size());
706 result = buildPathDescription(atozdirectionPaths,aend.concat("To").concat(zend).concat("_indirect_"));
708 LOG.info("result is empty");
713 public static void main(String[] args) {
714 Topology topo = new Topology();
716 SuperNodePath path = new SuperNodePath(topo.getNetwork());
717 String aend = "NodeA";
718 String zend = "NodeZ";
719 path.run(aend, zend);
720 path.getDirectPathDesc(aend, zend, path.getPaths());
721 path.getIndirectPathDesc(aend, zend, path.getPaths());
724 public List<NodeLinkNode> getPaths() {
728 public void setPaths(List<NodeLinkNode> paths) {