walkAsync<R> method
Future<R?>
walkAsync<R>(
- Iterable<
T> from, { - required GraphWalkNodeProviderAsync<
T> nodeProvider, - required GraphWalkOutputsProviderAsync<
T> outputsProvider, - required GraphWalkNodeProcessorAsync<
T, R> process, - int? maxDepth,
A generic walk algorithm.
Implementation
Future<R?> walkAsync<R>(
Iterable<T> from, {
required GraphWalkNodeProviderAsync<T> nodeProvider,
required GraphWalkOutputsProviderAsync<T> outputsProvider,
required GraphWalkNodeProcessorAsync<T, R> process,
int? maxDepth,
}) async {
maxDepth ??= defaultMaxDepth;
final processed = _processedNodes;
final queue = ListQueue<GraphNodeStep<T>>();
for (var rootValue in from) {
var rootStepValue = GraphValueStep.root(this, rootValue);
final rootNode = await nodeProvider(rootStepValue, rootValue) ??
(throw StateError("Can't find root node: $rootValue"));
var rootStep = GraphNodeStep.root(this, rootNode);
queue.add(rootStep);
}
while (queue.isNotEmpty) {
final step = queue.removeFirst();
final node = step.node;
final nodeValue = step.nodeValue;
var processCount = processed.increment(node);
if (processCount <= maxExpansion && step.depth <= maxDepth) {
if (processRoots || step.isNotRoot) {
var ret = await process(step);
if (ret != null) {
if (ret is GraphWalkingInstructionResult) {
return ret.result as R?;
} else if (ret is GraphWalkingInstructionOperation) {
switch (ret.operation) {
case GraphWalkingOperation.stop:
return null;
case GraphWalkingOperation.next:
continue;
}
} else if (ret is GraphWalkingInstructionSetExpansionCounter) {
processed[node] = ret.count;
} else if (ret is GraphWalkingInstructionSetNodesExpansionCounter) {
processed.addCounter(ret.counter);
} else {
return _resolveWalkProcessReturn<T, R>(node, ret);
}
}
}
if (stopMatcher.matchesNode(node)) {
return _resolveWalkProcessReturn<T, R>(node, true);
}
var outputs = await outputsProvider(step, nodeValue);
if (outputs != null) {
var outputsNodes = outputs.map((v) {
var nodeStepValue = GraphValueStep.subNode(step, v);
return nodeProvider(nodeStepValue, v);
});
queue.addAllToScanQueue(
await outputsNodes.toGraphNodeStepAsync(step), bfs);
}
}
}
return _resolveWalkProcessReturn<T, R>(null, false);
}