public PathSet forward()

in hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/algorithm/SubGraphTraverser.java [184:293]


        public PathSet forward(Directions direction) {
            PathSet paths = new PathSet();
            MultivaluedMap<Id, Node> newVertices = newMultivalueMap();
            Iterator<Edge> edges;
            // Traversal vertices of previous level
            for (Map.Entry<Id, List<Node>> entry : this.sources.entrySet()) {
                Id vid = entry.getKey();
                // Record edgeList to determine if multiple edges exist
                List<Edge> edgeList = IteratorUtils.list(edgesOfVertex(
                        vid, direction, this.label, this.degree));
                edges = edgeList.iterator();

                if (!edges.hasNext()) {
                    // Reach the end, rays found
                    if (this.rings) {
                        continue;
                    }
                    for (Node n : entry.getValue()) {
                        // Store rays
                        paths.add(new Path(n.path()));
                        this.pathCount++;
                        if (this.reachLimit()) {
                            return paths;
                        }
                    }
                }

                int neighborCount = 0;
                Set<Id> currentNeighbors = newIdSet();
                while (edges.hasNext()) {
                    neighborCount++;
                    HugeEdge edge = (HugeEdge) edges.next();
                    this.edgeCount += 1L;
                    Id target = edge.id().otherVertexId();

                    this.edgeRecord.addEdge(vid, target, edge);

                    // Avoid deduplicate path
                    if (currentNeighbors.contains(target)) {
                        continue;
                    }
                    currentNeighbors.add(target);
                    this.accessedVertices.add(target);
                    for (Node node : entry.getValue()) {
                        // No ring, continue
                        if (!node.contains(target)) {
                            // Add node to next start-nodes
                            newVertices.add(target, new Node(target, node));
                            continue;
                        }

                        // Rays found if it's fake ring like:
                        // path is pattern: A->B<-A && A is only neighbor of B
                        boolean uniqueEdge = neighborCount == 1 &&
                                             !edges.hasNext();
                        boolean bothBack = target.equals(node.parent().id()) &&
                                           direction == Directions.BOTH;
                        if (!this.rings && bothBack && uniqueEdge) {
                            paths.add(new Path(node.path()));
                            this.pathCount++;
                            if (this.reachLimit()) {
                                return paths;
                            }
                        }

                        // Actual rings found
                        if (this.rings) {
                            boolean ringsFound = false;
                            // 1. sourceInRing is false, or
                            // 2. sourceInRing is true and target == source
                            if (!sourceInRing || target.equals(this.source)) {
                                if (!target.equals(node.parent().id())) {
                                    ringsFound = true;
                                } else if (direction != Directions.BOTH) {
                                    ringsFound = true;
                                } else if (hasMultiEdges(edgeList, target)) {
                                    ringsFound = true;
                                }
                            }

                            if (ringsFound) {
                                List<Id> path = node.path();
                                path.add(target);
                                paths.add(new RingPath(null, path));
                                this.pathCount++;
                                if (this.reachLimit()) {
                                    return paths;
                                }
                            }
                        }
                    }
                }
            }
            // Re-init sources
            this.sources = newVertices;

            if (!this.rings && --this.depth <= 0) {
                for (List<Node> list : newVertices.values()) {
                    for (Node n : list) {
                        paths.add(new Path(n.path()));
                        this.pathCount++;
                        if (this.reachLimit()) {
                            return paths;
                        }
                    }
                }
            }

            return paths;
        }