2022-01-19 12:18:33 +11:00
# IfcOpenShell - IFC toolkit and geometry engine
# Copyright (C) 2021 Thomas Krijnen <thomas@aecgeeks.com>
#
# This file is part of IfcOpenShell.
#
# IfcOpenShell is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# IfcOpenShell is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
2021-07-09 08:44:36 +02:00
import os
2022-05-10 19:26:12 +10:00
import pytest
2021-08-24 12:57:44 +02:00
import logging
2021-08-31 14:10:43 +10:00
import unittest
import tempfile
2022-05-10 19:26:12 +10:00
import xmlschema
2021-09-24 17:18:38 +02:00
import ifcopenshell
2022-05-11 13:06:15 +10:00
import ifcopenshell . api
from bcf import bcfxml
2022-05-31 19:13:21 +10:00
from ifcopenshell import ids
2021-07-02 17:27:09 +02:00
2021-11-23 17:53:32 +01:00
IFC_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IFC/ " , " IFC4_Wall_3_with_properties.ifc " )
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_all_fields.xml " )
2021-07-02 17:27:09 +02:00
2021-11-23 17:53:32 +01:00
logger = logging . getLogger ( " IDS_Logger " )
# logging.basicConfig(level=logging.INFO, format="%(message)s")
# logging.basicConfig(filename=os.path.join(os.path.dirname(__file__), "log.txt"), level=logging.INFO, format="%(message)s")
file = open ( os . path . join ( tempfile . gettempdir ( ) , " test.ifc " ) , " w " )
file . write ( IFC_URL )
file . close ( )
ifc_file = ifcopenshell . open ( IFC_URL )
os . remove ( os . path . join ( tempfile . gettempdir ( ) , " test.ifc " ) )
2021-07-02 17:27:09 +02:00
2022-05-10 16:17:38 +10:00
2022-05-31 22:27:16 +10:00
def set_facet ( facet ) :
pass
def run ( name , * , facet , inst , expected ) :
2022-05-31 19:13:21 +10:00
assert bool ( facet ( inst ) ) is expected
2021-07-09 08:44:36 +02:00
class TestIdsParsing ( unittest . TestCase ) :
2021-08-24 12:57:44 +02:00
def test_parse_basic_ids ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2021-09-24 17:18:38 +02:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_all_fields.xml " )
ids_file = ids . ids . open ( IDS_URL )
2021-07-09 08:44:36 +02:00
self . assertEqual ( type ( ids_file ) . __name__ , " ids " )
2021-08-24 12:57:44 +02:00
def test_parse_entity_facet ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2021-09-24 17:18:38 +02:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_entity.xml " )
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " IfcWall " )
2021-07-02 17:27:09 +02:00
2022-02-23 00:24:40 +01:00
def test_parse_predefinedType_facet ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_predefinedtype.xml " )
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual (
2022-02-23 00:24:40 +01:00
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " predefinedType " ] [ " simpleValue " ] , " CLADDING "
2021-08-24 12:57:44 +02:00
)
2021-07-05 13:21:36 +02:00
2021-08-24 12:57:44 +02:00
def test_parse_property_facet ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2021-09-24 17:18:38 +02:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_property.xml " )
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual (
2022-02-23 00:24:40 +01:00
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " propertySet " ] [ " simpleValue " ] , " Test_PropertySet "
2021-08-24 12:57:44 +02:00
)
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " simpleValue " ] , " Test_Value " )
2021-07-05 13:21:36 +02:00
2021-08-24 12:57:44 +02:00
def test_parse_material_facet ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2021-09-24 17:18:38 +02:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_material.xml " )
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " simpleValue " ] , " Test_Material " )
2021-07-05 13:21:36 +02:00
2021-08-24 12:57:44 +02:00
def test_parse_classification_facet ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_classification.xml " )
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual (
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " simpleValue " ] , " Test_Classification "
)
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " system " ] [ " simpleValue " ] , " Test_System " )
2021-07-05 13:21:36 +02:00
2022-05-22 22:10:28 +10:00
def test_failing_on_opening_invalid_ids_data ( self ) :
with pytest . raises ( xmlschema . validators . exceptions . XMLSchemaValidationError ) :
ids . ids . open ( """ <?xml version= " 1.0 " encoding= " UTF-8 " ?><clearly_not_an_ids/> """ )
2021-07-02 17:27:09 +02:00
2021-07-09 08:44:36 +02:00
""" Saving parsed IDS to IDS.xml """
def test_parsed_ids_to_xml ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files " , " IDS " , " IDS_Wall_needs_all_fields.xml " )
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2022-05-10 16:22:12 +10:00
fn = " output.xml "
2021-07-09 08:44:36 +02:00
result = ids_file . to_xml ( fn )
2022-05-10 16:22:12 +10:00
assert os . path . isfile ( fn )
2021-07-09 08:44:36 +02:00
os . remove ( fn )
self . assertTrue ( result )
2022-05-10 16:22:12 +10:00
def test_parsed_ids_to_string ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:22:12 +10:00
IDS_URL = os . path . join ( os . path . dirname ( __file__ ) , " Sample-BIM-Files " , " IDS " , " IDS_Wall_needs_all_fields.xml " )
ids_file = ids . ids . open ( IDS_URL )
output = ids_file . to_string ( )
assert output and " http://standards.buildingsmart.org/IDS " in output
2021-08-24 12:57:44 +02:00
""" Parsing IDS files with restrictions """
def test_parse_restrictions_enumeration ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) ,
" Sample-BIM-Files/IDS/ " ,
" IDS_Wall_needs_property_with_restriction_enumeration.xml " ,
)
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
[
x [ " @value " ]
for x in ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " enumeration " ]
] ,
[ " testA " , " testB " ] ,
)
def test_parse_restrictions_bounds ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_property_with_restriction_bounds.xml "
)
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " minInclusive " ] [ " @value " ] ,
" 0 " ,
)
def test_parse_restrictions_pattern_simple ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_property_with_restriction_pattern.xml "
)
2021-09-24 17:18:38 +02:00
ids_file = ids . ids . open ( IDS_URL )
2021-08-24 12:57:44 +02:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " pattern " ] [ " @value " ] ,
" [A-Z] { 2,4} " ,
)
2021-07-09 08:44:36 +02:00
class TestIdsAuthoring ( unittest . TestCase ) :
2022-05-10 17:36:24 +10:00
def test_create_an_ids_with_minimal_information ( self ) :
2022-05-10 19:26:12 +10:00
specs = ids . ids ( )
assert specs . asdict ( ) == {
" @xmlns " : " http://standards.buildingsmart.org/IDS " ,
" @xmlns:xs " : " http://www.w3.org/2001/XMLSchema " ,
" @xmlns:xsi " : " http://www.w3.org/2001/XMLSchema-instance " ,
" @xsi:schemaLocation " : " http://standards.buildingsmart.org/IDS/ids_05.xsd " ,
" info " : { " title " : " Untitled " } ,
2022-05-31 15:35:47 +10:00
" specifications " : { " specification " : [ ] } ,
2022-05-10 19:26:12 +10:00
}
2022-05-10 17:36:24 +10:00
def test_create_an_ids_with_all_possible_information ( self ) :
specs = ids . ids (
title = " title " ,
copyright = " copyright " ,
version = " version " ,
description = " description " ,
author = " author@test.com " ,
date = " 2020-01-01 " ,
purpose = " purpose " ,
milestone = " milestone " ,
)
2022-05-10 19:26:12 +10:00
assert specs . asdict ( ) == {
" @xmlns " : " http://standards.buildingsmart.org/IDS " ,
" @xmlns:xs " : " http://www.w3.org/2001/XMLSchema " ,
" @xmlns:xsi " : " http://www.w3.org/2001/XMLSchema-instance " ,
" @xsi:schemaLocation " : " http://standards.buildingsmart.org/IDS/ids_05.xsd " ,
" info " : {
" title " : " title " ,
" copyright " : " copyright " ,
" version " : " version " ,
" description " : " description " ,
" author " : " author@test.com " ,
" date " : " 2020-01-01 " ,
" purpose " : " purpose " ,
" milestone " : " milestone " ,
} ,
2022-05-31 15:35:47 +10:00
" specifications " : { " specification " : [ ] } ,
2022-05-10 19:26:12 +10:00
}
2022-05-10 17:36:24 +10:00
def test_check_invalid_ids_information ( self ) :
2022-05-10 19:26:12 +10:00
specs = ids . ids ( title = None , author = " author " , date = " 9999-99-99 " )
assert specs . asdict ( ) == {
" @xmlns " : " http://standards.buildingsmart.org/IDS " ,
" @xmlns:xs " : " http://www.w3.org/2001/XMLSchema " ,
" @xmlns:xsi " : " http://www.w3.org/2001/XMLSchema-instance " ,
" @xsi:schemaLocation " : " http://standards.buildingsmart.org/IDS/ids_05.xsd " ,
" info " : { " title " : " Untitled " } ,
2022-05-31 15:35:47 +10:00
" specifications " : { " specification " : [ ] } ,
2022-05-10 19:26:12 +10:00
}
def test_authoring_an_ids_with_no_specifications_is_invalid ( self ) :
specs = ids . ids ( )
with pytest . raises ( xmlschema . validators . exceptions . XMLSchemaChildrenValidationError ) :
specs . to_string ( )
def test_create_specification_with_minimal_information ( self ) :
spec = ids . specification ( )
assert spec . asdict ( ) == {
" @name " : " Unnamed " ,
2022-05-10 22:13:28 +10:00
" @ifcVersion " : [ " IFC2X3 " , " IFC4 " ] ,
2022-05-10 19:26:12 +10:00
" applicability " : { } ,
" requirements " : { } ,
}
def test_create_specification_with_all_possible_information ( self ) :
spec = ids . specification (
name = " name " ,
2022-05-31 15:35:47 +10:00
minOccurs = " 0 " ,
maxOccurs = " unbounded " ,
2022-05-10 22:13:28 +10:00
ifcVersion = " IFC4 " ,
2022-05-10 19:26:12 +10:00
identifier = " identifier " ,
description = " description " ,
instructions = " instructions " ,
)
assert spec . asdict ( ) == {
" @name " : " name " ,
2022-05-31 15:35:47 +10:00
" @minOccurs " : " 0 " ,
" @maxOccurs " : " unbounded " ,
2022-05-10 22:13:28 +10:00
" @ifcVersion " : " IFC4 " ,
2022-05-10 19:26:12 +10:00
" @identifier " : " identifier " ,
" @description " : " description " ,
" @instructions " : " instructions " ,
" applicability " : { } ,
" requirements " : { } ,
}
2022-05-22 22:10:28 +10:00
def test_creating_an_entity_facet ( self ) :
2022-05-10 21:20:10 +10:00
facet = ids . entity . create ( name = " IfcName " )
assert facet . asdict ( ) == { " name " : { " simpleValue " : " IfcName " } }
2022-05-22 22:10:28 +10:00
facet = ids . entity . create ( name = " IfcName " , predefinedType = " predefinedType " , instructions = " instructions " )
2022-05-10 21:20:10 +10:00
assert facet . asdict ( ) == {
" name " : { " simpleValue " : " IfcName " } ,
" predefinedType " : { " simpleValue " : " predefinedType " } ,
2022-05-22 22:10:28 +10:00
" @instructions " : " instructions " ,
2022-05-10 21:20:10 +10:00
}
def test_filtering_using_an_entity_facet ( self ) :
2022-05-31 22:27:16 +10:00
set_facet ( " entity " )
2022-05-10 21:20:10 +10:00
ifc = ifcopenshell . file ( )
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCRABBIT " )
2022-05-31 22:27:16 +10:00
run ( " Invalid entities always fail " , facet = facet , inst = ifc . createIfcWall ( ) , expected = False )
2022-05-11 13:06:15 +10:00
2022-05-31 19:13:21 +10:00
facet = ids . entity . create ( name = " IFCWALL " )
2022-05-31 22:27:16 +10:00
run ( " A matching entity should pass " , facet = facet , inst = ifc . createIfcWall ( ) , expected = True )
run (
2022-05-31 19:13:21 +10:00
" An matching entity should pass regardless of predefined type " ,
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " SOLIDWALL " ) ,
expected = True ,
)
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" An entity not matching the specified class should fail " ,
facet = facet ,
inst = ifc . createIfcSlab ( ) ,
expected = False ,
)
2022-05-22 22:10:28 +10:00
# TODO: Some votes to prefer inheritance (For: Moult, Evandro, Artur)
# Possible argument: CAD tools don't understand IFC
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" Subclasses are not considered as matching " ,
facet = facet ,
inst = ifc . createIfcWallStandardCase ( ) ,
expected = False ,
2022-05-17 22:21:11 +02:00
)
2022-05-10 21:20:10 +10:00
2022-05-31 16:22:44 +10:00
# TODO But in that case why are the enumerations for things like partOf using the IFC capitalisation?
facet = ids . entity . create ( name = " IfcWall " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" Entities must be specified as uppercase strings " ,
facet = facet ,
inst = ifc . createIfcWall ( ) ,
expected = False ,
)
2022-05-10 21:40:35 +10:00
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " SOLIDWALL " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A matching predefined type should pass " ,
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " SOLIDWALL " ) ,
expected = True ,
)
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A null predefined type should always fail a specified predefined types " ,
facet = facet ,
inst = ifc . createIfcWall ( ) ,
expected = False ,
)
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" An entity not matching a specified predefined type will fail " ,
2022-05-17 22:21:11 +02:00
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " PARTITIONING " ) ,
expected = False ,
)
2022-05-10 21:20:10 +10:00
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " solidwall " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A predefined type from an enumeration must be uppercase " ,
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " SOLIDWALL " ) ,
expected = False ,
)
2022-05-22 22:10:28 +10:00
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " WALDO " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A predefined type may specify a user-defined object type " ,
2022-05-17 22:21:11 +02:00
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " USERDEFINED " , ObjectType = " WALDO " ) ,
expected = True ,
)
2022-05-10 21:20:10 +10:00
2022-05-31 19:13:21 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " WALDO " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" User-defined types are checked case sensitively " ,
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " USERDEFINED " , ObjectType = " waldo " ) ,
expected = False ,
)
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALLTYPE " , predefinedType = " WALDO " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A predefined type may specify a user-defined element type " ,
2022-05-17 22:21:11 +02:00
facet = facet ,
inst = ifc . createIfcWallType ( PredefinedType = " USERDEFINED " , ElementType = " WALDO " ) ,
expected = True ,
)
2021-07-09 08:44:36 +02:00
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCTASKTYPE " , predefinedType = " TASKY " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A predefined type may specify a user-defined process type " ,
2022-05-31 16:22:44 +10:00
facet = facet ,
inst = ifc . createIfcTaskType ( PredefinedType = " USERDEFINED " , ProcessType = " TASKY " ) ,
expected = True ,
)
2022-05-22 22:10:28 +10:00
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " USERDEFINED " )
2022-05-31 22:27:16 +10:00
run (
2022-05-31 19:13:21 +10:00
" A predefined type must always specify a meaningful type, not USERDEFINED itself " ,
2022-05-17 22:21:11 +02:00
facet = facet ,
inst = ifc . createIfcWall ( PredefinedType = " USERDEFINED " , ObjectType = " WALDO " ) ,
expected = False ,
)
2022-05-11 10:12:36 +10:00
2022-05-11 13:06:15 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
wall_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " , predefined_type = " X " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " X " )
2022-05-31 22:27:16 +10:00
run ( " Inherited predefined types should pass " , facet = facet , inst = wall , expected = True )
2022-05-11 13:06:15 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " , predefined_type = " X " )
2022-05-11 13:27:19 +10:00
wall_type = ifcopenshell . api . run (
" root.create_entity " , ifc , ifc_class = " IfcWallType " , predefined_type = " NOTDEFINED "
)
2022-05-11 13:06:15 +10:00
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = " X " )
2022-05-31 22:27:16 +10:00
run ( " Overridden predefined types should pass " , facet = facet , inst = wall , expected = True )
2022-05-11 13:06:15 +10:00
2022-05-31 16:22:44 +10:00
restriction = ids . restriction . create ( options = [ " IFCWALL " , " IFCSLAB " ] , type = " enumeration " )
2022-05-10 21:40:35 +10:00
facet = ids . entity . create ( name = restriction )
2022-05-31 22:27:16 +10:00
run ( " Entities can be specified as an enumeration 1/3 " , facet = facet , inst = ifc . createIfcWall ( ) , expected = True )
run ( " Entities can be specified as an enumeration 2/3 " , facet = facet , inst = ifc . createIfcSlab ( ) , expected = True )
run ( " Entities can be specified as an enumeration 3/3 " , facet = facet , inst = ifc . createIfcBeam ( ) , expected = False )
2022-05-10 21:40:35 +10:00
2022-05-31 16:22:44 +10:00
restriction = ids . restriction . create ( options = " IFC.*TYPE " , type = " pattern " )
2022-05-10 21:40:35 +10:00
facet = ids . entity . create ( name = restriction )
2022-06-21 17:00:46 +10:00
run ( " Entities can be specified as a XSD regex pattern 1/2 " , facet = facet , inst = ifc . createIfcWall ( ) , expected = False )
run ( " Entities can be specified as a XSD regex pattern 2/2 " , facet = facet , inst = ifc . createIfcWallType ( ) , expected = True )
2022-05-10 21:40:35 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " FOO.* " , type = " pattern " )
2022-05-31 16:22:44 +10:00
facet = ids . entity . create ( name = " IFCWALL " , predefinedType = restriction )
2022-05-11 13:06:15 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " , predefined_type = " FOOBAR " )
wall2 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " , predefined_type = " FOOBAZ " )
2022-05-22 22:10:28 +10:00
wall3 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " , predefined_type = " BAZFOO " )
2022-05-31 22:27:16 +10:00
run ( " Restrictions an be specified for the predefined type 1/3 " , facet = facet , inst = wall , expected = True )
run ( " Restrictions an be specified for the predefined type 2/3 " , facet = facet , inst = wall2 , expected = True )
run ( " Restrictions an be specified for the predefined type 3/3 " , facet = facet , inst = wall3 , expected = False )
2022-05-11 13:06:15 +10:00
2022-05-10 22:42:21 +10:00
def test_creating_an_attribute_facet ( self ) :
2022-05-11 10:12:36 +10:00
attribute = ids . attribute . create ( name = " name " )
2022-05-31 15:35:47 +10:00
assert attribute . asdict ( ) == { " name " : { " simpleValue " : " name " } }
attribute = ids . attribute . create ( name = " name " , value = " value " )
assert attribute . asdict ( ) == { " name " : { " simpleValue " : " name " } , " value " : { " simpleValue " : " value " } }
2022-05-11 13:27:19 +10:00
attribute = ids . attribute . create (
2022-05-31 15:35:47 +10:00
name = " name " , value = " value " , minOccurs = " 0 " , maxOccurs = " unbounded " , instructions = " instructions "
2022-05-11 13:27:19 +10:00
)
2022-05-11 10:12:36 +10:00
assert attribute . asdict ( ) == {
" name " : { " simpleValue " : " name " } ,
" value " : { " simpleValue " : " value " } ,
2022-05-31 15:35:47 +10:00
" @minOccurs " : " 0 " ,
" @maxOccurs " : " unbounded " ,
2022-05-11 10:12:36 +10:00
" @instructions " : " instructions " ,
}
2022-05-10 16:23:07 +10:00
2022-05-10 22:42:21 +10:00
def test_filtering_using_an_attribute_facet ( self ) :
2022-05-31 22:27:16 +10:00
set_facet ( " attribute " )
2022-05-10 22:42:21 +10:00
ifc = ifcopenshell . file ( )
facet = ids . attribute . create ( name = " Foobar " )
2022-05-31 22:27:16 +10:00
run ( " Invalid attribute names always fail " , facet = facet , inst = ifc . createIfcWall ( ) , expected = False )
2022-05-10 22:42:21 +10:00
facet = ids . attribute . create ( name = " Name " )
2022-05-31 22:27:16 +10:00
run ( " Attributes with a string value should pass " , facet = facet , inst = ifc . createIfcWall ( Name = " Foobar " ) , expected = True )
run ( " Attributes with null values always fail " , facet = facet , inst = ifc . createIfcWall ( ) , expected = False )
# The logic is that unfortunately most BIM users cannot differentiate between the two.
run ( " Attributes with empty strings always fail " , facet = facet , inst = ifc . createIfcWall ( Name = " " ) , expected = False )
facet = ids . attribute . create ( name = " CountValue " )
run ( " Attributes with a zero number have meaning and should pass " , facet = facet , inst = ifc . createIfcQuantityCount ( Name = " Foobar " , CountValue = 0 ) , expected = True )
facet = ids . attribute . create ( name = " IsCritical " )
element = ifc . createIfcTaskTime ( IsCritical = True )
run ( " Attributes with a boolean true should pass " , facet = facet , inst = element , expected = True )
element . IsCritical = False
run ( " Attributes with a boolean false should pass " , facet = facet , inst = element , expected = True )
facet = ids . attribute . create ( name = " RelatingPriorities " )
run ( " Attributes with an empty list always fail " , facet = facet , inst = ifc . createIfcRelConnectsPathElements ( RelatingElement = ifc . createIfcWall ( ) , RelatedElement = ifc . createIfcWall ( ) , RelatingPriorities = [ ] , RelatedPriorities = [ ] , RelatedConnectionType = " ATSTART " , RelatingConnectionType = " ATEND " ) , expected = False )
facet = ids . attribute . create ( name = " LayerStyles " )
item = ifc . createIfcCartesianPoint ( [ 0. , 0. , 0. ] )
layer = ifc . createIfcPresentationLayerWithStyle ( " Foo " , None , [ item ] , None , True , False , False , [ ] )
run ( " Attributes with an empty set always fail " , facet = facet , inst = layer , expected = False )
layer . LayerOn = " UNKNOWN "
facet = ids . attribute . create ( name = " LayerOn " )
run ( " Attributes with a logical unknown always fail " , facet = facet , inst = layer , expected = False )
facet = ids . attribute . create ( name = " ScheduleDuration " )
element = ifc . createIfcTaskTime ( ScheduleDuration = " P0D " )
run ( " Attributes with a zero duration should pass " , facet = facet , inst = element , expected = True )
facet = ids . attribute . create ( name = " TaskTime " )
element = ifc . createIfcTask ( IsMilestone = True , TaskTime = ifc . createIfcTaskTime ( ) )
run ( " Attributes referencing an object should pass " , facet = facet , inst = element , expected = True )
2022-05-22 22:10:28 +10:00
facet = ids . attribute . create ( name = " DiffuseColour " )
element = ifc . createIfcSurfaceStyleRendering ( )
2022-05-31 22:27:16 +10:00
rgb = ifc . createIfcColourRgb ( None , 1 , 1 , 1 )
run ( " Attributes with a select referencing an object should pass " , facet = facet , inst = ifc . createIfcSurfaceStyleRendering ( SurfaceColour = rgb , ReflectanceMethod = " FLAT " , DiffuseColour = ifc . createIfcColourRgb ( None , 1 , 1 , 1 ) ) , expected = True )
run ( " Attributes with a select referencing a primitive should pass " , facet = facet , inst = ifc . createIfcSurfaceStyleRendering ( SurfaceColour = rgb , ReflectanceMethod = " FLAT " , DiffuseColour = ifc . createIfcNormalisedRatioMeasure ( 0.5 ) ) , expected = True )
2022-05-10 22:42:21 +10:00
2022-06-21 17:00:46 +10:00
facet = ids . attribute . create ( name = " EngagedIn " )
person = ifc . createIfcPerson ( )
organisation = ifc . createIfcOrganization ( Name = " Foo " )
ifc . createIfcPersonAndOrganization ( ThePerson = person , TheOrganization = organisation )
run ( " Inverse attributes cannot be checked and always fail " , facet = facet , inst = person , expected = False )
facet = ids . attribute . create ( name = " Dim " )
run ( " Derived attributes cannot be checked and always fail " , facet = facet , inst = ifc . createIfcCartesianPoint ( [ 0. , 0. , 0. ] ) , expected = False )
2022-05-10 22:42:21 +10:00
facet = ids . attribute . create ( name = " Name " , value = " Foobar " )
2022-05-31 22:27:16 +10:00
run ( " Attributes should check strings case sensitively 1/2 " , facet = facet , inst = ifc . createIfcWall ( Name = " Foobar " ) , expected = True )
run ( " Attributes should check strings case sensitively 2/2 " , facet = facet , inst = ifc . createIfcWall ( Name = " foobar " ) , expected = False )
2022-05-10 22:42:21 +10:00
2022-06-21 17:00:46 +10:00
facet = ids . attribute . create ( name = " TaskTime " , value = " Foobar " )
run ( " Value checks always fail for objects " , facet = facet , inst = ifc . createIfcTask ( IsMilestone = False , TaskTime = ifc . createIfcTaskTime ( ) ) , expected = False )
2022-05-22 22:10:28 +10:00
2022-06-21 17:00:46 +10:00
rgb = ifc . createIfcColourRgb ( None , 1 , 1 , 1 )
facet = ids . attribute . create ( name = " DiffuseColour " , value = " Foobar " )
run ( " Value checks always fail for selects " , facet = facet , inst = ifc . createIfcSurfaceStyleRendering ( SurfaceColour = rgb , ReflectanceMethod = " FLAT " , DiffuseColour = ifc . createIfcNormalisedRatioMeasure ( 0.5 ) ) , expected = False )
2022-05-22 22:10:28 +10:00
2022-06-21 17:00:46 +10:00
facet = ids . attribute . create ( name = " Coordinates " , value = " Foobar " )
run ( " Value checks always fail for lists " , facet = facet , inst = ifc . createIfcCartesianPoint ( [ 0. , 0. , 0. ] ) , expected = False )
2022-05-22 22:10:28 +10:00
# TODO continue from here
2022-06-21 17:00:46 +10:00
global_id = ifcopenshell . guid . new ( )
facet = ids . attribute . create ( name = " GlobalId " , value = global_id )
run ( " GlobalIds are treated as strings and not expanded " , facet = facet , inst = ifc . createIfcWall ( GlobalId = global_id ) , expected = True )
# 255 characters
identifier = " 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 "
facet = ids . attribute . create ( name = " Identification " , value = identifier + " _extra_characters " )
run ( " IDS does not bother with string truncation such as for identifiers " , facet = facet , inst = ifc . createIfcPerson ( Identification = identifier ) , expected = False )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 42 " )
run ( " Numeric values are checked using type casting 1/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42 ) , expected = True )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 42. " )
run ( " Numeric values are checked using type casting 2/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42.0 ) , expected = True )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 42.0 " )
run ( " Numeric values are checked using type casting 3/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42.0 ) , expected = True )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 42 " )
run ( " Numeric values are checked using type casting 4/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42.3 ) , expected = False )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 42,3 " )
run ( " Only specifically formatted numbers are allowed 1/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42.3 ) , expected = False )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 123,4.5 " )
run ( " Only specifically formatted numbers are allowed 2/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 1234.5 ) , expected = False )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 1.2345e3 " )
run ( " Only specifically formatted numbers are allowed 3/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 1234.5 ) , expected = True )
facet = ids . attribute . create ( name = " RefractionIndex " , value = " 1.2345E3 " )
run ( " Only specifically formatted numbers are allowed 3/4 " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 1234.5 ) , expected = True )
facet = ids . attribute . create ( name = " NumberOfRisers " , value = " 42 " )
run ( " Integers follow the same rules as numbers " , facet = facet , inst = ifc . createIfcStairFlight ( NumberOfRisers = 42 ) , expected = True )
facet = ids . attribute . create ( name = " NumberOfRisers " , value = " 42.0 " )
run ( " Integers follow the same rules as numbers 2/2 " , facet = facet , inst = ifc . createIfcStairFlight ( NumberOfRisers = 42 ) , expected = True )
facet = ids . attribute . create ( name = " NumberOfRisers " , value = " 42.3 " )
run ( " Integers are always floored when cast 1/2 " , facet = facet , inst = ifc . createIfcStairFlight ( NumberOfRisers = 42 ) , expected = True )
facet = ids . attribute . create ( name = " NumberOfRisers " , value = " 42.7 " )
run ( " Integers are always floored when cast 2/2 " , facet = facet , inst = ifc . createIfcStairFlight ( NumberOfRisers = 42 ) , expected = True )
facet = ids . attribute . create ( name = " NumberOfRisers " , value = " 42.7 " )
run ( " Integers are always floored when cast 2/2 " , facet = facet , inst = ifc . createIfcStairFlight ( NumberOfRisers = 42 ) , expected = True )
facet = ids . attribute . create ( name = " IsMilestone " , value = " TRUE " )
element = ifc . createIfcTask ( IsMilestone = False )
run ( " Booleans must be specified as uppercase strings 1/3 " , facet = facet , inst = element , expected = False )
facet = ids . attribute . create ( name = " IsMilestone " , value = " FALSE " )
run ( " Booleans must be specified as uppercase strings 2/3 " , facet = facet , inst = element , expected = True )
facet = ids . attribute . create ( name = " IsMilestone " , value = " False " )
run ( " Booleans must be specified as uppercase strings 2/3 " , facet = facet , inst = element , expected = False )
facet = ids . attribute . create ( name = " EditionDate " , value = " 2022-01-01 " )
run ( " Dates are treated as strings 1/2 " , facet = facet , inst = ifc . createIfcClassification ( Name = " Name " , EditionDate = " 2022-01-01 " ) , expected = True )
run ( " Dates are treated as strings 1/2 " , facet = facet , inst = ifc . createIfcClassification ( Name = " Name " , EditionDate = " 2022-01-01+00:00 " ) , expected = False )
facet = ids . attribute . create ( name = " ScheduleDuration " , value = " PT16H " )
run ( " Durations are treated as strings 1/2 " , facet = facet , inst = ifc . createIfcClassification ( Name = " Name " , EditionDate = " PT16H " ) , expected = False )
run ( " Durations are treated as strings 2/2 " , facet = facet , inst = ifc . createIfcClassification ( Name = " Name " , EditionDate = " P2D " ) , expected = False )
2022-05-22 22:10:28 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " .*Name.* " , type = " pattern " )
2022-05-11 13:06:15 +10:00
facet = ids . attribute . create ( name = restriction )
2022-06-21 17:00:46 +10:00
run ( " Name restrictions may be used 1/4 " , facet = facet , inst = ifc . createIfcMaterialLayerSet ( MaterialLayers = [ ifc . createIfcMaterialLayer ( LayerThickness = 1 ) ] , LayerSetName = " Foo " ) , expected = True )
run ( " Name restrictions may be used 2/4 " , facet = facet , inst = ifc . createIfcMaterialConstituentSet ( Name = " Foo " ) , expected = True )
2022-05-11 13:06:15 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = [ " Name " , " Description " ] , type = " enumeration " )
2022-05-11 13:06:15 +10:00
facet = ids . attribute . create ( name = restriction )
2022-06-21 17:00:46 +10:00
run ( " Name restrictions may be used 3/4 " , facet = facet , inst = ifc . createIfcWall ( Name = " Foo " ) , expected = False )
run ( " Name restrictions may be used 4/4 " , facet = facet , inst = ifc . createIfcWall ( Name = " Foo " , Description = " Bar " ) , expected = True )
2022-05-11 13:06:15 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = [ " Foo " , " Bar " ] , type = " enumeration " )
2022-05-10 22:42:21 +10:00
facet = ids . attribute . create ( name = " Name " , value = restriction )
2022-06-21 17:00:46 +10:00
run ( " Value restrictions may be used 1/3 " , facet = facet , inst = ifc . createIfcWall ( Name = " Foo " ) , expected = True )
run ( " Value restrictions may be used 2/3 " , facet = facet , inst = ifc . createIfcWall ( Name = " Bar " ) , expected = True )
run ( " Value restrictions may be used 3/3 " , facet = facet , inst = ifc . createIfcWall ( Name = " Foobar " ) , expected = False )
2022-05-11 13:06:15 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
wall_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
wall_type . Description = " Foobar "
2022-06-21 17:00:46 +10:00
run ( " Attributes are not inherited by the occurrence " , facet = facet , inst = wall , expected = False )
2022-05-11 13:06:15 +10:00
2022-06-21 17:00:46 +10:00
restriction = ids . restriction . create ( options = [ " 42 " ] , type = " enumeration " , base = " string " )
facet = ids . attribute . create ( name = " RefractionIndex " , value = restriction )
run ( " Typecast checking may also occur within enumeration restrictions " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42 ) , expected = True )
restriction = ids . restriction . create (
options = { " minInclusive " : 42 , " maxInclusive " : 42 } , type = " bounds " , base = " decimal "
)
facet = ids . attribute . create ( name = " RefractionIndex " , value = restriction )
run ( " Strict numeric checking may be done with a bounds restriction " , facet = facet , inst = ifc . createIfcSurfaceStyleRefraction ( RefractionIndex = 42 ) , expected = True )
2022-05-11 13:06:15 +10:00
def test_creating_a_classification_facet ( self ) :
2022-05-11 13:27:19 +10:00
facet = ids . classification . create ( )
2022-05-31 15:35:47 +10:00
assert facet . asdict ( ) == { }
facet = ids . classification . create ( value = " value " , system = " system " )
assert facet . asdict ( ) == { " value " : { " simpleValue " : " value " } , " system " : { " simpleValue " : " system " } }
2022-05-11 13:27:19 +10:00
facet = ids . classification . create (
value = " value " ,
system = " system " ,
uri = " https://test.com " ,
2022-05-31 15:35:47 +10:00
minOccurs = " 0 " ,
maxOccurs = " unbounded " ,
2022-05-11 13:27:19 +10:00
instructions = " instructions " ,
)
assert facet . asdict ( ) == {
" value " : { " simpleValue " : " value " } ,
" system " : { " simpleValue " : " system " } ,
" @uri " : " https://test.com " ,
2022-05-31 15:35:47 +10:00
" @minOccurs " : " 0 " ,
" @maxOccurs " : " unbounded " ,
2022-05-11 13:27:19 +10:00
" @instructions " : " instructions " ,
}
2021-07-09 08:44:36 +02:00
2022-05-11 14:49:47 +10:00
def test_filtering_using_a_classification_facet ( self ) :
2022-06-21 17:00:46 +10:00
set_facet ( " classification " )
2022-05-11 14:49:47 +10:00
library = ifcopenshell . file ( )
system = library . createIfcClassification ( Name = " Foobar " )
ref1 = library . createIfcClassificationReference ( Identification = " 1 " , ReferencedSource = system )
ref11 = library . createIfcClassificationReference ( Identification = " 11 " , ReferencedSource = ref1 )
ref2 = library . createIfcClassificationReference ( Identification = " 2 " , ReferencedSource = system )
ref22 = library . createIfcClassificationReference ( Identification = " 22 " , ReferencedSource = ref2 )
ifc = ifcopenshell . file ( )
project = ifc . createIfcProject ( )
ifcopenshell . api . run ( " classification.add_classification " , ifc , classification = system )
element0 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
element1 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
ifcopenshell . api . run (
" classification.add_reference " , ifc , product = element1 , reference = ref1 , classification = system
)
element11 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
ifcopenshell . api . run (
" classification.add_reference " , ifc , product = element11 , reference = ref11 , classification = system
)
element22 = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
ifcopenshell . api . run (
" classification.add_reference " ,
ifc ,
product = element22 ,
reference = ref22 ,
classification = system ,
is_lightweight = False ,
)
facet = ids . classification . create ( )
2022-06-21 17:00:46 +10:00
run ( " A classification facet with no data matches any classification 1/2 " , facet = facet , inst = element0 , expected = False )
run ( " A classification facet with no data matches any classification 2/2 " , facet = facet , inst = element1 , expected = True )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( value = " 1 " )
2022-06-21 17:00:46 +10:00
run ( " Values should match exactly if lightweight classifications are used " , facet = facet , inst = element1 , expected = True )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( value = " 2 " )
2022-06-21 17:00:46 +10:00
run ( " Values match subreferences if full classifications are used (e.g. EF_25_10 should match EF_25_10_25, EF_25_10_30, etc) " , facet = facet , inst = element22 , expected = True )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( system = " Foobar " )
2022-06-21 17:00:46 +10:00
run ( " Systems should match exactly 1/5 " , facet = facet , inst = project , expected = True )
run ( " Systems should match exactly 2/5 " , facet = facet , inst = element0 , expected = False )
run ( " Systems should match exactly 3/5 " , facet = facet , inst = element1 , expected = True )
run ( " Systems should match exactly 4/5 " , facet = facet , inst = element11 , expected = True )
run ( " Systems should match exactly 5/5 " , facet = facet , inst = element22 , expected = True )
2022-05-11 14:49:47 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " 1.* " , type = " pattern " )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( value = restriction )
2022-06-21 17:00:46 +10:00
run ( " Restrictions can be used for values 1/3 " , facet = facet , inst = element1 , expected = True )
run ( " Restrictions can be used for values 2/3 " , facet = facet , inst = element11 , expected = True )
run ( " Restrictions can be used for values 3/3 " , facet = facet , inst = element22 , expected = False )
2022-05-11 14:49:47 +10:00
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " Foo.* " , type = " pattern " )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( system = restriction )
2022-06-21 17:00:46 +10:00
run ( " Restrictions can be used for systems 1/2 " , facet = facet , inst = element0 , expected = False )
run ( " Restrictions can be used for systems 2/2 " , facet = facet , inst = element1 , expected = True )
2022-05-11 14:49:47 +10:00
facet = ids . classification . create ( system = " Foobar " , value = " 1 " )
2022-06-21 17:00:46 +10:00
run ( " Both system and value must match (all, not any) if specified 1/2 " , facet = facet , inst = element1 , expected = True )
run ( " Both system and value must match (all, not any) if specified 2/2 " , facet = facet , inst = element11 , expected = False )
2022-05-11 14:49:47 +10:00
2022-05-31 15:35:47 +10:00
# The facet checks on either the type or instance.
2022-05-11 14:49:47 +10:00
# IFC doesn't specify how inheritance and overrides work here. Two options:
# Option 1) Occurrences replace inherited type references
# Option 2) Occurrences union with inherited type references
# Option 2 is followed here.
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
wall_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
2022-05-11 18:46:27 +10:00
ifcopenshell . api . run ( " classification.add_reference " , ifc , product = wall , reference = ref11 , classification = system )
2022-05-11 14:49:47 +10:00
ifcopenshell . api . run (
" classification.add_reference " , ifc , product = wall_type , reference = ref22 , classification = system
)
2022-05-31 15:35:47 +10:00
facet = ids . classification . create ( value = " 11 " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = wall , expected = True )
run ( " " , facet = facet , inst = wall_type , expected = False )
2022-05-31 15:35:47 +10:00
facet = ids . classification . create ( value = " 22 " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = wall , expected = True )
run ( " " , facet = facet , inst = wall_type , expected = True )
2022-05-11 14:49:47 +10:00
2022-05-11 15:30:39 +10:00
def test_creating_a_property_facet ( self ) :
facet = ids . property . create ( )
assert facet . asdict ( ) == {
" propertySet " : { " simpleValue " : " Property_Set " } ,
" name " : { " simpleValue " : " PropertyName " } ,
}
2022-05-11 18:46:27 +10:00
facet = ids . property . create (
propertySet = " propertySet " ,
name = " name " ,
value = " value " ,
measure = " String " ,
uri = " https://test.com " ,
2022-05-31 15:35:47 +10:00
minOccurs = " 0 " ,
maxOccurs = " unbounded " ,
2022-05-11 18:46:27 +10:00
instructions = " instructions " ,
)
2022-05-11 15:30:39 +10:00
assert facet . asdict ( ) == {
" propertySet " : { " simpleValue " : " propertySet " } ,
" name " : { " simpleValue " : " name " } ,
" value " : { " simpleValue " : " value " } ,
" @measure " : " String " ,
" @uri " : " https://test.com " ,
2022-05-31 15:35:47 +10:00
" @minOccurs " : " 0 " ,
" @maxOccurs " : " unbounded " ,
2022-05-11 15:30:39 +10:00
" @instructions " : " instructions " ,
}
2021-07-09 08:44:36 +02:00
2022-05-11 17:10:22 +10:00
def test_filtering_using_a_property_facet ( self ) :
ifc = ifcopenshell . file ( )
2022-05-11 19:59:10 +10:00
ifc . createIfcProject ( )
# Milli prefix used to check measurement conversions
lengthunit = ifcopenshell . api . run ( " unit.add_si_unit " , ifc , unit_type = " LENGTHUNIT " , name = " METRE " , prefix = " MILLI " )
2022-05-11 23:30:10 +10:00
areaunit = ifcopenshell . api . run (
" unit.add_si_unit " , ifc , unit_type = " AREAUNIT " , name = " SQUARE_METRE " , prefix = " MILLI "
)
volumeunit = ifcopenshell . api . run (
" unit.add_si_unit " , ifc , unit_type = " VOLUMEUNIT " , name = " CUBIC_METRE " , prefix = " MILLI "
)
2022-05-11 19:59:10 +10:00
timeunit = ifcopenshell . api . run ( " unit.add_si_unit " , ifc , unit_type = " TIMEUNIT " , name = " SECOND " )
ifcopenshell . api . run ( " unit.assign_unit " , ifc , units = [ lengthunit , areaunit , volumeunit , timeunit ] )
2022-05-11 17:10:22 +10:00
# A name check by itself only checks that a property is non-null and non empty string
# The logic is that unfortunately most BIM users cannot differentiate between the two.
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : None } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
# A simple value checks an exact case-sensitive match
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " , value = " Bar " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Baz " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
# Simple values only check string matches
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " , value = " 1 " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " 1 " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : ifc . createIfcInteger ( 1 ) } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
# Restrictions are supported for property sets. If multiple are matched, all must satisfy requirements.
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " Foo_.* " , type = " pattern " )
2022-05-11 17:10:22 +10:00
facet = ids . property . create ( propertySet = restriction , name = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Baz " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
# Restrictions are supported for names. If multiple are matched, all must satisfy requirements.
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = " Foo.* " , type = " pattern " )
2022-05-11 17:10:22 +10:00
facet = ids . property . create ( propertySet = " Foo_Bar " , name = restriction , value = " x " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : " x " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : " x " , " Foobaz " : " x " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : " x " , " Foobaz " : " y " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
# Restrictions are supported for values. If multiple are matched, all must satisfy requirements.
2022-05-11 18:46:27 +10:00
restriction1 = ids . restriction . create ( options = " Foo.* " , type = " pattern " )
restriction2 = ids . restriction . create ( options = [ " x " , " y " ] , type = " enumeration " )
2022-05-11 17:10:22 +10:00
facet = ids . property . create ( propertySet = " Foo_Bar " , name = restriction1 , value = restriction2 )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : " x " , " Foobaz " : " y " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 17:10:22 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : " x " , " Foobaz " : " z " } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 17:10:22 +10:00
2022-05-11 18:46:27 +10:00
# Restrictions may be used to check basic data primitives
restriction = ids . restriction . create ( options = [ 42.12 ] , type = " enumeration " , base = " decimal " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foobar " , value = restriction )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : 42.12 } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = [ 42 ] , type = " enumeration " , base = " integer " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foobar " , value = restriction )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 18:46:27 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : 42 } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 18:46:27 +10:00
restriction = ids . restriction . create ( options = [ True ] , type = " enumeration " , base = " boolean " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foobar " , value = restriction )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 18:46:27 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : True } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 18:46:27 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : False } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 18:46:27 +10:00
2022-05-11 19:59:10 +10:00
# When measure is not specified, no unit conversion is done and only primitives are checked
restriction = ids . restriction . create ( options = [ 42.12 ] , type = " enumeration " , base = " decimal " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foobar " , value = restriction )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foobar " : 42.12 } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 19:59:10 +10:00
# Measure may be used to specify an IFC data type
restriction = ids . restriction . create ( options = [ 2 ] , type = " enumeration " , base = " decimal " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " , value = restriction , measure = " Time " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : ifc . createIfcMassMeasure ( 2 ) } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 19:59:10 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : ifc . createIfcTimeMeasure ( 2 ) } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 19:59:10 +10:00
# Measure also implies that a unit matters, and so a conversion shall take place to SI units
restriction = ids . restriction . create ( options = [ 2 ] , type = " enumeration " , base = " decimal " )
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " , value = restriction , measure = " Length " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = element , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : ifc . createIfcLengthMeasure ( 2 ) } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-11 19:59:10 +10:00
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : ifc . createIfcLengthMeasure ( 2000 ) } )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-11 19:59:10 +10:00
2022-05-31 15:35:47 +10:00
# The facet checks inherited properties from the type
2022-05-11 17:10:22 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
wall_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = wall_type , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 15:35:47 +10:00
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = wall , expected = True )
run ( " " , facet = facet , inst = wall_type , expected = True )
2022-05-11 17:10:22 +10:00
2022-05-31 15:35:47 +10:00
# The facet checks overriden properties from the occurrence
2022-05-11 17:10:22 +10:00
wall = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
wall_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = wall , relating_type = wall_type )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = wall_type , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Baz " } )
pset = ifcopenshell . api . run ( " pset.add_pset " , ifc , product = wall , name = " Foo_Bar " )
ifcopenshell . api . run ( " pset.edit_pset " , ifc , pset = pset , properties = { " Foo " : " Bar " } )
2022-05-31 15:35:47 +10:00
facet = ids . property . create ( propertySet = " Foo_Bar " , name = " Foo " , value = " Bar " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = wall , expected = True )
run ( " " , facet = facet , inst = wall_type , expected = False )
2022-05-11 17:10:22 +10:00
2022-05-22 22:10:28 +10:00
def test_creating_a_material_facet ( self ) :
2022-05-11 23:30:10 +10:00
facet = ids . material . create ( )
2022-05-31 15:35:47 +10:00
assert facet . asdict ( ) == { }
2022-05-12 12:06:23 +10:00
facet = ids . material . create (
2022-05-31 15:35:47 +10:00
value = " value " , uri = " https://test.com " , minOccurs = " 0 " , maxOccurs = " unbounded " , instructions = " instructions "
2022-05-12 12:06:23 +10:00
)
2022-05-11 23:30:10 +10:00
assert facet . asdict ( ) == {
" value " : { " simpleValue " : " value " } ,
" @uri " : " https://test.com " ,
2022-05-31 15:35:47 +10:00
" @minOccurs " : " 0 " ,
" @maxOccurs " : " unbounded " ,
2022-05-11 23:30:10 +10:00
" @instructions " : " instructions " ,
}
2022-05-12 12:06:23 +10:00
def test_filtering_using_a_material_facet ( self ) :
ifc = ifcopenshell . file ( )
# A material facet with no data matches any present material
facet = ids . material . create ( )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
# A value will match a material name or category
facet = ids . material . create ( value = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
material . Name = " Bar "
material . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
# A value will match any material name or category in a material list
facet = ids . material . create ( value = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
material_set = ifcopenshell . api . run ( " material.add_material_set " , ifc , set_type = " IfcMaterialList " )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material_set )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.add_list_item " , ifc , material_list = material_set , material = material )
material . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
material . Name = " Bar "
material . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
# A value will match any material name or category, or layer name or category in a layer set
facet = ids . material . create ( value = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
material_set = ifcopenshell . api . run ( " material.add_material_set " , ifc , set_type = " IfcMaterialLayerSet " )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material_set )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material = ifcopenshell . api . run ( " material.add_material " , ifc )
layer = ifcopenshell . api . run ( " material.add_layer " , ifc , layer_set = material_set , material = material )
layer . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
layer . Name = " Bar "
layer . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
layer . Category = " Bar "
material . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
material . Name = " Bar "
material . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
# A value will match any material name or category, or profile name or category in a profile set
facet = ids . material . create ( value = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
material_set = ifcopenshell . api . run ( " material.add_material_set " , ifc , set_type = " IfcMaterialProfileSet " )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material_set )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material = ifcopenshell . api . run ( " material.add_material " , ifc )
profile = ifcopenshell . api . run ( " material.add_profile " , ifc , profile_set = material_set , material = material )
profile . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
profile . Name = " Bar "
profile . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
profile . Category = " Bar "
material . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
material . Name = " Bar "
material . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
# A value will match any material name or category, or constituent name or category in a constituent set
facet = ids . material . create ( value = " Foo " )
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
material_set = ifcopenshell . api . run ( " material.add_material_set " , ifc , set_type = " IfcMaterialConstituentSet " )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material_set )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 12:06:23 +10:00
material = ifcopenshell . api . run ( " material.add_material " , ifc )
constituent = ifcopenshell . api . run (
" material.add_constituent " , ifc , constituent_set = material_set , material = material
)
constituent . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
constituent . Name = " Bar "
constituent . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
constituent . Category = " Bar "
material . Name = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
material . Name = " Bar "
material . Category = " Foo "
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 12:06:23 +10:00
2022-05-31 15:35:47 +10:00
# The facet will check for inherited materials
2022-05-12 12:06:23 +10:00
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
element_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = element , relating_type = element_type )
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element_type , material = material )
material . Name = " Foo "
2022-05-31 15:35:47 +10:00
facet = ids . material . create ( value = " Foo " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
run ( " " , facet = facet , inst = element_type , expected = True )
2022-05-12 12:06:23 +10:00
2022-05-31 15:35:47 +10:00
# The facet will check for overriden materials
2022-05-12 12:06:23 +10:00
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
element_type = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWallType " )
ifcopenshell . api . run ( " type.assign_type " , ifc , related_object = element , relating_type = element_type )
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element_type , material = material )
material . Name = " Bar "
material = ifcopenshell . api . run ( " material.add_material " , ifc )
ifcopenshell . api . run ( " material.assign_material " , ifc , product = element , material = material )
material . Name = " Foo "
2022-05-31 15:35:47 +10:00
facet = ids . material . create ( value = " Foo " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
run ( " " , facet = facet , inst = element_type , expected = False )
2021-07-09 08:44:36 +02:00
2022-05-12 14:33:44 +10:00
def test_creating_a_partof_facet ( self ) :
facet = ids . partOf . create ( )
2022-05-25 17:49:12 +10:00
assert facet . asdict ( ) == { " @entity " : " IfcSystem " }
2022-05-12 14:33:44 +10:00
facet = ids . partOf . create ( entity = " IfcGroup " )
2022-05-25 17:49:12 +10:00
assert facet . asdict ( ) == { " @entity " : " IfcGroup " }
2022-05-12 14:33:44 +10:00
def test_filtering_using_a_partof_facet ( self ) :
ifc = ifcopenshell . file ( )
# An IfcElementAssembly entity only passes those who are part of an assembly
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
subelement = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcWall " )
ifcopenshell . api . run ( " aggregate.assign_object " , ifc , product = subelement , relating_object = element )
facet = ids . partOf . create ( entity = " IfcElementAssembly " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
run ( " " , facet = facet , inst = subelement , expected = True )
2022-05-12 14:33:44 +10:00
# An IfcElementAssembly strictly checks that the whole is an IfcElementAssembly class
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcSlab " )
subelement = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcBeam " )
ifcopenshell . api . run ( " aggregate.assign_object " , ifc , product = subelement , relating_object = element )
facet = ids . partOf . create ( entity = " IfcElementAssembly " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = subelement , expected = False )
2022-05-12 14:33:44 +10:00
# A nested subelement still passes so long as one of its parents is an IfcElementAssembly
2022-05-22 22:10:28 +10:00
# TODO nononono
2022-05-12 14:33:44 +10:00
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
subelement = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcSlab " )
subsubelement = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcBeam " )
ifcopenshell . api . run ( " aggregate.assign_object " , ifc , product = subelement , relating_object = element )
ifcopenshell . api . run ( " aggregate.assign_object " , ifc , product = subsubelement , relating_object = subelement )
facet = ids . partOf . create ( entity = " IfcElementAssembly " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = subsubelement , expected = True )
2022-05-12 14:33:44 +10:00
# An IfcGroup only checks that a group is assigned without any other logic
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
group = ifcopenshell . api . run ( " group.add_group " , ifc )
facet = ids . partOf . create ( entity = " IfcGroup " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 14:33:44 +10:00
ifcopenshell . api . run ( " group.assign_group " , ifc , product = element , group = group )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 14:33:44 +10:00
# An IfcGroup can be passed by subtypes
2022-05-22 22:10:28 +10:00
# TODO: wrong, subtypes should not be matched
2022-05-12 14:33:44 +10:00
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
group = ifc . createIfcInventory ( )
facet = ids . partOf . create ( entity = " IfcGroup " )
ifcopenshell . api . run ( " group.assign_group " , ifc , product = element , group = group )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 14:33:44 +10:00
# An IfcSystem only checks that a system is assigned without any other logic
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
system = ifcopenshell . api . run ( " system.add_system " , ifc )
facet = ids . partOf . create ( entity = " IfcSystem " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = False )
2022-05-12 14:33:44 +10:00
ifcopenshell . api . run ( " system.assign_system " , ifc , product = element , system = system )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 14:33:44 +10:00
# An IfcSystem allows subtypes
2022-05-22 22:10:28 +10:00
# TODO: wrong, subtypes should not be matched
2022-05-12 14:33:44 +10:00
element = ifcopenshell . api . run ( " root.create_entity " , ifc , ifc_class = " IfcElementAssembly " )
system = ifcopenshell . api . run ( " system.add_system " , ifc , ifc_class = " IfcDistributionSystem " )
ifcopenshell . api . run ( " system.assign_system " , ifc , product = element , system = system )
facet = ids . partOf . create ( entity = " IfcSystem " )
2022-05-31 22:27:16 +10:00
run ( " " , facet = facet , inst = element , expected = True )
2022-05-12 14:33:44 +10:00
2021-08-24 12:57:44 +02:00
""" Creating IDS with restrictions """
def test_create_restrictions_enumeration ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-08-24 12:57:44 +02:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( ids . entity . create ( name = " Test_Name " ) )
2022-05-11 18:46:27 +10:00
r = ids . restriction . create ( options = [ " testA " , " testB " ] , type = " enumeration " )
2022-05-31 15:35:47 +10:00
m = ids . material . create ( value = r )
2021-08-24 12:57:44 +02:00
i . specifications [ 0 ] . add_requirement ( m )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " testA " )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " testB " )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " testC " )
def test_create_restrictions_bounds ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-08-24 12:57:44 +02:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( ids . entity . create ( name = " Test_Name " ) )
r = ids . restriction . create ( options = { " minInclusive " : 0 , " maxExclusive " : 10 } , type = " bounds " , base = " integer " )
2022-05-31 15:35:47 +10:00
p = ids . property . create ( propertySet = " Test " , name = " Test " , value = r )
2021-08-24 12:57:44 +02:00
i . specifications [ 0 ] . add_requirement ( p )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , 0 )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , 5 )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , - 1 )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , 10 )
def test_create_restrictions_pattern_simple ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-08-24 12:57:44 +02:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( ids . entity . create ( name = " Test_Name " ) )
2022-05-11 18:46:27 +10:00
r = ids . restriction . create ( options = " [A-Z] { 2,4} " , type = " pattern " )
2022-05-31 15:35:47 +10:00
p = ids . property . create ( propertySet = " Test " , name = " Test " , value = r )
2021-08-24 12:57:44 +02:00
i . specifications [ 0 ] . add_requirement ( p )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " XYZ " )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " abc " )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " ABCDE " )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " A " )
def test_create_restrictions_pattern_advanced ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-08-24 12:57:44 +02:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( ids . entity . create ( name = " Test_Name " ) )
2022-05-11 18:46:27 +10:00
r = ids . restriction . create ( options = " (Wanddurchbruch|Deckendurchbruch).* " , type = " pattern " )
2022-05-31 15:35:47 +10:00
p = ids . property . create ( propertySet = " Test " , name = " Test " , value = r )
2021-08-24 12:57:44 +02:00
i . specifications [ 0 ] . add_requirement ( p )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " Wanddurchbruch " )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " Deckendurchbruch " )
self . assertNotEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " Deeckendurchbruch " )
2021-11-23 17:53:32 +01:00
def test_create_restrictions_pattern_utf ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-11-23 17:53:32 +01:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( ids . entity . create ( name = " Test_Name " ) )
2022-05-11 18:46:27 +10:00
r = ids . restriction . create ( options = " èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ " , type = " pattern " )
2022-05-31 15:35:47 +10:00
p = ids . property . create ( propertySet = " Test " , name = " Test " , value = r )
2021-11-23 17:53:32 +01:00
i . specifications [ 0 ] . add_requirement ( p )
self . assertEqual ( i . specifications [ 0 ] . requirements . terms [ 0 ] . value , " èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ " )
2021-07-09 08:44:36 +02:00
2021-11-23 17:53:32 +01:00
def test_created_ids_to_xml ( self ) :
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-11-23 17:53:32 +01:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
2022-02-23 00:24:40 +01:00
e = ids . entity . create ( name = " Test_Name " , predefinedType = " Test_PredefinedType " )
2022-05-31 15:35:47 +10:00
c = ids . classification . create ( value = " Test_Value " , system = " Test_System " )
m = ids . material . create ( value = " Test_Value " )
2022-05-11 18:46:27 +10:00
re = ids . restriction . create ( options = [ " testA " , " testB " ] , type = " enumeration " )
2021-11-23 17:53:32 +01:00
rb = ids . restriction . create ( options = { " minInclusive " : 0 , " maxExclusive " : 10 } , type = " bounds " , base = " integer " )
2022-05-11 18:46:27 +10:00
rp1 = ids . restriction . create ( options = " [A-Z] { 2,4} " , type = " pattern " )
rp2 = ids . restriction . create ( options = " èêóòâôæøåążźćęóʑʒʓʔʕʗʘʙʚʛʜʝʞ " , type = " pattern " )
2022-05-31 15:35:47 +10:00
p1 = ids . property . create ( propertySet = " Test_PropertySet " , name = " Test_Parameter " , value = re )
p2 = ids . property . create ( propertySet = " Test_PropertySet " , name = " Test_Parameter " , value = rb )
p3 = ids . property . create ( propertySet = " Test_PropertySet " , name = " Test_Parameter " , value = rp1 )
p4 = ids . property . create ( propertySet = " Test_PropertySet " , name = " Test_Parameter " , value = rp2 )
p5 = ids . property . create ( propertySet = " Test_PropertySet " , name = " Test_Parameter " , value = [ re , rb , rp1 ] )
2021-11-23 17:53:32 +01:00
i . specifications [ 0 ] . add_applicability ( e )
i . specifications [ 0 ] . add_applicability ( m )
i . specifications [ 0 ] . add_requirement ( c )
i . specifications [ 0 ] . add_requirement ( p1 )
2022-05-22 22:10:28 +10:00
i . specifications [ 0 ] . add_requirement ( p2 )
2021-11-23 17:53:32 +01:00
i . specifications [ 0 ] . add_requirement ( p3 )
i . specifications [ 0 ] . add_requirement ( p4 )
2022-05-22 22:10:28 +10:00
i . specifications [ 0 ] . add_requirement ( p5 )
2021-11-23 17:53:32 +01:00
fn = " TEST_FILE.xml "
result = i . to_xml ( fn )
os . remove ( fn )
self . assertTrue ( result )
2022-05-10 16:17:38 +10:00
2021-07-09 08:44:36 +02:00
class TestIfcValidation ( unittest . TestCase ) :
2022-05-22 22:10:28 +10:00
def test_creating_a_minimal_ids_and_validating ( self ) :
specs = ids . ids ( title = " Title " )
spec = ids . specification ( name = " Name " )
2022-05-31 16:22:44 +10:00
spec . add_applicability ( ids . entity . create ( name = " IFCWALL " ) )
2022-05-22 22:10:28 +10:00
spec . add_requirement ( ids . attribute . create ( name = " Name " , value = " Waldo " ) )
specs . specifications . append ( spec )
assert " http://standards.buildingsmart.org/IDS " in specs . to_string ( )
assert spec . status == None
model = ifcopenshell . file ( )
wall = model . createIfcWall ( )
waldo = model . createIfcWall ( Name = " Waldo " )
specs . validate2 ( model )
assert spec . status == False
assert set ( spec . applicable_entities ) == { wall , waldo }
assert spec . failed_entities == [ wall ]
2022-05-25 17:49:12 +10:00
def test_creating_multiple_specifications ( self ) :
specs = ids . ids ( title = " Title " )
spec = ids . specification ( name = " Name " )
2022-05-31 16:22:44 +10:00
spec . add_applicability ( ids . entity . create ( name = " IFCWALL " ) )
2022-05-25 17:49:12 +10:00
spec . add_requirement ( ids . attribute . create ( name = " Name " , value = " Waldo " ) )
specs . specifications . append ( spec )
spec2 = ids . specification ( name = " Name " )
2022-05-31 16:22:44 +10:00
spec2 . add_applicability ( ids . entity . create ( name = " IFCWALL " ) )
2022-05-25 17:49:12 +10:00
spec2 . add_requirement ( ids . attribute . create ( name = " Name " , value = " Waldo " ) )
specs . specifications . append ( spec2 )
model = ifcopenshell . file ( )
wall = model . createIfcWall ( )
waldo = model . createIfcWall ( Name = " Waldo " )
specs . validate2 ( model )
assert spec . status == False
assert set ( spec . applicable_entities ) == { wall , waldo }
assert spec . failed_entities == [ wall ]
assert spec2 . failed_entities == [ wall ]
2021-08-24 12:57:44 +02:00
def test_validate_simple ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
# Same test as in reporting...
2021-11-23 17:53:32 +01:00
ids_file = ids . ids . open ( IDS_URL )
report = ids . SimpleHandler ( )
logger . addHandler ( report )
ids_file . validate ( ifc_file , logger )
self . assertEqual ( len ( report . statements ) , 5 )
2021-12-22 12:45:16 +01:00
logger . handlers . pop ( )
def test_validate_all_facets ( self ) :
2022-05-10 16:17:38 +10:00
# Those are true:
2021-12-22 12:45:16 +01:00
e = ids . entity . create ( name = " IfcWall " )
2022-05-31 15:35:47 +10:00
p1 = ids . property . create ( propertySet = " MySet " , name = " Param1 " , value = " banan " )
p2 = ids . property . create ( propertySet = " MySet " , name = " Param2 " , value = 120.0 )
p3 = ids . property . create ( propertySet = " Pset_WallCommon " , name = " LoadBearing " , value = False )
2022-05-10 16:17:38 +10:00
# Those are false:
2022-05-31 15:35:47 +10:00
p4 = ids . property . create ( propertySet = " MySet " , name = " Param1 " , value = " orange " )
p5 = ids . property . create ( propertySet = " MySet " , name = " Param2 " , value = 123.4 )
p6 = ids . property . create ( propertySet = " Pset_WallCommon " , name = " LoadBearing " , value = True )
2022-05-10 16:17:38 +10:00
2022-02-23 00:24:40 +01:00
i = ids . ids ( title = " My IDS " )
2021-12-22 12:45:16 +01:00
i . specifications . append ( ids . specification ( name = " Test_Specification " ) )
i . specifications [ 0 ] . add_applicability ( e )
i . specifications [ 0 ] . add_requirement ( p1 )
i . specifications [ 0 ] . add_requirement ( p2 )
i . specifications [ 0 ] . add_requirement ( p3 )
i . specifications [ 0 ] . add_requirement ( p4 )
i . specifications [ 0 ] . add_requirement ( p5 )
i . specifications [ 0 ] . add_requirement ( p6 )
report = ids . SimpleHandler ( report_valid = True )
logger . addHandler ( report )
i . validate ( ifc_file , logger )
# TODO self.assertEqual(len(report.statements), 27) #there are 5 walls in the IFC, one passed 3 criteria, est should fail (27 failures)
logger . handlers . pop ( )
2021-08-24 12:57:44 +02:00
""" Validating IDS files with restrictions """
2021-12-22 12:45:16 +01:00
def test_validate_restrictions_enumeration ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) ,
" Sample-BIM-Files/IDS/ " ,
" IDS_Wall_needs_property_with_restriction_enumeration.xml " ,
)
2021-12-22 12:45:16 +01:00
ids_file = ids . ids . open ( IDS_URL )
2022-05-10 16:17:38 +10:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
[
x [ " @value " ]
for x in ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " enumeration " ]
] ,
[ " testA " , " testB " ] ,
)
2021-12-22 12:45:16 +01:00
# TODO actual test of validation result
# self.assertTrue( )
def test_validate_restrictions_boundsInclusive ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_property_with_restriction_bounds.xml "
)
2021-12-22 12:45:16 +01:00
ids_file = ids . ids . open ( IDS_URL )
2022-05-10 16:17:38 +10:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " minInclusive " ] [ " @value " ] ,
" 0 " ,
)
2021-12-22 12:45:16 +01:00
# TODO actual test of validation result
# self.assertTrue( )
def test_validate_restrictions_boundsExclusive ( self ) :
2022-05-10 16:17:38 +10:00
# TODO
2021-12-22 12:45:16 +01:00
pass
def test_validate_restrictions_pattern_simple ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
IDS_URL = os . path . join (
os . path . dirname ( __file__ ) , " Sample-BIM-Files/IDS/ " , " IDS_Wall_needs_property_with_restriction_pattern.xml "
)
2021-12-22 12:45:16 +01:00
ids_file = ids . ids . open ( IDS_URL )
2022-05-10 16:17:38 +10:00
self . assertEqual ( ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " name " ] [ " simpleValue " ] , " Test_Parameter " )
self . assertEqual (
ids_file . specifications [ 0 ] . requirements . terms [ 0 ] . node [ " value " ] [ " restriction " ] [ 0 ] [ " pattern " ] [ " @value " ] ,
" [A-Z] { 2,4} " ,
)
2021-12-22 12:45:16 +01:00
# TODO actual test of validation result
# self.assertTrue( )
2021-08-24 12:57:44 +02:00
2021-11-23 17:53:32 +01:00
class TestIdsReporting ( unittest . TestCase ) :
def test_simple_report ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2022-05-10 16:17:38 +10:00
# Same test as in validation...
2021-11-23 17:53:32 +01:00
ids_file = ids . ids . open ( IDS_URL )
report = ids . SimpleHandler ( )
logger . addHandler ( report )
ids_file . validate ( ifc_file , logger )
self . assertEqual ( len ( report . statements ) , 5 )
2021-12-22 12:45:16 +01:00
logger . handlers . pop ( )
2021-11-23 17:53:32 +01:00
def test_bcf_report ( self ) :
2022-05-31 15:35:47 +10:00
return # TODO
2021-11-23 17:53:32 +01:00
ids_file = ids . ids . open ( IDS_URL )
fn = os . path . join ( tempfile . gettempdir ( ) , " test.bcf " )
bcf_handler = ids . BcfHandler ( project_name = " Default IDS Project " , author = " your@email.com " , filepath = fn )
logger . addHandler ( bcf_handler )
ids_file . validate ( ifc_file , logger )
my_bcfxml = bcfxml . load ( fn )
topics = my_bcfxml . get_topics ( )
self . assertEqual ( len ( topics ) , 5 )
2021-12-22 12:45:16 +01:00
logger . handlers . pop ( )