Skip to content

Commit a31b1b0

Browse files
committed
refactor(connection.py): extract protected method _is_directly_contained_in()
1 parent 3cafc86 commit a31b1b0

File tree

1 file changed

+75
-55
lines changed

1 file changed

+75
-55
lines changed

src/_balder/connection.py

+75-55
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,62 @@ def based_on_elements(self) -> OrConnectionRelation:
241241

242242
# ---------------------------------- PROTECTED METHODS -------------------------------------------------------------
243243

244+
def _is_directly_contained_in(self, other_conn: Connection, ignore_metadata: bool) -> bool:
245+
"""
246+
Helper method that returns true if this connection is directly contained in the `other_conn`.
247+
248+
.. note::
249+
'Directly contained-in' means that the resolved versions of both connections are of the same connection
250+
type, and the elements of that connection are directly embedded within one another from that point onward.
251+
It does not check deeper into the other_conn.
252+
253+
:param other_conn: the other connection
254+
:param ignore_metadata: True, if the metadata should be ignored
255+
"""
256+
257+
resolved_self = self.get_resolved()
258+
resolved_other = other_conn.get_resolved()
259+
260+
if resolved_self.__class__ == Connection and len(resolved_self.based_on_elements) == 0 or \
261+
resolved_other.__class__ == Connection and len(resolved_other.based_on_elements) == 0:
262+
# one of the resolved object is a raw `Connection` object without based-on-elements -> always true
263+
return True
264+
265+
if resolved_self.__class__ == Connection:
266+
return resolved_self.based_on_elements.contained_in(resolved_other, ignore_metadata=ignore_metadata)
267+
268+
if resolved_self.__class__ == resolved_other.__class__:
269+
# The element itself has already matched, now we still have to check whether at least one inner element
270+
# of this type is contained in minimum one element of the other
271+
singles_self = resolved_self.get_singles()
272+
singles_other = other_conn.get_singles()
273+
274+
# check that for one single_self element all hierarchical based_on elements are in one of the single
275+
# other element
276+
for cur_single_self, cur_single_other in itertools.product(singles_self, singles_other):
277+
# check if both consists of only one element
278+
if len(cur_single_self.based_on_elements) == 0:
279+
# the cur self single is only one element -> this is contained in the other
280+
return True
281+
282+
if len(cur_single_other.based_on_elements) == 0:
283+
# the other element is only one element, but the self element not -> contained_in
284+
# for this single definitely false
285+
continue
286+
287+
# note: for both only one `based_on_elements` is possible, because they are singles
288+
self_first_basedon = cur_single_self.based_on_elements[0]
289+
other_first_basedon = cur_single_other.based_on_elements[0]
290+
291+
if isinstance(self_first_basedon, Connection) and \
292+
isinstance(other_first_basedon, AndConnectionRelation):
293+
continue
294+
295+
# find a complete valid match
296+
if self_first_basedon.contained_in(other_first_basedon, ignore_metadata=ignore_metadata):
297+
return True
298+
return False
299+
244300
# ---------------------------------- METHODS -----------------------------------------------------------------------
245301

