populate method

void populate(
  1. TreeElement incoming,
  2. FormDef form, {
  3. AnswerResolver resolver = defaultAnswerResolver,
})

Fills this template node (and its subtree) from the saved node incoming: typed values, repeat instances, attributes; a missing non-repeat child becomes non-relevant. Port of TreeElement.populate.

Implementation

void populate(
  TreeElement incoming,
  FormDef form, {
  AnswerResolver resolver = defaultAnswerResolver,
}) {
  if (isLeaf) {
    final value = incoming.value;
    if (value == null) {
      this.value = null;
    } else if (dataType == DataType.text || dataType == DataType.nullType) {
      this.value = value;
    } else {
      this.value = resolver(value.value as String, this, form);
    }
  } else {
    final names = <String>[];
    for (final child in children) {
      if (!names.contains(child.name)) names.add(child.name!);
    }
    // Remove the default repeat instances, keeping templates.
    for (var i = 0; i < numChildren; i++) {
      final child = childAt(i);
      if (child.isRepeatable &&
          child.multiplicity != TreeReference.indexTemplate) {
        removeChildAt(i);
        i--;
      }
    }
    // Keep the schema's order.
    if (numChildren != names.length) throw StateError('sanity check failed');
    for (var i = 0; i < numChildren; i++) {
      final child = childAt(i);
      final expectedName = names[i];
      if (child.name != expectedName) {
        var j = i + 1;
        while (j < numChildren && childAt(j).name != expectedName) {
          j++;
        }
        if (j == numChildren) throw StateError('sanity check failed');
        final child2 = childAt(j);
        removeChildAt(j);
        insertChildAt(i, child2);
      }
    }
    for (var i = 0; i < numChildren; i++) {
      final child = childAt(i);
      final newChildren = incoming.childrenWithName(child.name!);
      if (child.isRepeatable) {
        for (var k = 0; k < newChildren.length; k++) {
          final newChild = child.deepCopy(includeTemplates: true)
            ..multiplicity = k;
          insertChildAt(i + k + 1, newChild);
          newChild.populate(newChildren[k], form, resolver: resolver);
        }
        i += newChildren.length;
      } else if (newChildren.isEmpty) {
        child.isRelevant = false;
      } else {
        child.populate(newChildren.first, form, resolver: resolver);
      }
    }
  }
  for (final a in incoming.attributes) {
    setAttribute(a.namespace, a.name!, a.attributeValue);
  }
}