build method

DiagramDocument build()

Derives the successor snapshot, or returns document when empty.

Implementation

DiagramDocument build() {
  if (isEmpty) return document;
  final base = document;
  final canonical = base._elementPositions.length == base.elements.length;
  if (canonical && _inserted.isEmpty && _removed.isEmpty) {
    return _replaceInPlace();
  }
  if (canonical &&
      _removed.isEmpty &&
      _before.isEmpty &&
      _after.isEmpty &&
      _appended.length == _inserted.length) {
    // Pure append: share every complete chunk and extend the positions.
    final appended = _inserted.values.toList();
    final positions = Map.of(base._elementPositions);
    var position = base.elements.length;
    for (final element in appended) {
      positions[element.id] = position++;
    }
    return DiagramDocument._derived(
      id: base.id,
      revision: base.revision + 1,
      elements: (base.elements as _ElementVector)._replaceAndAppend(
        _replacementPositions(),
        appended,
      ),
      elementPositions: Map.unmodifiable(positions),
      ownershipTopology: Object(),
      selectionTopology: Object(),
      admissionTopology: Object(),
      contentToken: Object(),
      changeEvidence: _evidence(),
    );
  }
  final elements = <DiagramElement>[];
  void emit(Object slot, DiagramElement? element) {
    for (final previous in _before[slot] ?? const <Object>[]) {
      emit(previous, _inserted[previous]);
    }
    if (element != null) elements.add(element);
    for (final next in _after[slot] ?? const <Object>[]) {
      emit(next, _inserted[next]);
    }
  }

  for (final element in base.elements) {
    final removed = _removed.contains(element.id);
    emit(element.id, removed ? null : _replaced[element.id] ?? element);
  }
  for (final slot in _appended) {
    emit(slot, _inserted[slot]);
  }
  final result = DiagramDocument(
    id: base.id,
    revision: base.revision + 1,
    elements: elements,
  );
  if (!canonical || result._elementPositions.length != elements.length) {
    return result;
  }
  return result._withEvidence(_evidence());
}