Graph<T>.fromJson constructor

Graph<T>.fromJson(
  1. Map<String, dynamic> json, {
  2. T nodeValueMapper(
    1. GraphStep<T>? previousStep,
    2. String key
    )?,
})

Creates a Graph from json.

Implementation

factory Graph.fromJson(Map<String, dynamic> json,
    {T Function(GraphStep<T>? previousStep, String key)? nodeValueMapper}) {
  if (nodeValueMapper == null) {
    if (T == String) {
      nodeValueMapper = (s, k) => k.toString() as T;
    } else {
      nodeValueMapper = (s, k) => k as T;
    }
  }

  var allEntries = GraphWalker.extractAllEntries(json);
  var maxExpansion = allEntries.length + 1;

  final graph = Graph<T>();

  graph.populate(
    json.keys.map((k) => nodeValueMapper!(null, k)),
    maxExpansion: maxExpansion,
    nodeProvider: (step, nodeValue) {
      var node = graph.node(nodeValue);

      var parentNode = graph.getNode(step.parentValue);
      Map parentJsonNode = parentNode?.attachment ?? json;
      var jsonNode = parentJsonNode[nodeValue];

      var nodeAttachment = node.attachment;
      if (nodeAttachment == null) {
        if (jsonNode != null && (jsonNode is! Map && jsonNode is! String)) {
          throw StateError("Invalid node type> $nodeValue: $jsonNode");
        }
        node.attachment = jsonNode;
      } else if (!identical(jsonNode, nodeAttachment)) {
        if (jsonNode is Map) {
          if (nodeAttachment is Map) {
            nodeAttachment.addAll(jsonNode);
          } else if (nodeAttachment is String) {
            node.attachment = jsonNode;
          }
        } else if (jsonNode is String) {
          if (jsonNode != nodeValue.toString()) {
            throw StateError(
                "Invalid node reference: $nodeValue -> $jsonNode");
          }
        } else if (jsonNode != null) {
          throw StateError(
              "Invalid node type (graph)> $nodeValue: $jsonNode");
        }
      }

      return node;
    },
    outputsProvider: (step, nodeValue) {
      var jsonNode = graph.getNode(nodeValue)?.attachment;
      if (jsonNode is! Map || jsonNode.isEmpty) return null;
      var outputs =
          jsonNode.keys.map((k) => nodeValueMapper!(step, k.toString()));
      return outputs;
    },
  );

  return graph;
}