@@ -0,0 +1,1324 @@
+package org.jenkinsci.plugins.workflow.support;%0A%0Aimport org.jenkinsci.plugins.workflow.flow.FlowExecution;%0Aimport org.jenkinsci.plugins.workflow.graph.FlowNode;%0A%0Aimport java.util.Collection;%0Aimport java.util.HashSet;%0Aimport java.util.Set;%0Aimport java.util.Stack;%0A%0A/**%0A * Visits a graph of flow nodes and iterates nodes in them.%0A *%0A * TODO: guarantee DFS order%0A *%0A * @author Kohsuke Kawaguchi%0A */%0Apublic class FlowGraphWalker %7B%0A    // queue of nodes to visit.%0A    // it's a stack and not queue to visit nodes in DFS%0A    Stack%3CFlowNode%3E q = new Stack%3CFlowNode%3E();%0A%0A    Set%3CFlowNode%3E visited = new HashSet%3CFlowNode%3E();%0A%0A    public FlowGraphWalker(FlowExecution exec) %7B%0A        q.addAll(exec.getCurrentHeads());%0A    %7D%0A%0A    public FlowGraphWalker() %7B%0A    %7D%0A%0A    public void addHead(FlowNode head) %7B%0A        q.add(head);%0A    %7D%0A%0A    public void addHeads(Collection%3CFlowNode%3E heads) %7B%0A        q.addAll(heads);%0A    %7D%0A%0A    /**%0A     * Each time this method is called, it returns a new node until all the nodes are visited,%0A     * in which case this method returns null.%0A     */%0A    public FlowNode next() %7B%0A        while (!q.isEmpty()) %7B%0A            FlowNode n = q.pop();%0A            if (visited.contains(n))%0A                continue;%0A%0A            q.addAll(n.getParents());%0A            return n;%0A        %7D%0A        return null;%0A    %7D%0A%7D%0A

Extracted the logic of walking