Files
sfera/packages/ui-semantics/src/ui_semantics/__init__.py
T
m af900e4e34
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled
Extract managed form elements from XML
2026-05-21 06:10:05 +03:00

68 lines
2.4 KiB
Python

from __future__ import annotations
from pydantic import BaseModel, Field
from sir import EdgeKind, NodeKind, SemanticNode, SirSnapshot
class FormSemantics(BaseModel):
form: SemanticNode
commands: list[SemanticNode] = Field(default_factory=list)
elements: list[SemanticNode] = Field(default_factory=list)
command_handlers: dict[str, SemanticNode] = Field(default_factory=dict)
def form_semantics(snapshot: SirSnapshot) -> list[FormSemantics]:
nodes = {node.lineage_id: node for node in snapshot.nodes}
forms = {
node.lineage_id: FormSemantics(form=node)
for node in snapshot.nodes
if node.kind == NodeKind.FORM
}
element_children: dict[str, list[SemanticNode]] = {}
for edge in snapshot.edges:
form = forms.get(edge.source_lineage)
target = nodes.get(edge.target_lineage)
if target is None:
continue
if edge.kind == EdgeKind.HAS_ELEMENT and target.kind == NodeKind.FORM_ELEMENT:
element_children.setdefault(edge.source_lineage, []).append(target)
if form is None:
continue
if edge.kind == EdgeKind.HAS_COMMAND:
form.commands.append(target)
for form in forms.values():
form.elements.extend(_flatten_form_elements(form.form.lineage_id, element_children))
command_to_form = {
command.lineage_id: form
for form in forms.values()
for command in form.commands
}
for edge in snapshot.edges:
if edge.kind != EdgeKind.HANDLES:
continue
form = command_to_form.get(edge.source_lineage)
handler = nodes.get(edge.target_lineage)
if form is not None and handler is not None:
form.command_handlers[edge.source_lineage] = handler
return sorted(forms.values(), key=lambda item: item.form.qualified_name)
def _flatten_form_elements(root_lineage: str, element_children: dict[str, list[SemanticNode]]) -> list[SemanticNode]:
result: list[SemanticNode] = []
seen: set[str] = set()
def visit(parent_lineage: str) -> None:
for element in element_children.get(parent_lineage, []):
if element.lineage_id in seen:
continue
seen.add(element.lineage_id)
result.append(element)
visit(element.lineage_id)
visit(root_lineage)
return result
__all__ = ["FormSemantics", "form_semantics"]