toTreeFrom<K> method

Map<K, dynamic> toTreeFrom<K>(
  1. List<T> roots, {
  2. required GraphWalkNodeProvider<T> nodeProvider,
  3. required GraphWalkNodeOutputsProvider<T> outputsProvider,
  4. K keyCast(
    1. GraphStep<T> step,
    2. T value
    )?,
})

Returns a Map representation of this graph from roots.

Implementation

Map<K, dynamic> toTreeFrom<K>(
  List<T> roots, {
  required GraphWalkNodeProvider<T> nodeProvider,
  required GraphWalkNodeOutputsProvider<T> outputsProvider,
  K Function(GraphStep<T> step, T value)? keyCast,
}) {
  final processed = _processedNodes;

  if (keyCast == null) {
    if (K == String) {
      keyCast = (s, v) => v.toString() as K;
    } else if (K == Node || K == <Node<T>>[].genericType) {
      keyCast = (s, v) => nodeProvider(s, v) as K;
    } else {
      keyCast = (s, v) => v as K;
    }
  }

  Map<K, dynamic> Function() createNode = K == dynamic
      ? () => (<T, dynamic>{} as Map<K, dynamic>)
      : () => <K, dynamic>{};

  Map<Node<T>, Map<K, dynamic>> allTreeNodes = K == dynamic
      ? (<Node<T>, Map<T, dynamic>>{} as Map<Node<T>, Map<K, dynamic>>)
      : <Node<T>, Map<K, dynamic>>{};

  Map<K, dynamic> tree =
      K == dynamic ? (<T, dynamic>{} as Map<K, dynamic>) : <K, dynamic>{};

  var rootNodes = roots.map((e) {
    var rootStep = GraphValueStep.root(this, e);
    return nodeProvider(rootStep, e) ??
        (throw ArgumentError("Root not present in graph: $e"));
  }).toList();

  if (sortByInputDependency) {
    rootNodes = rootNodes.sortedByInputDependency();
  }

  final queue = ListQueue<GraphNodeStep<T>>();

  queue.addAll(rootNodes.toGraphRootStep(this));

  while (queue.isNotEmpty) {
    final step = queue.removeFirst();
    final node = step.node;

    var processedCount = processed.increment(node);

    var nodeKey = keyCast(step, node.value);

    if (processedCount <= 1) {
      var parentNode = step.parentNode;
      var parentTreeNode =
          parentNode != null ? allTreeNodes[parentNode]! : tree;

      var treeNode = allTreeNodes[node];
      if (treeNode == null) {
        treeNode = allTreeNodes[node] = createNode();
        parentTreeNode[nodeKey] = node.outputs.isEmpty ? null : treeNode;
      } else {
        parentTreeNode[nodeKey] = nodeKey;
      }

      var outputs = outputsProvider(step, node);

      if (outputs != null) {
        if (sortByInputDependency) {
          outputs = outputs.sortedByInputDependency();
        }

        queue.addAllToScanQueue(outputs.toGraphNodeStep(step), bfs);
      }
    } else {
      var parentNode = step.parentNode;
      var parentTreeNode =
          parentNode != null ? allTreeNodes[parentNode]! : tree;

      var treeNode = allTreeNodes[node];
      assert(treeNode != null);
      parentTreeNode[nodeKey] = nodeKey;
    }
  }

  return tree;
}