From 291bb0cd55bca6828c29f5ff0a8ab252061d2db0 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 1 Oct 2021 13:29:10 +1000 Subject: [PATCH] Removing an organisation now properly handles references appropriately. --- .../api/owner/remove_application.py | 12 +++ .../api/owner/remove_organisation.py | 28 ++++++ .../api/owner/test_remove_organisation.py | 88 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 src/ifcopenshell-python/ifcopenshell/api/owner/remove_application.py create mode 100644 src/ifcopenshell-python/test/api/owner/test_remove_organisation.py diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_application.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_application.py new file mode 100644 index 0000000000..84a2c9d430 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_application.py @@ -0,0 +1,12 @@ +import ifcopenshell.api + + +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"application": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + self.file.remove(self.settings["application"]) diff --git a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py index 0287a9c5e5..217aa5fe76 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py +++ b/src/ifcopenshell-python/ifcopenshell/api/owner/remove_organisation.py @@ -1,3 +1,6 @@ +import ifcopenshell.api + + class Usecase: def __init__(self, file, **settings): self.file = file @@ -6,4 +9,29 @@ class Usecase: self.settings[key] = value def execute(self): + for role in self.settings["organisation"].Roles or []: + if len(self.file.get_inverse(role)) == 1: + ifcopenshell.api.run("owner.remove_role", self.file, role=role) + for address in self.settings["organisation"].Addresses or []: + if len(self.file.get_inverse(address)) == 1: + ifcopenshell.api.run("owner.remove_address", self.file, address=address) + for inverse in self.file.get_inverse(self.settings["organisation"]): + if inverse.is_a("IfcOrganizationRelationship"): + if inverse.RelatingOrganization == self.settings["organisation"]: + self.file.remove(inverse) + elif inverse.RelatedOrganizations == (self.settings["organisation"],): + self.file.remove(inverse) + elif inverse.is_a("IfcDocumentInformation"): + if inverse.Editors == (self.settings["organisation"],): + inverse.Editors = None + elif inverse.is_a("IfcPersonAndOrganization"): + ifcopenshell.api.run("owner.remove_person_and_organisation", self.file, person_and_organisation=inverse) + elif inverse.is_a("IfcActor"): + ifcopenshell.api.run("owner.remove_actor", self.file, actor=inverse) + elif inverse.is_a("IfcResourceLevelRelationship") and not inverse.is_a("IfcOrganizationRelationship"): + if inverse.RelatedResourceObjects == (self.settings["organisation"],): + self.file.remove(inverse) + elif inverse.is_a("IfcApplication"): + ifcopenshell.api.run("owner.remove_application", self.file, application=inverse) + self.file.remove(self.settings["organisation"]) diff --git a/src/ifcopenshell-python/test/api/owner/test_remove_organisation.py b/src/ifcopenshell-python/test/api/owner/test_remove_organisation.py new file mode 100644 index 0000000000..67714e2be9 --- /dev/null +++ b/src/ifcopenshell-python/test/api/owner/test_remove_organisation.py @@ -0,0 +1,88 @@ +import test.bootstrap +import ifcopenshell.api + + +class TestRemoveOrganisation(test.bootstrap.IFC4): + def test_removing_a_organisation(self): + organisation = self.file.createIfcOrganization() + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcOrganization")) == 0 + + def test_removing_roles_and_addresses_only_used_by_the_organisation(self): + role = self.file.createIfcActorRole() + address = self.file.createIfcPostalAddress() + organisation = self.file.createIfcOrganization() + organisation.Roles = [role] + organisation.Addresses = [address] + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcOrganization")) == 0 + assert len(self.file.by_type("IfcActorRole")) == 0 + assert len(self.file.by_type("IfcPostalAddress")) == 0 + + def test_not_removing_roles_and_addresses_used_elsewhere(self): + role = self.file.createIfcActorRole() + address = self.file.createIfcPostalAddress() + organisation = self.file.createIfcOrganization() + organisation2 = self.file.createIfcOrganization() + organisation.Roles = [role] + organisation.Addresses = [address] + organisation2.Roles = [role] + organisation2.Addresses = [address] + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcOrganization")) == 1 + assert len(self.file.by_type("IfcActorRole")) == 1 + assert len(self.file.by_type("IfcPostalAddress")) == 1 + + def test_deleting_organisation_relationships_as_the_relating_organisation(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcOrganizationRelationship(RelatingOrganization=organisation) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcOrganizationRelationship")) == 0 + + def test_deleting_organisation_relationships_as_the_related_organisation(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcOrganizationRelationship(RelatedOrganizations=[organisation]) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcOrganizationRelationship")) == 0 + + def test_deleting_person_and_organisations(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcPersonAndOrganization(TheOrganization=organisation) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcPersonAndOrganization")) == 0 + + def test_deleting_actors(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcActor(GlobalId=ifcopenshell.guid.new(), TheActor=organisation) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcActor")) == 0 + + def test_ensuring_document_information_should_not_be_left_in_an_invalid_set_cardinality(self): + organisation = self.file.createIfcOrganization() + document_information = self.file.createIfcDocumentInformation(Editors=[organisation]) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert document_information.Editors 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 + + def test_deleting_an_application(self): + organisation = self.file.createIfcOrganization() + self.file.createIfcApplication(ApplicationDeveloper=organisation) + ifcopenshell.api.run("owner.remove_organisation", self.file, organisation=organisation) + assert len(self.file.by_type("IfcApplication")) == 0