Stubpce Update
[transportpce.git] / tests / stubpce / src / main / java / org / opendaylight / transportpce / stubpce / topology / SuperNodePath.java
1 /*
2  * Copyright © 2017 Orange, 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.stubpce.topology;
10
11 import com.google.common.collect.Lists;
12
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.ListIterator;
16 import java.util.SortedSet;
17 import java.util.TreeSet;
18
19 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.AToZDirection;
20 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.AToZDirectionBuilder;
21 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ZToADirection;
22 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ZToADirectionBuilder;
23 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZ;
24 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZBuilder;
25 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZKey;
26 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToA;
27 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToABuilder;
28 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToAKey;
29 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.Resource;
30 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.ResourceBuilder;
31 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.Link;
32 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.LinkBuilder;
33 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.path.description.list.PathDescriptionsBuilder;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38 /**
39  * Class to build Path between
40  * two Supernode.
41  *
42  * @author <a href="mailto:martial.coulibaly@gfi.com">Martial Coulibaly</a> on
43  *         behalf of Orange
44  */
45 public class SuperNodePath {
46     /** Logging. */
47     private static final Logger LOG = LoggerFactory.getLogger(SuperNodePath.class);
48     /** List of NodeLinkNode. */
49     private List<NodeLinkNode> paths;
50     /** Supernode topology. */
51     private Network network;
52
53     /**
54      * SuperNodePath constructor.
55      *
56      * @param network Supernode topology
57      */
58     public SuperNodePath(Network network) {
59         setPaths(new ArrayList<NodeLinkNode>());
60         this.network = network;
61     }
62
63     /**
64      * test if Supernode is an
65      * extremity of path to build.
66      *
67      * @param end extremity node Id
68      * @param supernodes Supernodes list to build path
69      * @return true if link extremity, false else
70      */
71     private Boolean endNode(String end, List<String> supernodes) {
72         Boolean result = false;
73         if (end != null && end.compareTo(" ") != 0) {
74             for (String node : supernodes) {
75                 if (node.compareTo(end) == 0) {
76                     result = true;
77                     break;
78                 }
79             }
80         }
81         return result;
82     }
83
84     /**
85      * get Supernode
86      * with supernode Id.
87      *
88      * @param nodeId supernode id to get
89      * @return SuperNode supernode gets
90      */
91     public SuperNode getSuperNode(String nodeId) {
92         SuperNode result = null;
93         if (network != null) {
94             for (SuperNode tmp : network.getSuperNodes()) {
95                 if (tmp.getSuperNodeId().compareTo(nodeId) == 0) {
96                     result = tmp;
97                     break;
98                 }
99             }
100         }
101         return result;
102     }
103
104     /**
105      *find links between
106      *two Supernodes.
107      *
108      * @param aend begin extremity
109      * @param zend end extremity
110      * @param links Roadm to Roadm links
111      * @param direct determine if link is direct or not
112      * @return String list of links name
113      */
114     private List<String> findLinks(String aend, String zend, List<String> links, boolean direct) {
115         List<String> result = new ArrayList<String>();
116         if (links.size() > 0) {
117             aend = aend.replace("Node", "ROADM");
118             zend = zend.replace("Node", "ROADM");
119             String atozlink = null;
120             String ztoalink = null;
121             for (String tmp : links) {
122                 if (tmp.contains(aend)
123                         && tmp.contains(zend)) {
124                     LOG.info("direct path found for : " + aend + " / " + zend);
125                     if (tmp.startsWith(aend)) {
126                         atozlink = tmp;
127                     }
128                     if (tmp.startsWith(zend)) {
129                         ztoalink = tmp;
130                     }
131                     if (atozlink != null && ztoalink != null) {
132                         result.add(atozlink.concat("/").concat(ztoalink));
133                         atozlink = null;
134                         ztoalink = null;
135                     }
136                 }
137             }
138         } else {
139             LOG.info("no roadm-to-roadm links !");
140         }
141         return result;
142     }
143
144     /**
145      *find next Supernode hop.
146      *
147      * @param link roadm to roadm link
148      * @param aend begin supernode
149      * @param node list of supernode id
150      * @return String  supernodeId next hop
151      */
152     private String findHop(String link, String aend, List<String> node) {
153         String result = null;
154         aend = aend.replace("Node", "ROADM");
155         for (String tmp : node) {
156             tmp = tmp.replace("Node", "ROADM");
157             if (tmp.compareTo(aend) != 0) {
158                 if (link.contains(aend) && link.contains(tmp)) {
159                     LOG.info("hop : " + tmp);
160                     result = tmp;
161                 }
162             }
163         }
164         return result;
165     }
166
167     /**
168      *get all Supernode in
169      *topology.
170      *
171      * @return String list of Supernode Id
172      */
173     private List<String> getSuperNodeId() {
174         List<String> result = new ArrayList<String>();
175         if (network.getSuperNodes().size() > 0) {
176             for (SuperNode tmp : network.getSuperNodes()) {
177                 result.add(tmp.getSuperNodeId());
178             }
179         }
180         return result;
181     }
182
183     /**
184      * get all roadm to roadm
185      * links in topology.
186      *
187      * @return String list of roadm to roadm links
188      */
189     private List<String> getRoadmLinks() {
190         List<String> result = new ArrayList<String>();
191         if (network.getRoadmToroadm().getLinks().size() > 0) {
192             for (String tmp : network.getRoadmToroadm().getLinks()) {
193                 result.add(tmp);
194             }
195         }
196         return result;
197     }
198
199     /**
200      * create NodeLinkNode
201      * structure.
202      *
203      * @param links String list of roadm to roadm links
204      * @param aend beginning Supernode
205      * @param zend ending Supernode
206      * @param direct determine if link is direct or not
207      */
208     private void fill(List<String> links,String aend, String zend, boolean direct) {
209         String term = "indirect";
210         if (direct) {
211             term = "direct";
212         }
213         if (!links.isEmpty()) {
214             List<String> atoz = new ArrayList<String>();
215             List<String> ztoa = new ArrayList<String>();
216             for (String tmp : links) {
217                 String [] split = tmp.split("/");
218                 if (split.length == 2) {
219                     atoz.add(split[0]);
220                     ztoa.add(split[1]);
221                 }
222             }
223             if (!atoz.isEmpty() && atoz.size() == ztoa.size()) {
224                 NodeLinkNode node = new NodeLinkNode(aend, zend, atoz,ztoa,direct);
225                 paths.add(node);
226             }
227
228         } else {
229             LOG.info(term + " links not found !");
230         }
231     }
232
233     /**
234      * launch SupernodePath process
235      * to build NodeLinkNode.
236      *
237      * @param aend beginning extremity path
238      * @param zend ending extremity path
239      */
240     public void run(String aend, String zend) {
241         if (network != null) {
242             List<String> supernodes = getSuperNodeId();
243             List<String> roadmLinks = getRoadmLinks();
244             if (aend != null && zend != null) {
245                 int size = supernodes.size();
246                 String hop = null;
247                 List<String> links = null;
248                 if (size > 0) {
249                     if (endNode(aend, supernodes) && endNode(zend, supernodes)) {
250                         LOG.info("Getting direct links ...");
251                         links = new ArrayList<String>();
252                         links = findLinks(aend,zend,roadmLinks,true);
253                         fill(links, aend, zend, true);
254                         LOG.info("Getting indirect links ..");
255                         links = new ArrayList<String>();
256                         for (String tmp : roadmLinks) {
257                             hop = findHop(tmp, aend, supernodes);
258                             if (hop != null) {
259                                 if (hop.compareTo(zend.replace("Node", "ROADM")) != 0) {
260                                     LOG.info("next hop found : " + hop);
261                                     links.addAll(findLinks(aend,hop,roadmLinks,false));
262                                     links.addAll(findLinks(hop,zend,roadmLinks,false));
263                                 } else {
264                                     break;
265                                 }
266                             }
267                         }
268                         fill(links, aend, zend, false);
269                     } else {
270                         LOG.info("aend or/and zend not exists !");
271                     }
272                 }
273             } else {
274                 LOG.info("aend or/and is null !");
275             }
276         } else {
277             LOG.info("network is null !!");
278         }
279     }
280
281     /**
282      * modify all AToZ Id
283      * in AToZ List containing
284      * in AToZdirection.
285      *
286      * @param order beginning order
287      * @param atozDirection AToZdirection List
288      * @return AToZdirection List
289      */
290     public List<AToZDirection> modifyOrder(int order, List<AToZDirection> atozDirection) {
291         List<AToZDirection> result = new ArrayList<AToZDirection>();
292         for (AToZDirection tmp : atozDirection) {
293             List<AToZ> atozList = tmp.getAToZ();
294             int size = atozList.size();
295             if (size > 0) {
296                 for (ListIterator<AToZ> it = atozList.listIterator(); it.hasNext();) {
297                     AToZ atoz = it.next();
298                     org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription
299                         .rev170426.pce.resource.resource.Resource res = atoz.getResource().getResource();
300                     int tmpkey = order + Integer.parseInt(atoz.getKey().getId());
301                     AToZKey atozKey = new AToZKey(Integer.toString(tmpkey));
302                     org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
303                         .pathdescription.rev170426.pce.resource.Resource resource = new ResourceBuilder()
304                         .setResource(res).build();
305                     AToZ hop = new AToZBuilder().setId(atozKey.getId()).setKey(atozKey).setResource(resource).build();
306                     it.remove();
307                     it.add(hop);
308                     tmpkey++;
309                 }
310                 result.add(tmp);
311             }
312         }
313         return result;
314     }
315
316     /**
317      * merge two AToZdirection List.
318      *
319      * @param cleanInterA first AToZdirection List
320      * @param cleanInterZ second AToZdirection List
321      * @param first boolean to determine if it is the first time merge is done
322      * @return AToZDirection List
323      */
324     public List<AToZDirection> merge(List<AToZDirection> cleanInterA, List<AToZDirection> cleanInterZ,
325             boolean first) {
326         List<AToZDirection> result = new ArrayList<AToZDirection>();
327         if (!cleanInterA.isEmpty()) {
328             int order  = cleanInterA.get(0).getAToZ().size();
329             if (order > 0) {
330                 List<AToZDirection> modify = modifyOrder(order, cleanInterZ);
331                 if (!modify.isEmpty()) {
332                     for (AToZDirection tmp : cleanInterA) {
333                         List<AToZ> atozList = new ArrayList<AToZ>(tmp.getAToZ());
334                         for (AToZDirection add : modify) {
335                             ListIterator<AToZ> it = atozList.listIterator();
336                             /** on va a la fin de la liste */
337                             while (it.hasNext()) {
338                                 it.next();
339                             }
340                             List<AToZ> addList = add.getAToZ();
341                             for (AToZ atoz : addList) {
342                                 it.add(atoz);
343                             }
344                             AToZDirectionBuilder newDirection = new AToZDirectionBuilder();
345                             newDirection.setRate((long) 100).setAToZWavelengthNumber((long) 200).setAToZ(atozList);
346                             result.add(newDirection.build());
347                             atozList = new ArrayList<AToZ>(tmp.getAToZ());
348                         }
349                     }
350                 } else {
351                     LOG.info("modify List is empty ! ");
352                 }
353             } else {
354                 LOG.info("order is not superior to 0");
355             }
356         } else {
357             if (first && !cleanInterZ.isEmpty()) {
358                 LOG.info("first merge so result is a copy of second AToZDirection List !");
359                 result = new ArrayList<AToZDirection>(cleanInterZ);
360             } else {
361                 LOG.info("cleanInterA is empty !");
362             }
363         }
364         return result;
365     }
366
367     /**
368      * gets Degree number
369      * for roadm links.
370      *
371      * @param atozLink atoz roadm link
372      * @param ztoaLink ztoa roadm link
373      * @return String list of degree
374      */
375     public List<String> getDeg(String atozLink, String ztoaLink) {
376         List<String> result = new ArrayList<String>();
377         if (atozLink != null && ztoaLink != null) {
378             String [] split = atozLink.split("-", 4);
379             if (split.length == 4) {
380                 result = Lists.newArrayList(split[1],split[3]);
381             }
382         } else {
383             LOG.info("atozlink and/or ztoalink is null !");
384         }
385         return result;
386     }
387
388     /**
389      * reverse link name
390      * (ROADMA-DEG1-ROADMZ-DEG2
391      * to
392      * ROADMZ-DEG2-ROADMA-DEG1).
393      *
394      * @param linkId Link name
395      * @return String link name reversed
396      */
397     public String reverseLinkId(String linkId) {
398         StringBuilder builder = new StringBuilder();
399         String [] split = linkId.split("-");
400         int size = split.length;
401         switch (size) {
402             case 3:
403                 if (linkId.contains("XPDR")) {
404                     if (linkId.startsWith("XPDR")) {
405                         builder.append(split[1]).append("-")
406                         .append(split[2]).append("-")
407                         .append(split[0]);
408                     } else {
409                         builder.append(split[2]).append("-")
410                         .append(split[0]).append("-")
411                         .append(split[1]);
412                     }
413                 }
414                 break;
415
416             case 4:
417                 builder.append(split[2]).append("-")
418                 .append(split[3]).append("-")
419                 .append(split[0]).append("-")
420                 .append(split[1]);
421                 break;
422
423             default:
424                 break;
425         }
426         return builder.toString();
427     }
428
429     /**
430      * convert AToAdirection to
431      * ZToAdirection.
432      *
433      * @param atozDirection AToZdirection to convert
434      * @return ZToAdirection
435      */
436     public ZToADirection convertToZtoaDirection(AToZDirection atozDirection) {
437         ZToADirectionBuilder ztoaDirection = new ZToADirectionBuilder();
438         if (atozDirection != null) {
439             List<AToZ> atozList = atozDirection.getAToZ();
440             List<ZToA> ztoaList = new ArrayList<ZToA>();
441             if (!atozList.isEmpty()) {
442                 List<AToZ> reverse = Lists.reverse(atozList);
443                 /** Building path. */
444                 ZToAKey ztoaKey = null;
445                 Resource resource = null;
446                 org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription
447                     .rev170426.pce.resource.resource.Resource resLink = null;
448                 ZToA hop = null;
449                 int odr = 0;
450                 for (AToZ atoz : reverse) {
451                     ztoaKey = new ZToAKey(Integer.toString(odr));
452                     resLink = atoz.getResource().getResource();
453                     if (resLink != null) {
454                         if (resLink instanceof Link) {
455                             Link link = (Link) resLink;
456                             String newLinkId = reverseLinkId(link.getLinkId());
457                             if (newLinkId != null) {
458                                 resource = new ResourceBuilder().setResource(
459                                         new LinkBuilder()
460                                         .setLinkId(newLinkId)
461                                         .build()
462                                         ).build();
463                             }
464
465                         } else {
466                             resource = new ResourceBuilder().setResource(resLink).build();
467                         }
468                     }
469                     if (resource != null) {
470                         hop = new ZToABuilder()
471                                 .setKey(ztoaKey)
472                                 .setResource(resource)
473                                 .build();
474                         ztoaList.add(hop);
475                         odr++;
476                     } else {
477                         LOG.info("resource is null ");
478                     }
479                 }
480                 if (!ztoaList.isEmpty()) {
481                     ztoaDirection.setRate((long) 100).setZToAWavelengthNumber((long) 200).setZToA(ztoaList);
482                 } else {
483                     LOG.info("ztoaList is empty !");
484                 }
485             }
486         }
487         return ztoaDirection.build();
488     }
489
490     /**
491      *build Pathdescritions ordered List
492      *to be loaded in Pathdescriptions
493      *datastore.
494      *
495      * @param atozDirection AToZdirection List
496      * @param term direct ou indirect
497      * @return PathDescriptionsOrdered List
498      */
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);
510                 }
511             }
512             if (!ztoadirList.isEmpty() && size == ztoadirList.size()) {
513                 LOG.info("building PathDescriptions ...");
514                 int index = 1;
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(pathDescr.build().toString());
522                     result.add(new PathDescriptionsOrdered(pathDescr.build(),index));
523                     index++;
524                 }
525             } else {
526                 LOG.info("Something wrong happen during atodir conversion...");
527             }
528
529         } else {
530             LOG.info("atozDirection is empty");
531         }
532         return result;
533     }
534
535     /**
536      * gets link extremity.
537      *
538      * @param link link
539      * @return Supernode List of extremities
540      */
541     public List<SuperNode> getSuperNodeEndLink(String link) {
542         List<SuperNode> result = new ArrayList<SuperNode>();
543         if (link != null) {
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 : " + aend + " and " + zend);
550                     SuperNode aendSp = getSuperNode(aend);
551                     SuperNode zendSp = getSuperNode(zend);
552                     if (aendSp != null && zendSp != null) {
553                         result.add(aendSp);
554                         result.add(zendSp);
555                     }
556                 }
557             }
558         }
559         return result;
560     }
561
562     /**
563      * build all direct paths.
564      *
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
569      */
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));
601                             } else {
602                                 LOG.info("cleanInterA ad/or cleanInterZ is empty !");
603                             }
604                         } else {
605                             LOG.info("deg size is not correct, must be 2 ! ");
606                         }
607                     } else {
608                         LOG.info("atozlink and / or ztoalink is null");
609                     }
610                 }
611             }
612
613         } else {
614             LOG.info("List of direct path is empty !");
615         }
616         if (!atozdirectionPaths.isEmpty()) {
617             LOG.info("result size : " + result.size());
618             result = buildPathDescription(atozdirectionPaths,aend.concat("To").concat(zend).concat("_direct_"));
619         } else {
620             LOG.info("result is empty");
621         }
622         return result;
623     }
624
625     /**
626      * build all indirect paths.
627      *
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
632      */
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;
646                     if (size == 2) {
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());
652                             int loop = 0;
653                             while (loop < 2) {
654                                 List<SuperNode> hop = getSuperNodeEndLink(atozLinks.get(loop));
655                                 if (!hop.isEmpty() && hop.size() == 2) {
656                                     aendSp = hop.get(0);
657                                     zendSp = hop.get(1);
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);
680                                         }
681                                         if (!cleanInterA.isEmpty() && !cleanInterZ.isEmpty()) {
682                                             atozdirectionPaths = merge(atozdirectionPaths,cleanInterA,first);
683                                             atozdirectionPaths = merge(atozdirectionPaths, cleanInterZ,false);
684                                             first = false;
685                                         } else {
686                                             LOG.info("cleanInterA ad/or cleanInterZ is empty !");
687                                             break;
688                                         }
689                                     }
690                                 } else {
691                                     LOG.info("Hop list is empty");
692                                 }
693                                 loop++;
694                             }
695                         }
696                     } else {
697                         LOG.info("Link size is not supported , must be two !");
698                     }
699                 }
700             }
701         } else {
702             LOG.info("List of indirect path is empty !");
703         }
704         if (!atozdirectionPaths.isEmpty()) {
705             LOG.info("result size : " + result.size());
706             result = buildPathDescription(atozdirectionPaths,aend.concat("To").concat(zend).concat("_indirect_"));
707         } else {
708             LOG.info("result is empty");
709         }
710         return result;
711     }
712
713     public static void main(String[] args) {
714         Topology topo = new Topology();
715         topo.start();
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());
722     }
723
724     public List<NodeLinkNode> getPaths() {
725         return paths;
726     }
727
728     public void setPaths(List<NodeLinkNode> paths) {
729         this.paths = paths;
730     }
731 }