include location (type/inst/any)

This commit is contained in:
ArturTomczak
2021-06-21 17:48:27 +02:00
parent 99f0e6c93e
commit eaa527f512
+83 -37
View File
@@ -3,7 +3,6 @@ import ifcopenshell.util.element
import re import re
from xmlschema import XMLSchema from xmlschema import XMLSchema
from xmlschema.validators import facets, identities from xmlschema.validators import facets, identities
class exception(Exception): class exception(Exception):
@@ -103,28 +102,48 @@ class classification(facet):
The IDS classification facet by traversing the HasAssociations inverse attribute The IDS classification facet by traversing the HasAssociations inverse attribute
""" """
parameters = ["system", "value"] parameters = ["system", "value", "location"]
message = "a classification reference '%(value)s' from '%(system)s'" message = "%(location)sclassification reference %(value)s from '%(system)s'"
def __call__(self, inst, logger): def __call__(self, inst, logger):
#TODO Location: 'type'/'instance'/'any'
self.location = self.node['@location']
instance_classiciations = inst.HasAssociations
if ifcopenshell.util.element.get_type(inst):
type_classifications = ifcopenshell.util.element.get_type(inst).HasAssociations
else:
type_classifications = ()
if self.location == 'instance' and instance_classiciations:
associations = instance_classiciations
elif self.location == 'type' and type_classifications:
associations = type_classifications
elif self.location == 'any' and (instance_classiciations or type_classifications):
associations = instance_classiciations + type_classifications
else:
associations = ()
refs = [] refs = []
for association in inst.HasAssociations: for association in associations:
if association.is_a("IfcRelAssociatesClassification"): if association.is_a("IfcRelAssociatesClassification"):
cref = association.RelatingClassification cref = association.RelatingClassification
if hasattr(cref, 'ItemReference'): #IFC2x3 if hasattr(cref, 'ItemReference'): #IFC2x3
refs.append((cref.ReferencedSource.Name, cref.ItemReference)) refs.append((cref.ReferencedSource.Name, cref.ItemReference))
elif hasattr(cref, 'Identification'): # IFC4 elif hasattr(cref, 'Identification'): # IFC4
refs.append((cref.ReferencedSource.Name, cref.Identification)) refs.append((cref.ReferencedSource.Name, cref.Identification))
self.location = location[self.location]
if refs: if refs:
return facet_evaluation( return facet_evaluation(
(self.system, self.value) in refs, (self.system, self.value) in refs,
self.message % {"system": refs[0][0], "value": refs[0][1]} self.message % {"system": refs[0][0], "value": "'"+refs[0][1]+"'", "location": self.location} # what if not first item of refs?
) )
else: else:
return facet_evaluation( return facet_evaluation(
False, False,
"has no classification" "does not have %sclassification reference" % self.location
) )
@@ -133,28 +152,46 @@ class property(facet):
The IDS property facet implemented using `ifcopenshell.util.element` The IDS property facet implemented using `ifcopenshell.util.element`
""" """
parameters = ["name", "propertyset", "value"] parameters = ["name", "propertyset", "value", "location"]
message = "a property '%(name)s' in '%(propertyset)s' with a value %(value)s" message = "%(location)sproperty '%(name)s' in '%(propertyset)s' with a value %(value)s"
def __call__(self, inst, logger): def __call__(self, inst, logger):
#TODO Location: 'type'/'instance'/'any'
props = ifcopenshell.util.element.get_psets(inst) self.location = self.node['@location']
instance_props = ifcopenshell.util.element.get_psets(inst)
if ifcopenshell.util.element.get_type(inst):
type_props = ifcopenshell.util.element.get_psets( ifcopenshell.util.element.get_type(inst) )
else:
type_props = {}
if self.location == 'instance':
props = instance_props
elif self.location == 'type' and type_props:
props = type_props
elif self.location == 'any' and (instance_props or type_props):
props = {**instance_props , **type_props}
else:
props = {}
pset = props.get(self.propertyset) pset = props.get(self.propertyset)
val = pset.get(self.name) if pset else None val = pset.get(self.name) if pset else None
self.location = location[self.location]
di = { di = {
"name": self.name, "name": self.name,
"propertyset": self.propertyset, "propertyset": self.propertyset,
"value": "'%s'" % val, "value": "'%s'" % val,
"location": self.location
} }
if val is not None: if val is not None:
msg = self.message % di msg = self.message % di
else: else:
if pset: if pset:
msg = "no property '%(name)s' in a set '%(propertyset)s'" % di msg = "does not have %(location)sproperty '%(name)s' in a set '%(propertyset)s'" % di
else: else:
msg = "no set '%(propertyset)s'" % di msg = "does not have %(location)sset '%(propertyset)s'" % di
#TODO implement data type comparison #TODO implement data type comparison
return facet_evaluation( return facet_evaluation(
@@ -167,16 +204,30 @@ class material(facet):
""" """
The IDS material facet by traversing the HasAssociations inverse attribute The IDS material facet by traversing the HasAssociations inverse attribute
""" """
parameters = ["value"] parameters = ["value", "location"]
message = "a material '%(value)s'" message = "%(location)smaterial '%(value)s'"
def __call__(self, inst, logger): def __call__(self, inst, logger):
material_relations = [rel for rel in inst.HasAssociations if rel.is_a("IfcRelAssociatesMaterial")]
#TODO Location: 'type'/'instance'/'any'. Handle type... https://github.com/IfcOpenShell/IfcOpenShell/blob/257997c2cb8d382a7f3026f9a33fed6ccbe31282/src/ifcopenshell-python/ifcopenshell/util/element.py#L54 self.location = self.node['@location']
# [material_relations.append(rel) for rel in ifcopenshell.util.element.get_type(inst).HasAssociations if rel.is_a("IfcRelAssociatesMaterial")]
instance_material_rel = [rel for rel in inst.HasAssociations if rel.is_a("IfcRelAssociatesMaterial")]
if ifcopenshell.util.element.get_type(inst):
type_material_rel = [rel for rel in ifcopenshell.util.element.get_type(inst).HasAssociations if rel.is_a("IfcRelAssociatesMaterial")]
else:
type_material_rel = []
if self.location == 'instance':
material_relations = list(instance_material_rel)
elif self.location == 'type' and type_material_rel:
material_relations = list(type_material_rel)
elif self.location == 'any' and (instance_material_rel or type_material_rel):
material_relations = instance_material_rel + type_material_rel
else:
material_relations = []
materials = [] materials = []
for rel in material_relations: for rel in material_relations:
#TODO test all subtypes of material definitions
if rel.RelatingMaterial.is_a() == "IfcMaterial": if rel.RelatingMaterial.is_a() == "IfcMaterial":
materials.append(rel.RelatingMaterial.Name) materials.append(rel.RelatingMaterial.Name)
elif rel.RelatingMaterial.is_a() == "IfcMaterialMaterialList": #DEPRECATED in IFC4 elif rel.RelatingMaterial.is_a() == "IfcMaterialMaterialList": #DEPRECATED in IFC4
@@ -199,9 +250,11 @@ class material(facet):
if not materials: if not materials:
materials.append('UNDEFINED') materials.append('UNDEFINED')
self.location = location[self.location]
return facet_evaluation( return facet_evaluation(
self.value in materials, self.value in materials,
self.message % {"value": "'/'".join(materials)}, self.message % {"value": "'/'".join(materials), "location": self.location},
) )
@@ -276,21 +329,6 @@ class restriction:
#TODO add whiteSpace #TODO add whiteSpace
else: else:
logger.error({'result':'ERROR', 'sentence':'Restriction not implemented'}) logger.error({'result':'ERROR', 'sentence':'Restriction not implemented'})
self.type = []
for n in node.childNodes:
if n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("enumeration"):
self.options.append(n.getAttribute("value"))
self.type = "enumeration"
elif n.nodeType == n.ELEMENT_NODE and (n.tagName.endswith("Inclusive") or n.tagName.endswith("Exclusive")):
self.options.append(n.getAttribute("value"))
self.type = "bounds"
elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("length"):
self.options.append(n.getAttribute("value"))
self.type = "length"
elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("pattern"):
self.options.append(n.getAttribute("value"))
self.type = "pattern"
def __eq__(self, other): def __eq__(self, other):
result=False result=False
@@ -394,6 +432,14 @@ class ids:
if comply: self.ifc_passed += 1 if comply: self.ifc_passed += 1
location = {
'instance': 'an instance ',
'type': 'a type ',
'any': 'a '
}
if __name__ == "__main__": if __name__ == "__main__":
import time import time
start_time = time.time() start_time = time.time()