diff --git a/src/ifctester/ifctester/facet.py b/src/ifctester/ifctester/facet.py index fa8ff43fb3..6b5536299d 100644 --- a/src/ifctester/ifctester/facet.py +++ b/src/ifctester/ifctester/facet.py @@ -206,6 +206,12 @@ class Entity(Facet): except: # If the user has specified a class that doesn't exist in the version results = [] + if not self.name.endswith("TYPE"): + try: + for element_type in ifc_file.by_type(f"{self.name}Type"): + results.extend(ifcopenshell.util.element.get_types(element_type)) + except: + pass else: results = [] ifc_classes = [t for t in ifc_file.wrapped_data.types() if t.upper() == self.name] @@ -223,7 +229,15 @@ class Entity(Facet): is_pass = inst.is_a().upper() == self.name reason = None - if not is_pass: + if ( + not is_pass + and inst.file.schema == "IFC2X3" + and not self.name.endswith("TYPE") + and (element_type := ifcopenshell.util.element.get_type(inst)) + ): + is_pass = element_type.is_a().upper() == f"{self.name}TYPE" + reason = {"type": "NAME", "actual": element_type.is_a().upper()[:-4]} + elif not is_pass: reason = {"type": "NAME", "actual": inst.is_a().upper()} if is_pass and self.predefinedType: diff --git a/src/ifctester/test/test_facet.py b/src/ifctester/test/test_facet.py index 045b796330..167201979b 100644 --- a/src/ifctester/test/test_facet.py +++ b/src/ifctester/test/test_facet.py @@ -230,6 +230,32 @@ class TestEntity: wall3 = ifcopenshell.api.root.create_entity(ifc, ifc_class="IfcWall", predefined_type="BAZFOO") run("Restrictions an be specified for the predefined type 3/3", facet=facet, inst=wall3, expected=False) + def test_ifc2x3_occurrence_type_mapping(self): + set_facet("entity") + + ifc = ifcopenshell.file(schema="IFC2X3") + application = ifcopenshell.api.owner.add_application(ifc) + person = ifcopenshell.api.owner.add_person( + ifc, identification="LPARTEE", family_name="Partee", given_name="Leeable" + ) + organisation = ifcopenshell.api.owner.add_organisation( + ifc, identification="AWB", name="Architects Without Ballpens" + ) + user = ifcopenshell.api.owner.add_person_and_organisation(ifc, person=person, organisation=organisation) + ifcopenshell.api.owner.settings.get_user = lambda x: user + ifcopenshell.api.owner.settings.get_application = lambda x: application + + element = ifcopenshell.api.root.create_entity(ifc, "IfcFlowTerminal") + element_type = ifcopenshell.api.root.create_entity(ifc, "IfcAirTerminalType") + ifcopenshell.api.type.assign_type(ifc, related_objects=[element], relating_type=element_type) + facet = Entity(name="IFCAIRTERMINAL") + assert facet.filter(ifc) == [element] + run("In IFC2X3 the type class is checked instead 1/2", facet=facet, inst=element, expected=True) + + facet = Entity(name="IFCELECTRICAPPLIANCE") + assert facet.filter(ifc) == [] + run("In IFC2X3 the type class is checked instead 2/2", facet=facet, inst=element, expected=False) + def test_to_string_required_applicability(self): spec = ifctester.ids.Specification(name="Foo", minOccurs=1, maxOccurs="unbounded") facet = Entity(name="IFCWALL")