diff --git a/capellambse_context_diagrams/collectors/custom.py b/capellambse_context_diagrams/collectors/custom.py index f7ddf9f..402e685 100644 --- a/capellambse_context_diagrams/collectors/custom.py +++ b/capellambse_context_diagrams/collectors/custom.py @@ -198,21 +198,19 @@ def _make_box( for port in getattr(obj, attr, []): self._make_port_and_owner(port) if self.diagram._display_parent_relation: - current = obj - while ( - current - and current.uuid not in self.diagram_target_owners - and getattr(current, "owner", None) is not None - and not isinstance(current.owner, generic.PackageTypes) - ): - current = self._make_owner_box(current) - self.common_owners.add(current.uuid) + owners, common_owner = generic.get_all_owner_elements( + obj, self.diagram_target_owners + ) + for owner in owners: + self._make_owner_box(owner) + if common_owner: + self.common_owners.add(common_owner.uuid) return box def _make_owner_box( self, - obj: t.Any, - ) -> t.Any: + obj: m.ModelElement, + ) -> m.ModelElement: if not (parent_box := self.boxes.get(obj.owner.uuid)): parent_box = self._make_box( obj.owner, diff --git a/capellambse_context_diagrams/collectors/default.py b/capellambse_context_diagrams/collectors/default.py index c311e0e..b534d11 100644 --- a/capellambse_context_diagrams/collectors/default.py +++ b/capellambse_context_diagrams/collectors/default.py @@ -256,15 +256,13 @@ def _process_ports(self) -> None: box.layoutOptions["portLabels.placement"] = "OUTSIDE" if self.diagram._display_parent_relation: - current = owner - while ( - current - and current.uuid not in self.diagram_target_owners - and getattr(current, "owner", None) is not None - and not isinstance(current.owner, generic.PackageTypes) - ): - current = self._make_owner_box(self.diagram, current) - self.common_owners.add(current.uuid) + owners, common_owner = generic.get_all_owner_elements( + owner, self.diagram_target_owners + ) + for current in owners: + self._make_owner_box(self.diagram, current) + if common_owner: + self.common_owners.add(common_owner.uuid) def _make_port( self, port_obj: t.Any diff --git a/capellambse_context_diagrams/collectors/generic.py b/capellambse_context_diagrams/collectors/generic.py index cbbe21b..be986d7 100644 --- a/capellambse_context_diagrams/collectors/generic.py +++ b/capellambse_context_diagrams/collectors/generic.py @@ -267,3 +267,21 @@ def get_all_owners(obj: m.ModelElement) -> cabc.Iterator[str]: while current is not None: yield current.uuid current = getattr(current, "owner", None) + + +def get_all_owner_elements( + obj: m.ModelElement, excluded: list[str] | None = None +) -> tuple[list[m.ModelElement], m.ModelElement | None]: + """Return a list of all owners of ``obj`` and the last owner.""" + excluded = excluded or [] + current: m.ModelElement | None = obj + owners = [] + while ( + current is not None + and current.uuid not in excluded + and (owner := getattr(current, "owner", None)) is not None + and not isinstance(current.owner, PackageTypes) + ): + owners.append(owner) + current = owner + return owners, current