Class LinearScanner
java.lang.Object
org.jenkinsci.plugins.workflow.graphanalysis.AbstractFlowScanner
org.jenkinsci.plugins.workflow.graphanalysis.LinearScanner
- Direct Known Subclasses:
- LinearBlockHoppingScanner
Scans through the flow graph in strictly linear fashion, visiting only the first branch in parallel blocks.
 
Iteration order: depth-ONLY, meaning we walk through parents and only follow the first parent of each FlowNode
 This means that where are parallel branches, we will only visit a partial set of FlowNodes in the directed acyclic graph.
 
Use case: we don't care about parallel branches or know they don't exist, we just want to walk through the top-level blocks.
This is the fastest and simplest way to walk a flow, because you only care about a single node at a time. Nuance: where there are multiple parent nodes (in a parallel block), and one is denylisted, we'll find the first non-denylisted one.
- Author:
- Sam Van Oort
- 
Field SummaryFields inherited from class org.jenkinsci.plugins.workflow.graphanalysis.AbstractFlowScannerMAX_LIST_CHECK_SIZE, myBlackList, myCurrent, myNext
- 
Constructor SummaryConstructors
- 
Method SummaryModifier and TypeMethodDescriptionfilteredNodes(Collection<FlowNode> heads, com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.filteredNodes(Collection<FlowNode> heads, Collection<FlowNode> blackList, com.google.common.base.Predicate<FlowNode> matchCondition) Return a filtered list ofFlowNodes matching a condition, in the order encountered.findFirstMatch(Collection<FlowNode> heads, com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.findFirstMatch(Collection<FlowNode> heads, Collection<FlowNode> blackListNodes, com.google.common.base.Predicate<FlowNode> matchCondition) Find the first FlowNode within the iteration order matching a given condition Includes null-checking on arguments to allow directly calling with unchecked inputs (simplifies use).findFirstMatch(FlowExecution exec, com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.unsafe to callprotected FlowNodenext(FlowNode current, Collection<FlowNode> blackList) Actual meat of the iteration, get the next node to visit, using and updating state as neededprotected voidreset()Reset internal state so that we can begin walking a new flow graph Public APIs need to invoke this before searchesprotected voidsetHeads(Collection<FlowNode> heads) Set up to begin flow scanning using the filteredHeads as starting points This method makes several assumptions: -AbstractFlowScanner.reset()has already been invoked to reset state - filteredHeads has already had any points inAbstractFlowScanner.myBlackListremoved - none of the filteredHeads are nullbooleansetup(Collection<FlowNode> heads) Deprecated.booleansetup(Collection<FlowNode> heads, Collection<FlowNode> blackList) Deprecated.voidvisitAll(Collection<FlowNode> heads, Collection<FlowNode> blackList, FlowNodeVisitor visitor) Given aFlowNodeVisitor, invokeFlowNodeVisitor.visit(FlowNode)on each node and halt early if it returns false.voidvisitAll(Collection<FlowNode> heads, FlowNodeVisitor visitor) Syntactic sugar forAbstractFlowScanner.visitAll(Collection, Collection, FlowNodeVisitor)where we don't denylist any nodesMethods inherited from class org.jenkinsci.plugins.workflow.graphanalysis.AbstractFlowScannerallNodes, allNodes, convertToFastCheckable, filter, filteredNodes, filteredNodes, findFirstMatch, hasNext, iterator, next, remove, setup, setupMethods inherited from class java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface java.lang.IterableforEach, spliteratorMethods inherited from interface java.util.IteratorforEachRemaining
- 
Constructor Details- 
LinearScannerpublic LinearScanner()
 
- 
- 
Method Details- 
resetprotected void reset()Description copied from class:AbstractFlowScannerReset internal state so that we can begin walking a new flow graph Public APIs need to invoke this before searches- Specified by:
- resetin class- AbstractFlowScanner
 
- 
setHeadsSet up to begin flow scanning using the filteredHeads as starting points This method makes several assumptions: -AbstractFlowScanner.reset()has already been invoked to reset state - filteredHeads has already had any points inAbstractFlowScanner.myBlackListremoved - none of the filteredHeads are null- Specified by:
- setHeadsin class- AbstractFlowScanner
- Parameters:
- heads- Head nodes that have been filtered against denyList. Do not pass multiple heads.
 
- 
nextDescription copied from class:AbstractFlowScannerActual meat of the iteration, get the next node to visit, using and updating state as needed- Specified by:
- nextin class- AbstractFlowScanner
- Parameters:
- current- Current node to use in generating next value
- blackList- Nodes that are not eligible for visiting
- Returns:
- Next node to visit, or null if we've exhausted the node list
 
- 
filteredNodes@Deprecated @NonNull public List<FlowNode> filteredNodes(Collection<FlowNode> heads, @NonNull com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.Syntactic sugar forAbstractFlowScanner.filteredNodes(Collection, Collection, Predicate)with no denyList nodes- Overrides:
- filteredNodesin class- AbstractFlowScanner
 
- 
filteredNodes@NonNull public List<FlowNode> filteredNodes(Collection<FlowNode> heads, Collection<FlowNode> blackList, com.google.common.base.Predicate<FlowNode> matchCondition) Return a filtered list ofFlowNodes matching a condition, in the order encountered. Includes null-checking on arguments to allow directly calling with unchecked inputs (simplifies use).- Overrides:
- filteredNodesin class- AbstractFlowScanner
- Parameters:
- heads- Nodes to start iterating backward from by visiting their parents. Do not pass multiple heads.
- blackList- Nodes we may not visit or walk beyond.
- matchCondition- Predicate that must be met for nodes to be included in output. Input is always non-null.
- Returns:
- List of flownodes matching the predicate.
 
- 
findFirstMatch@Deprecated public FlowNode findFirstMatch(Collection<FlowNode> heads, @NonNull com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.Syntactic sugar forAbstractFlowScanner.findFirstMatch(Collection, Collection, Predicate)where there is no denyList- Overrides:
- findFirstMatchin class- AbstractFlowScanner
 
- 
findFirstMatchpublic FlowNode findFirstMatch(Collection<FlowNode> heads, Collection<FlowNode> blackListNodes, com.google.common.base.Predicate<FlowNode> matchCondition) Find the first FlowNode within the iteration order matching a given condition Includes null-checking on arguments to allow directly calling with unchecked inputs (simplifies use).- Overrides:
- findFirstMatchin class- AbstractFlowScanner
- Parameters:
- heads- Head nodes to start walking from. Do not pass multiple heads.
- blackListNodes- Nodes that are never visited, search stops here (bound is exclusive). If you want to create an inclusive bound, just use a node's parents.
- matchCondition- Predicate to match when we've successfully found a given node type
- Returns:
- First matching node, or null if no matches found
 
- 
visitAllSyntactic sugar forAbstractFlowScanner.visitAll(Collection, Collection, FlowNodeVisitor)where we don't denylist any nodes- Overrides:
- visitAllin class- AbstractFlowScanner
- Parameters:
- heads- Do not pass multiple heads.
 
- 
visitAllpublic void visitAll(Collection<FlowNode> heads, Collection<FlowNode> blackList, @NonNull FlowNodeVisitor visitor) Given aFlowNodeVisitor, invokeFlowNodeVisitor.visit(FlowNode)on each node and halt early if it returns false. Includes null-checking on all but the visitor, to allow directly calling with unchecked inputs (simplifies use). Useful if you wish to collect some information from every node in the FlowGraph. To do that, accumulate internal state in the visitor, and invoke a getter when complete.- Overrides:
- visitAllin class- AbstractFlowScanner
- Parameters:
- heads- Nodes to start walking the DAG backwards from. Do not pass multiple heads.
- blackList- Nodes we can't visit or pass beyond.
- visitor- Visitor that will see each FlowNode encountered.
 
- 
findFirstMatch@Deprecated public FlowNode findFirstMatch(FlowExecution exec, @NonNull com.google.common.base.Predicate<FlowNode> matchPredicate) Deprecated.unsafe to callSyntactic sugar forAbstractFlowScanner.findFirstMatch(Collection, Collection, Predicate)usingFlowExecution.getCurrentHeads()to get heads and no denyList- Overrides:
- findFirstMatchin class- AbstractFlowScanner
 
- 
setupDeprecated.Helper: version ofAbstractFlowScanner.setup(Collection, Collection)where we don't have any nodes to denylist- Overrides:
- setupin class- AbstractFlowScanner
 
- 
setupDeprecated.Set up for iteration/analysis on a graph of nodes, initializing the internal state Includes null-checking on arguments to allow directly calling with unchecked inputs (simplifies use).- Overrides:
- setupin class- AbstractFlowScanner
- Parameters:
- heads- The head nodes we start walking from (the most recently executed nodes, i.e. FlowExecution.getCurrentHeads()
- blackList- Nodes that we cannot visit or walk past (useful to limit scanning to only nodes after a specific point)
- Returns:
- True if we can have nodes to work with, otherwise false
 
 
- 
AbstractFlowScanner.filteredNodes(FlowNode, Predicate)