246302
def get_intersection_with_other_single(
@@ -656,9 +712,10 @@ def contained_in(
656712
ignore_metadata=False
657713
) -> bool:
658714
"""
659-
This method helps to find out whether this connection-tree fits within another connection tree. A connection
660-
object is a certain part of the large connection tree that Balder has at its disposal. This method checks
661-
whether a possibility of this connection tree fits in one possibility of the given connection tree.
715+
This method determines if one connection tree can be embedded within another connection tree. A connection
716+
object represents a specific segment of the extensive connection tree managed by Balder. The method evaluates
717+
whether at least one SINGLE connection object of this connection tree fits within a possible SINGLE connection
718+
of the provided connection `other_conn`.
662719
663720
.. note::
664721
The method returns true if one single connection of this object fits in another single connection that is
@@ -681,63 +738,26 @@ def contained_in(
681738
resolved_self = self.get_resolved()
682739
resolved_other = other_conn.get_resolved()
683740

684-
if resolved_self.__class__ == Connection and len(resolved_self.based_on_elements) == 0 or \
685-
resolved_other.__class__ == Connection and len(resolved_other.based_on_elements) == 0:
686-
# one of the resolved object is a raw `Connection` object without based-on-elements -> always true
741+
if self._is_directly_contained_in(resolved_other, ignore_metadata=ignore_metadata):
687742
return True
688743

689-
if resolved_self.__class__ == Connection:
690-
return resolved_self.based_on_elements.contained_in(resolved_other, ignore_metadata=ignore_metadata)
691-
692-
if resolved_self.__class__ == resolved_other.__class__:
693-
# The element itself has already matched, now we still have to check whether at least one inner element
694-
# of this type is contained in the minimum one element of the other
695-
singles_self = resolved_self.get_singles()
696-
singles_other = resolved_other.get_singles()
744+
# the elements itself do not match -> go deeper within the other connection
697745

698-
# check that for one single_self element all hierarchical based_on elements are in one of the single
699-
# other element
700-
for cur_single_self, cur_single_other in itertools.product(singles_self, singles_other):
701-
# check if both consists of only one element
702-
if len(cur_single_self.based_on_elements) == 0:
703-
# the cur self single is only one element -> this is contained in the other
704-
return True
746+
resolved_other_relation = resolved_other.based_on_elements \
747+
if isinstance(resolved_other, Connection) else resolved_other
705748

706-
if len(cur_single_other.based_on_elements) == 0:
707-
# the other element is only one element, but the self element not -> contained_in
708-
# for this single definitely false
709-
continue
710-
711-
# note: for both only one `based_on_elements` is possible, because they are singles
712-
self_first_basedon = cur_single_self.based_on_elements[0]
713-
other_first_basedon = cur_single_other.based_on_elements[0]
714-
715-
if isinstance(self_first_basedon, Connection) and \
716-
isinstance(other_first_basedon, AndConnectionRelation):
717-
continue
718-
719-
# find a complete valid match
720-
if self_first_basedon.contained_in(other_first_basedon, ignore_metadata=ignore_metadata):
721-
return True
722-
723-
else:
724-
# the elements itself do not match -> go deeper within the other connection
725-
726-
resolved_other_relation = resolved_other.based_on_elements \
727-
if isinstance(resolved_other, Connection) else resolved_other
728-
729-
for cur_other_based_on in resolved_other_relation.connections:
730-
# `cur_other_based_on` can only be a Connection or an AND (resolved can not ba a inner OR)
731-
if isinstance(cur_other_based_on, AndConnectionRelation):
732-
# check if the current connection fits in one of the AND relation items -> allowed too (f.e. a
733-
# smaller AND contained in a bigger AND)
734-
for cur_other_and_element in cur_other_based_on.connections:
735-
if resolved_self.contained_in(cur_other_and_element, ignore_metadata=ignore_metadata):
736-
return True
737-
else:
738-
if resolved_self.contained_in(cur_other_based_on, ignore_metadata=ignore_metadata):
739-
# element was found in this branch
749+
for cur_other_based_on in resolved_other_relation.connections:
750+
# `cur_other_based_on` can only be a Connection or an AND (resolved can not ba a inner OR)
751+
if isinstance(cur_other_based_on, AndConnectionRelation):
752+
# check if the current connection fits in one of the AND relation items -> allowed too (f.e. a
753+
# smaller AND contained in a bigger AND)
754+
for cur_other_and_element in cur_other_based_on.connections:
755+
if resolved_self.contained_in(cur_other_and_element, ignore_metadata=ignore_metadata):
740756
return True
757+
else:
758+
if resolved_self.contained_in(cur_other_based_on, ignore_metadata=ignore_metadata):
759+
# element was found in this branch
760+
return True
741761
return False
742762

743763
def intersection_with(

0 commit comments

Comments
 (0)