From fe1e30702a02119d17e2b99c6c024fda87cd889c Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 1 Oct 2021 14:48:44 +1000 Subject: [PATCH] Fix bug where removing addresses and roles could leave other elements in invalid states, "IfcPersonAndOrganization" --- .../ifcopenshell/api/owner/remove_address.py | 4 ++ .../ifcopenshell/api/owner/remove_role.py | 7 +++ .../test/api/owner/test_remove_address.py | 14 ++++++ .../test/api/owner/test_remove_role.py | 48 +++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 src/ifcopenshell-python/test/api/owner/test_remove_role.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py index 2362f4a24d..af6e9235e5 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_address.py @@ -6,4 +6,8 @@ class Usecase: self.settings[key] = value def execute(self): + for inverse in self.file.get_inverse(self.settings["address"]): + if inverse.is_a() in ("IfcOrganization", "IfcPerson"): + if inverse.Addresses == (self.settings["address"],): + inverse.Addresses = None self.file.remove(self.settings["address"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py index 2218616a44..7fd10c8c70 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_role.py @@ -6,4 +6,11 @@ class Usecase: self.settings[key] = value def execute(self): + for inverse in self.file.get_inverse(self.settings["role"]): + if inverse.is_a() in ("IfcOrganization", "IfcPerson", "IfcPersonAndOrganization"): + if inverse.Roles == (self.settings["role"],): + inverse.Roles = None + elif inverse.is_a("IfcResourceLevelRelationship") and not inverse.is_a("IfcOrganizationRelationship"): + if inverse.RelatedResourceObjects == (self.settings["organisation"],): + self.file.remove(inverse) self.file.remove(self.settings["role"]) diff --git a/src/ifcopenshell-python/test/api/owner/test_remove_address.py b/src/ifcopenshell-python/test/api/owner/test_remove_address.py index ec21b0d6bf..7d19c5e755 100644 --- a/src/ifcopenshell-python/test/api/owner/test_remove_address.py +++ b/src/ifcopenshell-python/test/api/owner/test_remove_address.py @@ -9,3 +9,17 @@ class TestRemoveAddress(test.bootstrap.IFC4): ifcopenshell.api.run("owner.remove_address", self.file, address=postal) ifcopenshell.api.run("owner.remove_address", self.file, address=telecom) assert len(self.file.by_type("IfcAddress")) == 0 + + def test_ensuring_organisation_cardinality_is_valid(self): + address = self.file.createIfcPostalAddress() + organisation = self.file.createIfcOrganization() + organisation.Addresses = [address] + ifcopenshell.api.run("owner.remove_address", self.file, address=address) + assert organisation.Addresses is None + + def test_ensuring_person_cardinality_is_valid(self): + address = self.file.createIfcPostalAddress() + person = self.file.createIfcPerson() + person.Addresses = [address] + ifcopenshell.api.run("owner.remove_address", self.file, address=address) + assert person.Addresses is None diff --git a/src/ifcopenshell-python/test/api/owner/test_remove_role.py b/src/ifcopenshell-python/test/api/owner/test_remove_role.py new file mode 100644 index 0000000000..82720d976a --- /dev/null +++ b/src/ifcopenshell-python/test/api/owner/test_remove_role.py @@ -0,0 +1,48 @@ +import test.bootstrap +import ifcopenshell.api + + +class TestRemoveRole(test.bootstrap.IFC4): + def test_removing_a_role(self): + role = self.file.createIfcActorRole() + ifcopenshell.api.run("owner.remove_role", self.file, role=role) + assert len(self.file.by_type("IfcActorRole")) == 0 + + def test_ensuring_organisation_cardinality_is_valid(self): + role = self.file.createIfcActorRole() + organisation = self.file.createIfcOrganization() + organisation.Roles = [role] + ifcopenshell.api.run("owner.remove_role", self.file, role=role) + assert organisation.Roles is None + + def test_ensuring_person_cardinality_is_valid(self): + role = self.file.createIfcActorRole() + person = self.file.createIfcPerson() + person.Roles = [role] + ifcopenshell.api.run("owner.remove_role", self.file, role=role) + assert person.Roles is None + + def test_ensuring_person_and_organisation_cardinality_is_valid(self): + role = self.file.createIfcActorRole() + person_and_organisation = self.file.createIfcPersonAndOrganization() + person_and_organisation.Roles = [role] + ifcopenshell.api.run("owner.remove_role", self.file, role=role) + assert person_and_organisation.Roles is None + + def test_deleting_resource_approval_relationships(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcResourceApprovalRelationship(RelatedResourceObjects=[organisation]) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcResourceApprovalRelationship")) == 0 + + def test_deleting_resource_constraint_relationships(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcResourceConstraintRelationship(RelatedResourceObjects=[organisation]) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcResourceConstraintRelationship")) == 0 + + def test_deleting_external_reference_relationships(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcExternalReferenceRelationship(RelatedResourceObjects=[organisation]) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcExternalReferenceRelationship")) == 0