GenUiSurfaceGraph.of constructor
GenUiSurfaceGraph.of(
- SurfaceDefinition definition
Reads the graph out of definition.
Implementation
factory GenUiSurfaceGraph.of(SurfaceDefinition definition) {
final Set<String> ids = definition.components.keys.toSet();
final children = <String, Set<String>>{};
final boundPaths = <String, Set<String>>{};
// Which of a component's children arrived through a template, and over
// which list: a templated child reads its properties inside that list's
// row, so its paths resolve against it rather than against the root.
final templates = <String, Map<String, String>>{};
final rawPaths = <String, Set<String>>{};
for (final Component component in definition.components.values) {
final found = <String>{};
final paths = <String>{};
final repeated = <String, String>{};
_scan(component.properties, ids, found, paths, repeated);
children[component.id] = found;
rawPaths[component.id] = paths;
if (repeated.isNotEmpty) templates[component.id] = repeated;
}
final order = <String>[];
final seen = <String>{};
final cyclic = <String>{};
final onStack = <String>{};
final bases = <String, String>{genUiRootComponentId: '/'};
void walk(String id) {
if (!ids.contains(id)) return;
if (onStack.contains(id)) {
cyclic.add(id);
return;
}
if (!seen.add(id)) return;
order.add(id);
onStack.add(id);
final String base = bases[id] ?? '/';
for (final String child in children[id]!) {
final String? over = templates[id]?[child];
// A component reached two ways keeps the first base it was given.
bases[child] ??= over == null
? base
: '${_resolve(base, over)}/$genUiRowWildcard';
walk(child);
}
onStack.remove(id);
}
walk(genUiRootComponentId);
for (final MapEntry<String, Set<String>> entry in rawPaths.entries) {
final String base = bases[entry.key] ?? '/';
boundPaths[entry.key] = <String>{
for (final String path in entry.value) _resolve(base, path),
};
}
return GenUiSurfaceGraph._(
definition: definition,
children: children,
boundPaths: boundPaths,
order: List<String>.unmodifiable(order),
unreachable: Set<String>.unmodifiable(
ids.where((String id) => !seen.contains(id)).toSet(),
),
cyclic: Set<String>.unmodifiable(cyclic),
);
}