mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-19 14:41:25 +00:00
Rough merge of schema runtime representation
This commit is contained in:
@@ -121,7 +121,7 @@ actions = {
|
|||||||
'general_aggregation_types' : "lambda t: AggregationType(t)",
|
'general_aggregation_types' : "lambda t: AggregationType(t)",
|
||||||
'select_type' : "lambda t: SelectType(t)",
|
'select_type' : "lambda t: SelectType(t)",
|
||||||
'binary_type' : "lambda t: BinaryType(t)",
|
'binary_type' : "lambda t: BinaryType(t)",
|
||||||
'subtype_declaration' : "lambda t: SubtypeExpression(t)",
|
'subtype_declaration' : "lambda t: SubTypeExpression(t)",
|
||||||
'derive_clause' : "lambda t: AttributeList('derive', t)",
|
'derive_clause' : "lambda t: AttributeList('derive', t)",
|
||||||
'derived_attr' : "lambda t: DerivedAttribute(t)",
|
'derived_attr' : "lambda t: DerivedAttribute(t)",
|
||||||
'inverse_clause' : "lambda t: AttributeList('inverse', t)",
|
'inverse_clause' : "lambda t: AttributeList('inverse', t)",
|
||||||
@@ -170,32 +170,45 @@ for id in to_emit:
|
|||||||
stmt = "Suppress%s" % stmt
|
stmt = "Suppress%s" % stmt
|
||||||
statements.append("%s << %s" % (id, stmt))
|
statements.append("%s << %s" % (id, stmt))
|
||||||
|
|
||||||
print ("""import sys
|
print ("""import os
|
||||||
from pyparsing import *
|
import sys
|
||||||
from nodes import *
|
import pickle
|
||||||
|
|
||||||
%s
|
cache_file = sys.argv[1] + ".cache.dat"
|
||||||
|
if os.path.exists(cache_file):
|
||||||
|
with open(cache_file, "rb") as f:
|
||||||
|
mapping = pickle.load(f)
|
||||||
|
else:
|
||||||
|
from pyparsing import *
|
||||||
|
from nodes import *
|
||||||
|
|
||||||
import schema
|
import schema
|
||||||
import mapping
|
import mapping
|
||||||
|
|
||||||
|
%s
|
||||||
|
|
||||||
|
syntax.ignore("--" + restOfLine)
|
||||||
|
syntax.ignore(Regex(r"\((?:\*(?:[^*]*\*+)+?\))"))
|
||||||
|
ast = syntax.parseFile(sys.argv[1])
|
||||||
|
schema = schema.Schema(ast)
|
||||||
|
mapping = mapping.Mapping(schema)
|
||||||
|
|
||||||
|
with open(cache_file, "wb") as f:
|
||||||
|
pickle.dump(mapping, f, protocol=0)
|
||||||
|
|
||||||
import header
|
import header
|
||||||
import enum_header
|
import enum_header
|
||||||
import implementation
|
import implementation
|
||||||
import latebound_header
|
import latebound_header
|
||||||
import latebound_implementation
|
import latebound_implementation
|
||||||
|
import schema_class
|
||||||
syntax.ignore("--" + restOfLine)
|
|
||||||
syntax.ignore(Regex(r"\((?:\*(?:[^*]*\*+)+?\))"))
|
|
||||||
ast = syntax.parseFile(sys.argv[1])
|
|
||||||
schema = schema.Schema(ast)
|
|
||||||
mapping = mapping.Mapping(schema)
|
|
||||||
|
|
||||||
header.Header(mapping).emit()
|
header.Header(mapping).emit()
|
||||||
enum_header.EnumHeader(mapping).emit()
|
enum_header.EnumHeader(mapping).emit()
|
||||||
implementation.Implementation(mapping).emit()
|
implementation.Implementation(mapping).emit()
|
||||||
latebound_header.LateBoundHeader(mapping).emit()
|
latebound_header.LateBoundHeader(mapping).emit()
|
||||||
latebound_implementation.LateBoundImplementation(mapping).emit()
|
latebound_implementation.LateBoundImplementation(mapping).emit()
|
||||||
|
schema_class.SchemaClass(mapping).emit()
|
||||||
|
|
||||||
sys.stdout.write(schema.name)
|
sys.stdout.write(schema.name)
|
||||||
"""%('\n'.join(statements)))
|
"""%('\n '.join(statements)))
|
||||||
|
|||||||
@@ -210,17 +210,17 @@ class Implementation(codegen.Base):
|
|||||||
|
|
||||||
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
|
simple_type_impl.append(templates.simpletype_impl_comment % {'name': class_name})
|
||||||
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
|
simple_type_impl.extend(map(compose, map(lambda x: (class_name, attr_type, superclass, "(IfcEntityInstanceData*)0")+x, (
|
||||||
('getArgumentType', templates.const_function, 'IfcUtil::ArgumentType', ('unsigned int i',), templates.simpletype_impl_argument_type ),
|
|
||||||
('getArgument', templates.const_function, 'Argument*', ('unsigned int i',), templates.simpletype_impl_argument ),
|
|
||||||
('is', templates.const_function, 'bool', ('Type::Enum v',), simpletype_impl_is ),
|
|
||||||
('type', templates.const_function, 'Type::Enum', (), templates.simpletype_impl_type ),
|
|
||||||
('Class', templates.function, 'Type::Enum', (), templates.simpletype_impl_class ),
|
('Class', templates.function, 'Type::Enum', (), templates.simpletype_impl_class ),
|
||||||
|
('declaration', templates.const_function, 'const IfcParse::type_declaration&', (), templates.simpletype_impl_declaration ),
|
||||||
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
|
('', constructor, '', ('IfcEntityInstanceData* e',), templates.simpletype_impl_explicit_constructor),
|
||||||
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
|
('', constructor, '', ("%s v" % type_str,), simpletype_impl_constructor ),
|
||||||
('', templates.cast_function, type_str, (), simpletype_impl_cast )
|
('', templates.cast_function, type_str, (), simpletype_impl_cast )
|
||||||
))))
|
))))
|
||||||
simple_type_impl.append('')
|
simple_type_impl.append('')
|
||||||
|
|
||||||
|
external_definitions = ["extern entity* %s_type;" % n for n in mapping.schema.entities.keys() ] + \
|
||||||
|
["extern type_declaration* %s_type;" % n for n in mapping.schema.simpletypes.keys()]
|
||||||
|
|
||||||
self.str = templates.implementation % {
|
self.str = templates.implementation % {
|
||||||
'schema_name_upper' : mapping.schema.name.upper(),
|
'schema_name_upper' : mapping.schema.name.upper(),
|
||||||
'schema_name' : mapping.schema.name.capitalize(),
|
'schema_name' : mapping.schema.name.capitalize(),
|
||||||
@@ -232,7 +232,8 @@ class Implementation(codegen.Base):
|
|||||||
'simple_type_statement' : simple_type_statements,
|
'simple_type_statement' : simple_type_statements,
|
||||||
'parent_type_statements' : parent_type_statements,
|
'parent_type_statements' : parent_type_statements,
|
||||||
'entity_implementations' : catnl(entity_implementations),
|
'entity_implementations' : catnl(entity_implementations),
|
||||||
'simple_type_impl' : catnl(simple_type_impl)
|
'simple_type_impl' : catnl(simple_type_impl),
|
||||||
|
'external_definitions' : catnl(external_definitions)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.schema_name = mapping.schema.name.capitalize()
|
self.schema_name = mapping.schema.name.capitalize()
|
||||||
|
|||||||
@@ -44,15 +44,17 @@ class TypeDeclaration(Node):
|
|||||||
class EntityDeclaration(Node):
|
class EntityDeclaration(Node):
|
||||||
name = property(lambda self: self.tokens[1])
|
name = property(lambda self: self.tokens[1])
|
||||||
attributes = property(lambda self: self.tokens_of_type(ExplicitAttribute))
|
attributes = property(lambda self: self.tokens_of_type(ExplicitAttribute))
|
||||||
|
abstract = property(lambda self: self.single_token_of_type(SuperTypeExpression) is not None and \
|
||||||
|
self.single_token_of_type(SuperTypeExpression).abstract)
|
||||||
def init(self):
|
def init(self):
|
||||||
assert self.tokens[0] == 'entity'
|
assert self.tokens[0] == 'entity'
|
||||||
s = self.single_token_of_type(SubtypeExpression)
|
s = self.single_token_of_type(SubTypeExpression)
|
||||||
self.inverse = self.single_token_of_type(AttributeList, 'type', 'inverse')
|
self.inverse = self.single_token_of_type(AttributeList, 'type', 'inverse')
|
||||||
self.derive = self.single_token_of_type(AttributeList, 'type', 'derive')
|
self.derive = self.single_token_of_type(AttributeList, 'type', 'derive')
|
||||||
self.supertypes = s.types if s else []
|
self.supertypes = s.types if s else []
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
builder = ""
|
builder = ""
|
||||||
builder += "Entity(%s)" % (self.name)
|
builder += "%sEntity(%s)" % ("Abstract " if self.abstract else "", self.name)
|
||||||
if len(self.supertypes):
|
if len(self.supertypes):
|
||||||
builder += "\n Supertypes: %s"%(",".join(self.supertypes))
|
builder += "\n Supertypes: %s"%(",".join(self.supertypes))
|
||||||
if len(self.attributes):
|
if len(self.attributes):
|
||||||
@@ -106,12 +108,20 @@ class SelectType(Node):
|
|||||||
class SubSuperTypeExpression(Node):
|
class SubSuperTypeExpression(Node):
|
||||||
type = property(lambda self: self.tokens[0])
|
type = property(lambda self: self.tokens[0])
|
||||||
types = property(lambda self: self.tokens[3::2])
|
types = property(lambda self: self.tokens[3::2])
|
||||||
|
abstract = False
|
||||||
def init(self):
|
def init(self):
|
||||||
assert self.type == self.class_type
|
if self.tokens[0] == 'abstract':
|
||||||
|
self.tokens = self.tokens[1:]
|
||||||
|
self.abstract = True
|
||||||
|
assert self.type == self.type_relationship
|
||||||
|
|
||||||
|
|
||||||
class SubtypeExpression(SubSuperTypeExpression):
|
class SubTypeExpression(SubSuperTypeExpression):
|
||||||
class_type = 'subtype'
|
type_relationship = 'subtype'
|
||||||
|
|
||||||
|
|
||||||
|
class SuperTypeExpression(SubSuperTypeExpression):
|
||||||
|
type_relationship = 'supertype'
|
||||||
|
|
||||||
|
|
||||||
class AttributeList(Node):
|
class AttributeList(Node):
|
||||||
|
|||||||
@@ -27,25 +27,27 @@ if tuple(map(int, platform.python_version_tuple())) < (2, 7):
|
|||||||
|
|
||||||
# According to ISO 10303-11 7.1.2: Letters: "... The case of
|
# According to ISO 10303-11 7.1.2: Letters: "... The case of
|
||||||
# letters is significant only within explicit string literals."
|
# letters is significant only within explicit string literals."
|
||||||
class OrderedCaseInsensitiveDict(collections.OrderedDict):
|
class OrderedCaseInsensitiveDict_KeyObject(str):
|
||||||
class KeyObject(str):
|
def __eq__(self, other):
|
||||||
def __eq__(self, other):
|
return self.lower() == other.lower()
|
||||||
return self.lower() == other.lower()
|
def __hash__(self):
|
||||||
def __hash__(self):
|
return hash(self.lower())
|
||||||
return hash(self.lower())
|
|
||||||
|
|
||||||
|
|
||||||
|
class OrderedCaseInsensitiveDict(collections.OrderedDict):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
collections.OrderedDict.__init__(self)
|
collections.OrderedDict.__init__(self)
|
||||||
for key, value in collections.OrderedDict(*args, **kwargs).items():
|
for key, value in collections.OrderedDict(*args, **kwargs).items():
|
||||||
self[OrderedCaseInsensitiveDict.KeyObject(key)] = value
|
self[OrderedCaseInsensitiveDict_KeyObject(key)] = value
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
return collections.OrderedDict.__setitem__(self, OrderedCaseInsensitiveDict.KeyObject(key), value)
|
return collections.OrderedDict.__setitem__(self, OrderedCaseInsensitiveDict_KeyObject(key), value)
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return collections.OrderedDict.__getitem__(self, OrderedCaseInsensitiveDict.KeyObject(key))
|
return collections.OrderedDict.__getitem__(self, OrderedCaseInsensitiveDict_KeyObject(key))
|
||||||
def get(self, key, *args, **kwargs):
|
def get(self, key, *args, **kwargs):
|
||||||
return collections.OrderedDict.get(self, OrderedCaseInsensitiveDict.KeyObject(key), *args, **kwargs)
|
return collections.OrderedDict.get(self, OrderedCaseInsensitiveDict_KeyObject(key), *args, **kwargs)
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return collections.OrderedDict.__contains__(self, OrderedCaseInsensitiveDict.KeyObject(key))
|
return collections.OrderedDict.__contains__(self, OrderedCaseInsensitiveDict_KeyObject(key))
|
||||||
|
|
||||||
|
|
||||||
class Schema:
|
class Schema:
|
||||||
def is_enumeration(self, v):
|
def is_enumeration(self, v):
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
###############################################################################
|
||||||
|
# #
|
||||||
|
# This file is part of IfcOpenShell. #
|
||||||
|
# #
|
||||||
|
# IfcOpenShell is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the Lesser GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3.0 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 #
|
||||||
|
# Lesser GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the Lesser GNU General Public License #
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||||
|
# #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import operator
|
||||||
|
|
||||||
|
import nodes
|
||||||
|
import codegen
|
||||||
|
import templates
|
||||||
|
|
||||||
|
class SchemaClass(codegen.Base):
|
||||||
|
def __init__(self, mapping):
|
||||||
|
|
||||||
|
class UnmetDependenciesException(Exception): pass
|
||||||
|
|
||||||
|
schema_name = mapping.schema.name
|
||||||
|
declared_types = []
|
||||||
|
|
||||||
|
def get_declared_type(type, emitted_names=None):
|
||||||
|
if isinstance(type, nodes.AggregationType):
|
||||||
|
aggr_type = type.aggregate_type
|
||||||
|
make_bound = lambda b: -1 if b == '?' else int(b)
|
||||||
|
bound1, bound2 = map(make_bound, (type.bounds.lower, type.bounds.upper))
|
||||||
|
decl_type = get_declared_type(type.type)
|
||||||
|
return "new aggregation_type(aggregation_type::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(decl_type)s)" % locals()
|
||||||
|
elif isinstance(type, nodes.BinaryType):
|
||||||
|
return "new simple_type(simple_type::binary_type)"
|
||||||
|
elif isinstance(type, str):
|
||||||
|
if mapping.schema.is_type(type) or mapping.schema.is_entity(type):
|
||||||
|
if emitted_names is None or type in emitted_types:
|
||||||
|
return "new named_type(%s_type)" % type
|
||||||
|
else:
|
||||||
|
raise UnmetDependenciesException(type)
|
||||||
|
else:
|
||||||
|
return "new simple_type(simple_type::%s_type)" % type
|
||||||
|
|
||||||
|
def find_inverse_name_and_index(entity_name, attribute_name):
|
||||||
|
attributes_per_subtype = []
|
||||||
|
while True:
|
||||||
|
entity = mapping.schema.entities[entity_name]
|
||||||
|
attr_names = list(map(operator.attrgetter('name'), entity.attributes))
|
||||||
|
if len(attr_names):
|
||||||
|
attributes_per_subtype.append((entity_name, attr_names))
|
||||||
|
if len(entity.supertypes) != 1: break
|
||||||
|
entity_name = entity.supertypes[0]
|
||||||
|
index = 0
|
||||||
|
for et, attrs in attributes_per_subtype[::-1]:
|
||||||
|
try: return et, attrs.index(attribute_name)
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
self.schema_name = mapping.schema.name.capitalize()
|
||||||
|
|
||||||
|
statements = ['',
|
||||||
|
'#include "../ifcparse/IfcSchema.h"',
|
||||||
|
'',
|
||||||
|
'using namespace IfcParse;'
|
||||||
|
'']
|
||||||
|
|
||||||
|
collections_by_type = (('entity', mapping.schema.entities ),
|
||||||
|
('type_declaration', mapping.schema.simpletypes ),
|
||||||
|
('select_type', mapping.schema.selects ),
|
||||||
|
('enumeration_type', mapping.schema.enumerations))
|
||||||
|
|
||||||
|
for cpp_type, collection in collections_by_type:
|
||||||
|
for name in collection.keys():
|
||||||
|
statements.append('%(cpp_type)s* %(name)s_type = 0;' % locals())
|
||||||
|
|
||||||
|
statements.append('#ifdef _MSC_VER' )
|
||||||
|
statements.append('#pragma optimize("", off)')
|
||||||
|
statements.append('#endif' )
|
||||||
|
|
||||||
|
statements.append('schema_definition* populate_schema() {')
|
||||||
|
|
||||||
|
emitted_types = set()
|
||||||
|
while len(emitted_types) < len(mapping.schema.simpletypes):
|
||||||
|
for name, type in mapping.schema.simpletypes.items():
|
||||||
|
if name in emitted_types: continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
declared_type = get_declared_type(type, emitted_types)
|
||||||
|
except UnmetDependenciesException:
|
||||||
|
continue
|
||||||
|
|
||||||
|
statements.append(' %(name)s_type = new type_declaration(IfcSchema::Type::%(name)s, %(declared_type)s);' % locals())
|
||||||
|
emitted_types.add(name)
|
||||||
|
|
||||||
|
declared_types.append('%(name)s_type' % locals())
|
||||||
|
|
||||||
|
for name, enum in mapping.schema.enumerations.items():
|
||||||
|
statements.append(' {')
|
||||||
|
statements.append(' std::vector<std::string> items; items.reserve(%d);' % len(enum.values))
|
||||||
|
statements.extend(map(lambda v: ' items.push_back("%s");' % v, sorted(enum.values)))
|
||||||
|
statements.append(' %(name)s_type = new enumeration_type(IfcSchema::Type::%(name)s, items);' % locals())
|
||||||
|
statements.append(' }')
|
||||||
|
|
||||||
|
declared_types.append('%(name)s_type' % locals())
|
||||||
|
|
||||||
|
emitted_entities = set()
|
||||||
|
while len(emitted_entities) < len(mapping.schema.entities):
|
||||||
|
for name, type in mapping.schema.entities.items():
|
||||||
|
if name in emitted_entities: continue
|
||||||
|
if len(type.supertypes) == 0 or set(type.supertypes) < emitted_entities:
|
||||||
|
supertype = '0' if len(type.supertypes) == 0 else '%s_type' % type.supertypes[0]
|
||||||
|
statements.append(' %(name)s_type = new entity(IfcSchema::Type::%(name)s, %(supertype)s);' % locals())
|
||||||
|
emitted_entities.add(name)
|
||||||
|
|
||||||
|
declared_types.append('%(name)s_type' % locals())
|
||||||
|
|
||||||
|
emmited = emitted_types | emitted_entities | set(mapping.schema.enumerations.keys())
|
||||||
|
|
||||||
|
emitted_selects = set()
|
||||||
|
while len(emitted_selects) < len(mapping.schema.selects):
|
||||||
|
for name, type in mapping.schema.selects.items():
|
||||||
|
if name in emitted_selects: continue
|
||||||
|
if set(type.values) < emmited:
|
||||||
|
statements.append(' {')
|
||||||
|
statements.append(' std::vector<const declaration*> items; items.reserve(%d);' % len(type.values))
|
||||||
|
statements.extend(map(lambda v: ' items.push_back(%s_type);' % v, sorted(type.values)))
|
||||||
|
statements.append(' %(name)s_type = new select_type(IfcSchema::Type::%(name)s, items);' % locals())
|
||||||
|
statements.append(' }')
|
||||||
|
emitted_selects.add(name)
|
||||||
|
emmited.add(name)
|
||||||
|
|
||||||
|
declared_types.append('%(name)s_type' % locals())
|
||||||
|
|
||||||
|
num_declarations = len(declared_types)
|
||||||
|
|
||||||
|
for name, type in mapping.schema.entities.items():
|
||||||
|
derived = set(mapping.derived_in_supertype(type))
|
||||||
|
attribute_names = list(map(operator.attrgetter('name'), mapping.arguments(type)))
|
||||||
|
|
||||||
|
statements.append(' {')
|
||||||
|
statements.append(' std::vector<const entity::attribute*> attributes; attributes.reserve(%d);' % len(type.attributes))
|
||||||
|
for attr in type.attributes:
|
||||||
|
attr_name, optional = attr.name, str(attr.optional).lower()
|
||||||
|
decl_type = get_declared_type(attr.type)
|
||||||
|
statements.append(' attributes.push_back(new entity::attribute("%(attr_name)s", %(decl_type)s, %(optional)s));' % locals())
|
||||||
|
statements.append(' std::vector<bool> derived; derived.reserve(%d);' % len(attribute_names))
|
||||||
|
statements.append(' ' + " ".join(map(lambda b: 'derived.push_back(%s);' % str(b in derived).lower(), attribute_names)))
|
||||||
|
statements.append(' %(name)s_type->set_attributes(attributes, derived);' % locals())
|
||||||
|
statements.append(' }')
|
||||||
|
|
||||||
|
for name, type in mapping.schema.entities.items():
|
||||||
|
if type.inverse:
|
||||||
|
statements.append(' {')
|
||||||
|
statements.append(' std::vector<const entity::inverse_attribute*> attributes; attributes.reserve(%d);' % len(type.inverse.elements))
|
||||||
|
for attr in type.inverse.elements:
|
||||||
|
if attr.bounds:
|
||||||
|
make_bound = lambda b: -1 if b == '?' else int(b)
|
||||||
|
bound1, bound2 = map(make_bound, (attr.bounds.lower, attr.bounds.upper))
|
||||||
|
else:
|
||||||
|
bound1, bound2 = -1, -1
|
||||||
|
attr_name, aggr_type, entity_ref = attr.name, attr.type, attr.entity
|
||||||
|
if aggr_type is None: aggr_type = 'unspecified'
|
||||||
|
attribute_entity, attribute_entity_index = find_inverse_name_and_index(entity_ref, attr.attribute)
|
||||||
|
statements.append(' attributes.push_back(new entity::inverse_attribute("%(attr_name)s", entity::inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(entity_ref)s_type, %(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
|
||||||
|
statements.append(' %(name)s_type->set_inverse_attributes(attributes);' % locals())
|
||||||
|
statements.append(' }')
|
||||||
|
|
||||||
|
statements.append('')
|
||||||
|
statements.append(' std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);' % locals())
|
||||||
|
for type_name in declared_types:
|
||||||
|
statements.append(' declarations.push_back(%(type_name)s);' % locals())
|
||||||
|
|
||||||
|
statements.append(' return new schema_definition("%(schema_name)s", declarations, true);' % locals())
|
||||||
|
|
||||||
|
statements.extend(('}',''))
|
||||||
|
|
||||||
|
statements.append('#ifdef _MSC_VER' )
|
||||||
|
statements.append('#pragma optimize("", on)')
|
||||||
|
statements.append('#endif' )
|
||||||
|
|
||||||
|
statements.extend(('const schema_definition& get_schema() {',
|
||||||
|
'',
|
||||||
|
' static const schema_definition* s = populate_schema();',
|
||||||
|
' return *s;',
|
||||||
|
'}','',''))
|
||||||
|
|
||||||
|
self.str = "\n".join(statements)
|
||||||
|
|
||||||
|
self.file_name = '%s-schema.cpp'%self.schema_name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.str
|
||||||
@@ -30,11 +30,14 @@ header = """
|
|||||||
|
|
||||||
#include "../ifcparse/IfcEntityList.h"
|
#include "../ifcparse/IfcEntityList.h"
|
||||||
#include "../ifcparse/IfcBaseClass.h"
|
#include "../ifcparse/IfcBaseClass.h"
|
||||||
|
#include "../ifcparse/IfcSchema.h"
|
||||||
#include "../ifcparse/IfcException.h"
|
#include "../ifcparse/IfcException.h"
|
||||||
#include "../ifcparse/Argument.h"
|
#include "../ifcparse/Argument.h"
|
||||||
|
|
||||||
#include "../ifcparse/%(schema_name)senum.h"
|
#include "../ifcparse/%(schema_name)senum.h"
|
||||||
|
|
||||||
|
const IfcParse::schema_definition& get_schema();
|
||||||
|
|
||||||
#define IfcSchema %(schema_name)s
|
#define IfcSchema %(schema_name)s
|
||||||
|
|
||||||
namespace %(schema_name)s {
|
namespace %(schema_name)s {
|
||||||
@@ -112,6 +115,7 @@ namespace Type {
|
|||||||
|
|
||||||
implementation= """
|
implementation= """
|
||||||
#include "../ifcparse/%(schema_name)s.h"
|
#include "../ifcparse/%(schema_name)s.h"
|
||||||
|
#include "../ifcparse/IfcSchema.h"
|
||||||
#include "../ifcparse/IfcException.h"
|
#include "../ifcparse/IfcException.h"
|
||||||
#include "../ifcparse/IfcWrite.h"
|
#include "../ifcparse/IfcWrite.h"
|
||||||
|
|
||||||
@@ -121,6 +125,9 @@ using namespace %(schema_name)s;
|
|||||||
using namespace IfcParse;
|
using namespace IfcParse;
|
||||||
using namespace IfcWrite;
|
using namespace IfcWrite;
|
||||||
|
|
||||||
|
// External definitions
|
||||||
|
%(external_definitions)s
|
||||||
|
|
||||||
IfcUtil::IfcBaseClass* %(schema_name)s::SchemaEntity(IfcEntityInstanceData* e) {
|
IfcUtil::IfcBaseClass* %(schema_name)s::SchemaEntity(IfcEntityInstanceData* e) {
|
||||||
switch(e->type()) {
|
switch(e->type()) {
|
||||||
%(schema_entity_statements)s
|
%(schema_entity_statements)s
|
||||||
@@ -353,10 +360,7 @@ derived_field_statement_attrs = 'idxs.insert(%d); '
|
|||||||
simpletype = """%(documentation)s
|
simpletype = """%(documentation)s
|
||||||
class IFC_PARSE_API %(name)s : public %(superclass)s {
|
class IFC_PARSE_API %(name)s : public %(superclass)s {
|
||||||
public:
|
public:
|
||||||
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const;
|
virtual const IfcParse::type_declaration& declaration() const;
|
||||||
virtual Argument* getArgument(unsigned int i) const;
|
|
||||||
bool is(Type::Enum v) const;
|
|
||||||
Type::Enum type() const;
|
|
||||||
static Type::Enum Class();
|
static Type::Enum Class();
|
||||||
explicit %(name)s (IfcEntityInstanceData* e);
|
explicit %(name)s (IfcEntityInstanceData* e);
|
||||||
%(name)s (%(type)s v);
|
%(name)s (%(type)s v);
|
||||||
@@ -366,16 +370,17 @@ public:
|
|||||||
|
|
||||||
simpletype_impl_comment = "// Function implementations for %(name)s"
|
simpletype_impl_comment = "// Function implementations for %(name)s"
|
||||||
simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException(\"Argument index out of range\"); }"
|
simpletype_impl_argument_type = "if (i == 0) { return %(attr_type)s; } else { throw IfcParse::IfcAttributeOutOfRangeException(\"Argument index out of range\"); }"
|
||||||
simpletype_impl_argument = "return entity->getArgument(i);"
|
simpletype_impl_argument = "return data_->getArgument(i);"
|
||||||
simpletype_impl_is_with_supertype = "return v == Type::%(class_name)s || %(superclass)s::is(v);"
|
simpletype_impl_is_with_supertype = "return v == Type::%(class_name)s || %(superclass)s::is(v);"
|
||||||
simpletype_impl_is_without_supertype = "return v == %(class_name)s::Class();"
|
simpletype_impl_is_without_supertype = "return v == %(class_name)s::Class();"
|
||||||
simpletype_impl_type = "return Type::%(class_name)s;"
|
simpletype_impl_type = "return Type::%(class_name)s;"
|
||||||
simpletype_impl_class = "return Type::%(class_name)s;"
|
simpletype_impl_class = "return Type::%(class_name)s;"
|
||||||
simpletype_impl_explicit_constructor = "entity = e;"
|
simpletype_impl_explicit_constructor = "data_ = e;"
|
||||||
simpletype_impl_constructor = "entity = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v" +"); entity->setArgument(0, attr);}"
|
simpletype_impl_constructor = "data_ = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v" +"); data_->setArgument(0, attr);}"
|
||||||
simpletype_impl_constructor_templated = "entity = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); entity->setArgument(0, attr);}"
|
simpletype_impl_constructor_templated = "data_ = new IfcEntityInstanceData(Class()); {IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(v->generalize()); data_->setArgument(0, attr);}"
|
||||||
simpletype_impl_cast = "return *entity->getArgument(0);"
|
simpletype_impl_cast = "return *data_->getArgument(0);"
|
||||||
simpletype_impl_cast_templated = "IfcEntityList::ptr es = *entity->getArgument(0); return es->as<%(underlying_type)s>();"
|
simpletype_impl_cast_templated = "IfcEntityList::ptr es = *data_->getArgument(0); return es->as<%(underlying_type)s>();"
|
||||||
|
simpletype_impl_declaration = "return *%(class_name)s_type;"
|
||||||
|
|
||||||
select = """%(documentation)s
|
select = """%(documentation)s
|
||||||
typedef IfcUtil::IfcBaseClass %(name)s;
|
typedef IfcUtil::IfcBaseClass %(name)s;
|
||||||
@@ -392,13 +397,7 @@ IFC_PARSE_API %(name)s FromString(const std::string& s);
|
|||||||
entity = """%(documentation)s
|
entity = """%(documentation)s
|
||||||
class IFC_PARSE_API %(name)s %(superclass)s{
|
class IFC_PARSE_API %(name)s %(superclass)s{
|
||||||
public:
|
public:
|
||||||
%(attributes)s virtual unsigned int getArgumentCount() const { return %(argument_count)d; }
|
%(attributes)s %(inverse)s virtual const IfcParse::entity& declaration() const;
|
||||||
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const {%(argument_type_function_body)s}
|
|
||||||
virtual Type::Enum getArgumentEntity(unsigned int i) const {%(argument_entity_function_body)s}
|
|
||||||
virtual const char* getArgumentName(unsigned int i) const {%(argument_name_function_body)s}
|
|
||||||
virtual Argument* getArgument(unsigned int i) const { return entity->getArgument(i); }
|
|
||||||
%(inverse)s bool is(Type::Enum v) const;
|
|
||||||
Type::Enum type() const;
|
|
||||||
static Type::Enum Class();
|
static Type::Enum Class();
|
||||||
%(name)s (IfcEntityInstanceData* e);
|
%(name)s (IfcEntityInstanceData* e);
|
||||||
%(name)s (%(constructor_arguments)s);
|
%(name)s (%(constructor_arguments)s);
|
||||||
@@ -420,11 +419,12 @@ const char* %(name)s::ToString(%(name)s v) {
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
entity_implementation = """// Function implementations for %(name)s
|
entity_implementation = """// Function implementations for %(name)s
|
||||||
%(attributes)s%(inverse)sbool %(name)s::is(Type::Enum v) const { return v == Type::%(name)s%(parent_type_test)s; }
|
%(attributes)s
|
||||||
Type::Enum %(name)s::type() const { return Type::%(name)s; }
|
%(inverse)s
|
||||||
|
const IfcParse::entity& %(name)s::declaration() const { return *%(name)s_type; }
|
||||||
Type::Enum %(name)s::Class() { return Type::%(name)s; }
|
Type::Enum %(name)s::Class() { return Type::%(name)s; }
|
||||||
%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (e->type() != Type::%(name)s) throw IfcException("Unable to find find keyword in schema"); entity = e; }
|
%(name)s::%(name)s(IfcEntityInstanceData* e) : %(superclass)s { if (!e) return; if (!e->is(Type::%(name)s)) throw IfcException("Unable to find find keyword in schema"); data_ = e; }
|
||||||
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {entity = new IfcEntityInstanceData(Class()); %(constructor_implementation)s }
|
%(name)s::%(name)s(%(constructor_arguments)s) : %(superclass)s {data_ = new IfcEntityInstanceData(Class()); %(constructor_implementation)s }
|
||||||
"""
|
"""
|
||||||
|
|
||||||
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
|
optional_attribute_description = "/// Whether the optional attribute %s is defined for this %s"
|
||||||
@@ -450,24 +450,24 @@ parent_type_stmt = ' if(v==%(name)s%(padding)s) { return %(parent)s; }'
|
|||||||
|
|
||||||
parent_type_test = " || %s::is(v)"
|
parent_type_test = " || %s::is(v)"
|
||||||
|
|
||||||
optional_attr_stmt = "return !entity->getArgument(%(index)d)->isNull();"
|
optional_attr_stmt = "return !data_->getArgument(%(index)d)->isNull();"
|
||||||
|
|
||||||
get_attr_stmt = "return *entity->getArgument(%(index)d);"
|
get_attr_stmt = "return *data_->getArgument(%(index)d);"
|
||||||
get_attr_stmt_enum = "return %(type)s::FromString(*entity->getArgument(%(index)d));"
|
get_attr_stmt_enum = "return %(type)s::FromString(*data_->getArgument(%(index)d));"
|
||||||
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*entity->getArgument(%(index)d)));"
|
get_attr_stmt_entity = "return (%(type)s)((IfcUtil::IfcBaseClass*)(*data_->getArgument(%(index)d)));"
|
||||||
get_attr_stmt_array = "IfcEntityList::ptr es = *entity->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
|
get_attr_stmt_array = "IfcEntityList::ptr es = *data_->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
|
||||||
get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *entity->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
|
get_attr_stmt_nested_array = "IfcEntityListList::ptr es = *data_->getArgument(%(index)d); return es->as<%(list_instance_type)s>();"
|
||||||
|
|
||||||
get_inverse = "return entity->getInverse(Type::%(type)s, %(index)d)->as<%(type)s>();"
|
get_inverse = "return data_->getInverse(Type::%(type)s, %(index)d)->as<%(type)s>();"
|
||||||
|
|
||||||
set_attr_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v" +");entity->setArgument(%(index)d,attr);}"
|
set_attr_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v" +");data_->setArgument(%(index)d,attr);}"
|
||||||
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));entity->setArgument(%(index)d,attr);}"
|
set_attr_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::EnumerationReference(v,%(type)s::ToString(v)));data_->setArgument(%(index)d,attr);}"
|
||||||
set_attr_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()" +");entity->setArgument(%(index)d,attr);}"
|
set_attr_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(v->generalize()" +");data_->setArgument(%(index)d,attr);}"
|
||||||
|
|
||||||
constructor_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)" +");entity->setArgument(%(index)d,attr);}"
|
constructor_stmt = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)" +");data_->setArgument(%(index)d,attr);}"
|
||||||
constructor_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))" +");entity->setArgument(%(index)d,attr);}"
|
constructor_stmt_enum = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((IfcWrite::IfcWriteArgument::EnumerationReference(%(name)s,%(type)s::ToString(%(name)s)))" +");data_->setArgument(%(index)d,attr);}"
|
||||||
constructor_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()" +");entity->setArgument(%(index)d,attr);}"
|
constructor_stmt_array = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set((%(name)s)->generalize()" +");data_->setArgument(%(index)d,attr);}"
|
||||||
constructor_stmt_derived = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()" +");entity->setArgument(%(index)d,attr);}"
|
constructor_stmt_derived = "{IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument();attr->set(IfcWrite::IfcWriteArgument::Derived()" +");data_->setArgument(%(index)d,attr);}"
|
||||||
|
|
||||||
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); entity->setArgument(%(index)d, attr); }"
|
constructor_stmt_optional = " if (%(name)s) {%(stmt)s } else { IfcWrite::IfcWriteArgument* attr = new IfcWrite::IfcWriteArgument(); attr->set(boost::blank()); entity->setArgument(%(index)d, attr); }"
|
||||||
|
|
||||||
|
|||||||
+26
-18
@@ -32,20 +32,28 @@
|
|||||||
|
|
||||||
class Argument;
|
class Argument;
|
||||||
|
|
||||||
|
namespace IfcParse { // these have to be declared first in order for the virtual function below to be covariant. separate into different header file
|
||||||
|
class declaration;
|
||||||
|
class entity;
|
||||||
|
class type_declaration;
|
||||||
|
}
|
||||||
|
|
||||||
namespace IfcUtil {
|
namespace IfcUtil {
|
||||||
|
|
||||||
class IFC_PARSE_API IfcBaseClass {
|
class IFC_PARSE_API IfcBaseClass {
|
||||||
public:
|
protected:
|
||||||
virtual ~IfcBaseClass() {}
|
IfcAbstractEntity* data_;
|
||||||
IfcEntityInstanceData* entity;
|
|
||||||
virtual bool is(IfcSchema::Type::Enum v) const = 0;
|
|
||||||
virtual IfcSchema::Type::Enum type() const = 0;
|
|
||||||
|
|
||||||
virtual unsigned int getArgumentCount() const = 0;
|
public:
|
||||||
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const = 0;
|
IfcBaseClass() : data_(0) {}
|
||||||
virtual IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const = 0;
|
IfcBaseClass(IfcAbstractEntity* d) : data_(d) {}
|
||||||
virtual Argument* getArgument(unsigned int i) const = 0;
|
virtual ~IfcBaseClass() {}
|
||||||
virtual const char* getArgumentName(unsigned int i) const = 0;
|
|
||||||
|
const IfcAbstractEntity& data() const { return *data_; }
|
||||||
|
IfcAbstractEntity& data() { return *data_; }
|
||||||
|
void data(IfcAbstractEntity* d);
|
||||||
|
|
||||||
|
virtual const IfcParse::declaration& declaration() const = 0;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T* as() {
|
T* as() {
|
||||||
@@ -64,19 +72,19 @@ namespace IfcUtil {
|
|||||||
|
|
||||||
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
|
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
|
||||||
public:
|
public:
|
||||||
Argument* getArgumentByName(const std::string& name) const;
|
IfcBaseEntity() : IfcBaseClass() {}
|
||||||
std::vector<std::string> getAttributeNames() const;
|
IfcBaseEntity(IfcAbstractEntity* d) : IfcBaseClass(d) {}
|
||||||
std::vector<std::string> getInverseAttributeNames() const;
|
|
||||||
unsigned id() const { return entity->id(); }
|
virtual const IfcParse::entity& declaration() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Investigate whether these should be template classes instead
|
// TODO: Investigate whether these should be template classes instead
|
||||||
class IFC_PARSE_API IfcBaseType : public IfcBaseEntity {
|
class IFC_PARSE_API IfcBaseType : public IfcBaseEntity {
|
||||||
public:
|
public:
|
||||||
unsigned int getArgumentCount() const;
|
IfcBaseType() : IfcBaseClass() {}
|
||||||
Argument* getArgument(unsigned int i) const;
|
IfcBaseType(IfcAbstractEntity* d) : IfcBaseClass(d) {}
|
||||||
const char* getArgumentName(unsigned int i) const;
|
|
||||||
IfcSchema::Type::Enum getArgumentEntity(unsigned int /*i*/) const { return IfcSchema::Type::UNDEFINED; }
|
virtual const IfcParse::type_declaration& declaration() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ private:
|
|||||||
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
|
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
|
||||||
|
|
||||||
bool parsing_complete_;
|
bool parsing_complete_;
|
||||||
|
const schema_definition* schema_;
|
||||||
|
|
||||||
entity_by_id_t byid;
|
entity_by_id_t byid;
|
||||||
entities_by_type_t bytype;
|
entities_by_type_t bytype;
|
||||||
@@ -170,6 +171,7 @@ public:
|
|||||||
void register_inverse(unsigned, Token);
|
void register_inverse(unsigned, Token);
|
||||||
void register_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
void register_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
||||||
void unregister_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
void unregister_inverse(unsigned, IfcUtil::IfcBaseClass*);
|
||||||
|
const schema_definition* schema() const { return schema_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "../ifcparse/IfcSpfStream.h"
|
#include "../ifcparse/IfcSpfStream.h"
|
||||||
#include "../ifcparse/IfcFile.h"
|
#include "../ifcparse/IfcFile.h"
|
||||||
#include "../ifcparse/IfcSIPrefix.h"
|
#include "../ifcparse/IfcSIPrefix.h"
|
||||||
|
#include "../ifcparse/IfcSchema.h"
|
||||||
|
|
||||||
#ifdef USE_IFC4
|
#ifdef USE_IFC4
|
||||||
#include "../ifcparse/Ifc4-latebound.h"
|
#include "../ifcparse/Ifc4-latebound.h"
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include "IfcSchema.h"
|
||||||
|
|
||||||
|
bool IfcParse::declaration::is(const std::string& name) const {
|
||||||
|
return is(IfcSchema::Type::FromString(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcParse::declaration::is(IfcSchema::Type::Enum name) const {
|
||||||
|
if (this->as_entity()) {
|
||||||
|
return this->as_entity()->is(name);
|
||||||
|
} else {
|
||||||
|
return this->name() == IfcSchema::Type::ToString(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcParse::named_type::is(const std::string& name) const {
|
||||||
|
return declared_type()->is(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IfcParse::named_type::is(IfcSchema::Type::Enum name) const {
|
||||||
|
return declared_type()->is(name);
|
||||||
|
}
|
||||||
@@ -0,0 +1,432 @@
|
|||||||
|
/********************************************************************************
|
||||||
|
* *
|
||||||
|
* This file is part of IfcOpenShell. *
|
||||||
|
* *
|
||||||
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the Lesser GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, either version 3.0 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 *
|
||||||
|
* Lesser GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the Lesser GNU General Public License *
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef IFCSCHEMA_H
|
||||||
|
#define IFCSCHEMA_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
#include "../ifcparse/IfcException.h"
|
||||||
|
|
||||||
|
#ifdef USE_IFC4
|
||||||
|
#include "../ifcparse/Ifc4enum.h"
|
||||||
|
#else
|
||||||
|
#include "../ifcparse/Ifc2x3enum.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace IfcParse {
|
||||||
|
|
||||||
|
class declaration;
|
||||||
|
|
||||||
|
class type_declaration;
|
||||||
|
class select_type;
|
||||||
|
class enumeration_type;
|
||||||
|
class entity;
|
||||||
|
|
||||||
|
class named_type;
|
||||||
|
class simple_type;
|
||||||
|
class aggregation_type;
|
||||||
|
|
||||||
|
class parameter_type {
|
||||||
|
public:
|
||||||
|
virtual const named_type* as_named_type() const { return static_cast<named_type*>(0); }
|
||||||
|
virtual const simple_type* as_simple_type() const { return static_cast<simple_type*>(0); }
|
||||||
|
virtual const aggregation_type* as_aggregation_type() const { return static_cast<aggregation_type*>(0); }
|
||||||
|
|
||||||
|
virtual bool is(const std::string& /*name*/) const { return false; }
|
||||||
|
virtual bool is(IfcSchema::Type::Enum /*name*/) const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class named_type : public parameter_type {
|
||||||
|
protected:
|
||||||
|
declaration* declared_type_;
|
||||||
|
public:
|
||||||
|
named_type(declaration* declared_type)
|
||||||
|
: declared_type_(declared_type) {}
|
||||||
|
|
||||||
|
declaration* declared_type() const { return declared_type_; }
|
||||||
|
|
||||||
|
virtual const named_type* as_named_type() const { return this; }
|
||||||
|
|
||||||
|
virtual bool is(const std::string& name) const;
|
||||||
|
virtual bool is(IfcSchema::Type::Enum name) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class simple_type : public parameter_type {
|
||||||
|
public:
|
||||||
|
typedef enum { binary_type, boolean_type, integer_type, logical_type, number_type, real_type, string_type, datatype_COUNT } data_type;
|
||||||
|
protected:
|
||||||
|
data_type declared_type_;
|
||||||
|
public:
|
||||||
|
simple_type(data_type declared_type)
|
||||||
|
: declared_type_(declared_type) {}
|
||||||
|
|
||||||
|
data_type declared_type() const { return declared_type_; }
|
||||||
|
|
||||||
|
virtual const simple_type* as_simple_type() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class aggregation_type : public parameter_type {
|
||||||
|
public:
|
||||||
|
typedef enum { array_type, bag_type, list_type, set_type } aggregate_type;
|
||||||
|
protected:
|
||||||
|
aggregate_type type_of_aggregation_;
|
||||||
|
int bound1_, bound2_;
|
||||||
|
parameter_type* type_of_element_;
|
||||||
|
public:
|
||||||
|
aggregation_type(aggregate_type type_of_aggregation, int bound1, int bound2, parameter_type* type_of_element)
|
||||||
|
: type_of_aggregation_(type_of_aggregation)
|
||||||
|
, bound1_(bound1)
|
||||||
|
, bound2_(bound2)
|
||||||
|
, type_of_element_(type_of_element)
|
||||||
|
{}
|
||||||
|
|
||||||
|
aggregate_type type_of_aggregation() const { type_of_aggregation_; }
|
||||||
|
int bound1() const { return bound1_; }
|
||||||
|
int bound2() const { return bound2_; }
|
||||||
|
parameter_type* type_of_element() const { return type_of_element_; }
|
||||||
|
|
||||||
|
virtual const aggregation_type* as_aggregation_type() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class declaration {
|
||||||
|
protected:
|
||||||
|
// std::string name_;
|
||||||
|
IfcSchema::Type::Enum name_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
declaration(IfcSchema::Type::Enum name)
|
||||||
|
: name_(name) {}
|
||||||
|
declaration(const std::string& name)
|
||||||
|
: name_(IfcSchema::Type::FromString(name)) {}
|
||||||
|
|
||||||
|
std::string name() const { return IfcSchema::Type::ToString(name_); }
|
||||||
|
|
||||||
|
virtual const type_declaration* as_type_declaration() const { return static_cast<type_declaration*>(0); }
|
||||||
|
virtual const select_type* as_select_type() const { return static_cast<select_type*>(0); }
|
||||||
|
virtual const enumeration_type* as_enumeration_type() const { return static_cast<enumeration_type*>(0); }
|
||||||
|
virtual const entity* as_entity() const { return static_cast<entity*>(0); }
|
||||||
|
|
||||||
|
// TODO: Type checking by Enum value
|
||||||
|
bool is(const std::string& name) const;
|
||||||
|
bool is(IfcSchema::Type::Enum name) const;
|
||||||
|
|
||||||
|
IfcSchema::Type::Enum type() const {
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class type_declaration : public declaration {
|
||||||
|
protected:
|
||||||
|
const parameter_type* declared_type_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
type_declaration(const std::string& name, const parameter_type* declared_type)
|
||||||
|
: declaration(name)
|
||||||
|
, declared_type_(declared_type) {}
|
||||||
|
type_declaration(IfcSchema::Type::Enum name, const parameter_type* declared_type)
|
||||||
|
: declaration(name)
|
||||||
|
, declared_type_(declared_type) {}
|
||||||
|
|
||||||
|
const parameter_type* declared_type() const { return declared_type_; }
|
||||||
|
|
||||||
|
virtual const type_declaration* as_type_declaration() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class select_type : public declaration {
|
||||||
|
protected:
|
||||||
|
std::vector<const declaration*> select_list_;
|
||||||
|
public:
|
||||||
|
select_type(const std::string& name, const std::vector<const declaration*>& select_list)
|
||||||
|
: declaration(name)
|
||||||
|
, select_list_(select_list) {}
|
||||||
|
select_type(IfcSchema::Type::Enum name, const std::vector<const declaration*>& select_list)
|
||||||
|
: declaration(name)
|
||||||
|
, select_list_(select_list) {}
|
||||||
|
|
||||||
|
const std::vector<const declaration*>& select_list() const { return select_list_; }
|
||||||
|
|
||||||
|
virtual const select_type* as_select_type() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class enumeration_type : public declaration {
|
||||||
|
protected:
|
||||||
|
std::vector<std::string> enumeration_items_;
|
||||||
|
public:
|
||||||
|
enumeration_type(const std::string& name, const std::vector<std::string>& enumeration_items)
|
||||||
|
: declaration(name)
|
||||||
|
, enumeration_items_(enumeration_items) {}
|
||||||
|
enumeration_type(IfcSchema::Type::Enum name, const std::vector<std::string>& enumeration_items)
|
||||||
|
: declaration(name)
|
||||||
|
, enumeration_items_(enumeration_items) {}
|
||||||
|
|
||||||
|
const std::vector<std::string>& enumeration_items() const { return enumeration_items_; }
|
||||||
|
|
||||||
|
virtual const enumeration_type* as_enumeration_type() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class entity : public declaration {
|
||||||
|
public:
|
||||||
|
class attribute {
|
||||||
|
protected:
|
||||||
|
std::string name_;
|
||||||
|
const parameter_type* type_of_attribute_;
|
||||||
|
bool optional_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
|
||||||
|
: name_(name)
|
||||||
|
, type_of_attribute_(type_of_attribute)
|
||||||
|
, optional_(optional) {}
|
||||||
|
|
||||||
|
const std::string& name() const { return name_; }
|
||||||
|
const parameter_type* type_of_attribute() const { return type_of_attribute_; }
|
||||||
|
bool optional() const { return optional_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class inverse_attribute {
|
||||||
|
public:
|
||||||
|
typedef enum { bag_type, set_type, unspecified_type } aggregate_type;
|
||||||
|
protected:
|
||||||
|
std::string name_;
|
||||||
|
aggregate_type type_of_aggregation_;
|
||||||
|
int bound1_, bound2_;
|
||||||
|
parameter_type* type_of_element_;
|
||||||
|
const entity* entity_reference_;
|
||||||
|
const attribute* attribute_reference_;
|
||||||
|
public:
|
||||||
|
inverse_attribute(const std::string& name, aggregate_type type_of_aggregation, int bound1, int bound2, const entity* entity_reference, const attribute* attribute_reference)
|
||||||
|
: name_(name)
|
||||||
|
, type_of_aggregation_(type_of_aggregation)
|
||||||
|
, bound1_(bound1)
|
||||||
|
, bound2_(bound2)
|
||||||
|
, entity_reference_(entity_reference)
|
||||||
|
, attribute_reference_(attribute_reference)
|
||||||
|
{}
|
||||||
|
|
||||||
|
const std::string& name() const { return name_; }
|
||||||
|
aggregate_type type_of_aggregation() const { type_of_aggregation_; }
|
||||||
|
int bound1() const { return bound1_; }
|
||||||
|
int bound2() const { return bound2_; }
|
||||||
|
const entity* entity_reference() const { return entity_reference_; }
|
||||||
|
const attribute* attribute_reference() const { return attribute_reference_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */
|
||||||
|
std::vector<const entity*> subtypes_;
|
||||||
|
|
||||||
|
std::vector<const attribute*> attributes_;
|
||||||
|
std::vector<bool> derived_;
|
||||||
|
|
||||||
|
std::vector<const inverse_attribute*> inverse_attributes_;
|
||||||
|
|
||||||
|
class attribute_by_name_cmp : public std::unary_function<const attribute*, bool> {
|
||||||
|
private:
|
||||||
|
std::string name_;
|
||||||
|
public:
|
||||||
|
attribute_by_name_cmp(const std::string name)
|
||||||
|
: name_(name) {}
|
||||||
|
bool operator()(const attribute* attr) {
|
||||||
|
return attr->name() == name_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
entity(const std::string& name, entity* supertype)
|
||||||
|
: declaration(name)
|
||||||
|
, supertype_(supertype)
|
||||||
|
{}
|
||||||
|
entity(IfcSchema::Type::Enum name, entity* supertype)
|
||||||
|
: declaration(name)
|
||||||
|
, supertype_(supertype)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool is(const std::string& name) const {
|
||||||
|
return is(IfcSchema::Type::FromString(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is(IfcSchema::Type::Enum name) const {
|
||||||
|
if (name == name_) return true;
|
||||||
|
else if (supertype_) return supertype_->is(name);
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_subtypes(const std::vector<const entity*>& subtypes) {
|
||||||
|
subtypes_ = subtypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_attributes(const std::vector<const attribute*>& attributes, const std::vector<bool>& derived) {
|
||||||
|
attributes_ = attributes;
|
||||||
|
derived_ = derived;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inverse_attributes(const std::vector<const inverse_attribute*>& inverse_attributes) {
|
||||||
|
inverse_attributes_ = inverse_attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<const entity*>& subtypes() const { return subtypes_; }
|
||||||
|
const std::vector<const attribute*>& attributes() const { return attributes_; }
|
||||||
|
const std::vector<bool>& derived() const { return derived_; }
|
||||||
|
|
||||||
|
const std::vector<const attribute*> all_attributes() const {
|
||||||
|
std::vector<const attribute*> attrs;
|
||||||
|
attrs.reserve(derived_.size());
|
||||||
|
if (supertype_) {
|
||||||
|
const std::vector<const attribute*> supertype_attrs = supertype_->all_attributes();
|
||||||
|
std::copy(supertype_attrs.begin(), supertype_attrs.end(), std::back_inserter(attrs));
|
||||||
|
}
|
||||||
|
std::copy(attributes_.begin(), attributes_.end(), std::back_inserter(attrs));
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<const inverse_attribute*> all_inverse_attributes() const {
|
||||||
|
std::vector<const inverse_attribute*> attrs;
|
||||||
|
if (supertype_) {
|
||||||
|
const std::vector<const inverse_attribute*> supertype_inv_attrs = supertype_->all_inverse_attributes();
|
||||||
|
std::copy(supertype_inv_attrs.begin(), supertype_inv_attrs.end(), std::back_inserter(attrs));
|
||||||
|
}
|
||||||
|
std::copy(inverse_attributes_.begin(), inverse_attributes_.end(), std::back_inserter(attrs));
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t attribute_index(const attribute* attr) const {
|
||||||
|
const entity* current = this;
|
||||||
|
ptrdiff_t index = -1;
|
||||||
|
do {
|
||||||
|
if (index > -1) {
|
||||||
|
index += current->attributes().size();
|
||||||
|
} else {
|
||||||
|
auto it = std::find(current->attributes().begin(), current->attributes().end(), attr);
|
||||||
|
if (it != current->attributes().end()) {
|
||||||
|
index = std::distance(current->attributes().begin(), it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (current = current->supertype_);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptrdiff_t attribute_index(const std::string& attr_name) const {
|
||||||
|
const entity* current = this;
|
||||||
|
ptrdiff_t index = -1;
|
||||||
|
attribute_by_name_cmp cmp(attr_name);
|
||||||
|
do {
|
||||||
|
if (index > -1) {
|
||||||
|
index += current->attributes().size();
|
||||||
|
} else {
|
||||||
|
auto it = std::find_if(current->attributes().begin(), current->attributes().end(), cmp);
|
||||||
|
if (it != current->attributes().end()) {
|
||||||
|
index = std::distance(current->attributes().begin(), it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (current = current->supertype_);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entity* supertype() const { return supertype_; }
|
||||||
|
|
||||||
|
virtual const entity* as_entity() const { return this; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class schema_definition {
|
||||||
|
private:
|
||||||
|
bool built_in_;
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
|
||||||
|
std::vector<const declaration*> declarations_;
|
||||||
|
|
||||||
|
std::vector<const type_declaration*> type_declarations_;
|
||||||
|
std::vector<const select_type*> select_types_;
|
||||||
|
std::vector<const enumeration_type*> enumeration_types_;
|
||||||
|
std::vector<const entity*> entities_;
|
||||||
|
|
||||||
|
class declaration_by_name_cmp : public std::binary_function<const declaration*, const std::string&, bool> {
|
||||||
|
public:
|
||||||
|
bool operator()(const declaration* decl, const std::string& name) {
|
||||||
|
// TODO: Efficiency?
|
||||||
|
return boost::to_lower_copy(decl->name()) < boost::to_lower_copy(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class declaration_by_enum_cmp : public std::binary_function<const declaration*, IfcSchema::Type::Enum, bool> {
|
||||||
|
public:
|
||||||
|
bool operator()(const declaration* decl, IfcSchema::Type::Enum name) {
|
||||||
|
return decl->type() < name;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class declaration_by_enum_sort : public std::binary_function<const declaration*, const declaration*, bool> {
|
||||||
|
public:
|
||||||
|
bool operator()(const declaration* a, const declaration* b) {
|
||||||
|
return a->type() < b->type();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
schema_definition(const std::string& name, const std::vector<const declaration*>& declarations, const bool built_in = false)
|
||||||
|
: name_(name)
|
||||||
|
, declarations_(declarations)
|
||||||
|
, built_in_(built_in)
|
||||||
|
{
|
||||||
|
std::sort(declarations_.begin(), declarations_.end(), declaration_by_enum_sort());
|
||||||
|
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||||
|
if ((**it).as_type_declaration()) type_declarations_.push_back((**it).as_type_declaration());
|
||||||
|
if ((**it).as_select_type()) select_types_.push_back((**it).as_select_type());
|
||||||
|
if ((**it).as_enumeration_type()) enumeration_types_.push_back((**it).as_enumeration_type());
|
||||||
|
if ((**it).as_entity()) entities_.push_back((**it).as_entity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~schema_definition() {
|
||||||
|
for (std::vector<const declaration*>::const_iterator it = declarations_.begin(); it != declarations_.end(); ++it) {
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const declaration* declaration_by_name(const std::string& name) const {
|
||||||
|
std::vector<const declaration*>::const_iterator it = std::lower_bound(declarations_.begin(), declarations_.end(), name, declaration_by_name_cmp());
|
||||||
|
if (it == declarations_.end() || boost::to_lower_copy((**it).name()) != boost::to_lower_copy(name)) {
|
||||||
|
throw IfcParse::IfcException("Entity with '" + name + "' not found");
|
||||||
|
} else {
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const declaration* declaration_by_name(IfcSchema::Type::Enum name) const {
|
||||||
|
if (!built_in_) throw;
|
||||||
|
return declarations_[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<const declaration*>& declarations() const { return declarations_; }
|
||||||
|
const std::vector<const type_declaration*>& type_declarations() const { return type_declarations_; }
|
||||||
|
const std::vector<const select_type*>& select_types() const { return select_types_; }
|
||||||
|
const std::vector<const enumeration_type*>& enumeration_types() const { return enumeration_types_; }
|
||||||
|
const std::vector<const entity*>& entities() const { return entities_; }
|
||||||
|
|
||||||
|
const std::string& name() const { return name_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -92,12 +92,6 @@ IfcEntityList::ptr IfcEntityList::unique() {
|
|||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int IfcUtil::IfcBaseType::getArgumentCount() const { return 1; }
|
|
||||||
Argument* IfcUtil::IfcBaseType::getArgument(unsigned int i) const { return entity->getArgument(i); }
|
|
||||||
const char* IfcUtil::IfcBaseType::getArgumentName(unsigned int i) const { if (i == 0) { return "wrappedValue"; } else { throw IfcParse::IfcAttributeOutOfRangeException("Argument index out of range"); } }
|
|
||||||
|
|
||||||
|
|
||||||
//Note: some of these methods are overloaded in derived classes
|
//Note: some of these methods are overloaded in derived classes
|
||||||
Argument::operator int() const { throw IfcParse::IfcException("Argument is not an integer"); }
|
Argument::operator int() const { throw IfcParse::IfcException("Argument is not an integer"); }
|
||||||
Argument::operator bool() const { throw IfcParse::IfcException("Argument is not a boolean"); }
|
Argument::operator bool() const { throw IfcParse::IfcException("Argument is not a boolean"); }
|
||||||
@@ -197,3 +191,12 @@ Argument* IfcUtil::IfcBaseEntity::getArgumentByName(const std::string& name) con
|
|||||||
unsigned int i = IfcSchema::Type::GetAttributeIndex(type(), name);
|
unsigned int i = IfcSchema::Type::GetAttributeIndex(type(), name);
|
||||||
return getArgument(i);
|
return getArgument(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IfcUtil::IfcBaseClass::~IfcBaseClass() {
|
||||||
|
delete data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfcUtil::IfcBaseClass::data(IfcAbstractEntity* d) {
|
||||||
|
delete data_;
|
||||||
|
data_ = d;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user