definitionForEntry function
({List<DraftCommand> commands, Handle definition})
definitionForEntry(
- DraftDocument doc,
- SymbolEntry entry
The definition a placement of entry in doc uses, and the commands
that make it when it is a copy (none when one is reused): the one
reuse-or-copy path, shared by placeSymbol and a size change (spec 09c
D7, V-7). A definition is reused when it carries the entry's key and
version, still exists, agrees on seating (spec 14 S2) and is leaf-equal
to the entry; otherwise the definition is copied with fresh handles,
allocated here. The entry's leaves are ascending by handle (R5-7).
Implementation
({Handle definition, List<DraftCommand> commands}) definitionForEntry(
DraftDocument doc, SymbolEntry entry) {
assert(_ascending(entry.leaves),
'the entry\'s leaves must be ascending by handle (spec 09c R5-7)');
final commands = <DraftCommand>[];
Handle? definition;
for (final h in doc.components.withComponent<SymbolComponent>()) {
final c = doc.components.get<SymbolComponent>(h);
// A component can outlive its definition in a file saved before 09c
// (removing a definition now takes its components, spec D11, but leaves
// such orphans alone, and purge never clears a component), so the
// definition must still exist. Its seating must agree with the entry's
// too (spec 14 S2, review F-5): a hand-edited or foreign plan's copy
// without seats would make every new placement of a table unservable,
// so such a copy is not reused; one is made beside it.
if (c != null &&
c.key == entry.key &&
c.version == entry.version &&
doc.tree.definition(h) != null &&
doc.components.get<SeatingComponent>(h)?.seats == entry.seats &&
isLeafEqual(doc, h, entry)) {
definition = h;
break;
}
}
if (definition == null) {
final copy = doc.handleSeed.next();
final taken = {for (final d in doc.tree.definitions) d.name};
final base = '${entry.key}@${entry.version}';
var name = base;
for (var n = 2; taken.contains(name); n++) {
name = '$base#$n';
}
commands
..add(AddDefinitionCommand(Definition(
handle: copy,
name: name,
basePoint: entry.definition.basePoint,
children: const [],
)))
..add(SetComponentCommand<SymbolComponent>(
copy,
SymbolComponent(
key: entry.key,
name: entry.name,
category: entry.category,
tags: entry.tags,
version: entry.version,
),
));
// A servable symbol stays servable in the plan (spec 14 S2).
final seats = entry.seats;
if (seats != null) {
commands.add(SetComponentCommand<SeatingComponent>(
copy, SeatingComponent(seats: seats)));
}
for (final leaf in entry.leaves) {
commands.add(AddEntityCommand(
record:
leaf.record.copyWith(handle: doc.handleSeed.next(), owner: copy),
payload: leaf.payload,
));
}
definition = copy;
}
return (definition: definition, commands: commands);
}