derive_from_functions(
diagram: ContextDiagram,
boxes: dict[str, ELKInputChild],
edges: dict[str, ELKInputEdge],
) -> None
Derive Components from allocated functions of the context target.
A Component, a ComponentExchange and two ComponentPorts are added
to data. These elements are prefixed with Derived- to
receive special styling in the serialization step.
Source code in src/capellambse_context_diagrams/builders/derived.py
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 | def derive_from_functions(
diagram: context.ContextDiagram,
boxes: dict[str, _elkjs.ELKInputChild],
edges: dict[str, _elkjs.ELKInputEdge],
) -> None:
"""Derive Components from allocated functions of the context target.
A Component, a ComponentExchange and two ComponentPorts are added
to ``data``. These elements are prefixed with ``Derived-`` to
receive special styling in the serialization step.
"""
assert isinstance(diagram.target, cs.Component)
ports: list[m.ModelElement] = []
for fnc in diagram.target.allocated_functions:
inc, out = _generic.port_collector(fnc, diagram.type)
ports.extend((inc | out).values())
derived_components: dict[str, cs.Component] = {}
for port in ports:
for fex in port.exchanges:
if isinstance(port, fa.FunctionOutputPort):
attr = "target"
else:
attr = "source"
try:
derived_comp = getattr(fex, attr).owner.owner
if (
derived_comp == diagram.target
or derived_comp.uuid in boxes
):
continue
if derived_comp.uuid not in derived_components:
derived_components[derived_comp.uuid] = derived_comp
except AttributeError: # No owner of owner.
pass
# Idea: Include flow direction of derived interfaces from all functional
# exchanges. Mixed means bidirectional. Just even out bidirectional
# interfaces and keep flow direction of others.
centerbox = boxes[diagram.target.uuid]
i = 0
for i, (uuid, derived_component) in enumerate(
derived_components.items(), 1
):
box = _makers.make_box(
derived_component,
no_symbol=diagram._display_symbols_as_boxes,
)
class_ = diagram.serializer.get_styleclass(derived_component.uuid)
box.id = f"{_makers.STYLECLASS_PREFIX}-{class_}:{uuid}"
boxes[uuid] = box
source_id = f"{_makers.STYLECLASS_PREFIX}-CP_INOUT:{i}"
target_id = f"{_makers.STYLECLASS_PREFIX}-CP_INOUT:{-i}"
box.ports.append(_makers.make_port(source_id))
centerbox.ports.append(_makers.make_port(target_id))
if i % 2 == 0:
source_id, target_id = target_id, source_id
uid = f"{_makers.STYLECLASS_PREFIX}-ComponentExchange:{i}"
edges[uid] = _elkjs.ELKInputEdge(
id=uid,
sources=[source_id],
targets=[target_id],
)
centerbox.height += (
_makers.PORT_PADDING
+ (_makers.PORT_SIZE + _makers.PORT_PADDING) * i // 2
)
|