mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
Populate entity subtypes, get schema info in Python
This commit is contained in:
@@ -23,6 +23,8 @@ import nodes
|
||||
import codegen
|
||||
import templates
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
class SchemaClass(codegen.Base):
|
||||
def __init__(self, mapping):
|
||||
|
||||
@@ -167,11 +169,11 @@ __attribute__((optnone))
|
||||
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))
|
||||
statements.append(' std::vector<const 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(' attributes.push_back(new 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(' %(schema_name)s_%(name)s_type->set_attributes(attributes, derived);' % locals())
|
||||
@@ -180,7 +182,7 @@ __attribute__((optnone))
|
||||
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))
|
||||
statements.append(' std::vector<const 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)
|
||||
@@ -190,9 +192,22 @@ __attribute__((optnone))
|
||||
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, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
|
||||
statements.append(' attributes.push_back(new inverse_attribute("%(attr_name)s", inverse_attribute::%(aggr_type)s_type, %(bound1)d, %(bound2)d, %(schema_name)s_%(entity_ref)s_type, %(schema_name)s_%(attribute_entity)s_type->attributes()[%(attribute_entity_index)d]));' % locals())
|
||||
statements.append(' %(schema_name)s_%(name)s_type->set_inverse_attributes(attributes);' % locals())
|
||||
statements.append(' }')
|
||||
|
||||
subtypes = defaultdict(list)
|
||||
|
||||
for name, type in mapping.schema.entities.items():
|
||||
for ty in type.supertypes:
|
||||
subtypes[ty].append(name)
|
||||
|
||||
for name, tys in subtypes.items():
|
||||
statements.append(' {')
|
||||
statements.append(' std::vector<const entity*> defs; defs.reserve(%d);' % len(tys))
|
||||
statements.append((' ' + "".join(map(lambda t: ("defs.push_back(%%(schema_name)s_%s_type);" % t), tys))) % locals())
|
||||
statements.append(' %(schema_name)s_%(name)s_type->set_subtypes(defs);' % locals())
|
||||
statements.append(' }')
|
||||
|
||||
statements.append('')
|
||||
statements.append(' std::vector<const declaration*> declarations; declarations.reserve(%(num_declarations)d);' % locals())
|
||||
|
||||
+2981
-2151
File diff suppressed because it is too large
Load Diff
+3547
-2502
File diff suppressed because it is too large
Load Diff
+39
-41
@@ -195,52 +195,50 @@ namespace IfcParse {
|
||||
virtual const enumeration_type* as_enumeration_type() const { return this; }
|
||||
};
|
||||
|
||||
class entity : public declaration {
|
||||
class attribute {
|
||||
protected:
|
||||
std::string name_;
|
||||
const parameter_type* type_of_attribute_;
|
||||
bool optional_;
|
||||
|
||||
public:
|
||||
class attribute {
|
||||
protected:
|
||||
std::string name_;
|
||||
const parameter_type* type_of_attribute_;
|
||||
bool optional_;
|
||||
attribute(const std::string& name, parameter_type* type_of_attribute, bool optional)
|
||||
: name_(name)
|
||||
, type_of_attribute_(type_of_attribute)
|
||||
, optional_(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_; }
|
||||
};
|
||||
|
||||
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_;
|
||||
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) {}
|
||||
|
||||
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_;
|
||||
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 { return 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_; }
|
||||
};
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
aggregate_type type_of_aggregation() const { return 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_; }
|
||||
};
|
||||
|
||||
class entity : public declaration {
|
||||
protected:
|
||||
const entity* supertype_; /* NB: IFC explicitly allows only single inheritance */
|
||||
std::vector<const entity*> subtypes_;
|
||||
|
||||
@@ -47,7 +47,7 @@ protected:
|
||||
node_type type_;
|
||||
IfcUtil::IfcBaseClass* inst_;
|
||||
int idx_;
|
||||
const IfcParse::entity::inverse_attribute* inv_;
|
||||
const IfcParse::inverse_attribute* inv_;
|
||||
std::string tagname_;
|
||||
std::string id_in_file_;
|
||||
const IfcParse::parameter_type* aggregate_elem_type_;
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::entity::inverse_attribute* inv) {
|
||||
static stack_node inverse(IfcUtil::IfcBaseClass* inst, const IfcParse::inverse_attribute* inv) {
|
||||
stack_node n;
|
||||
n.type_ = node_inverse;
|
||||
n.inst_ = inst;
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
|
||||
IfcUtil::IfcBaseClass* inst() const { return inst_; }
|
||||
int idx() const { return idx_; }
|
||||
const IfcParse::entity::inverse_attribute* inv_attr() const { return inv_; }
|
||||
const IfcParse::inverse_attribute* inv_attr() const { return inv_; }
|
||||
const std::string& tagname() const { return tagname_; }
|
||||
const std::string& id_in_file() const { return id_in_file_; }
|
||||
const IfcParse::parameter_type* aggregate_elem_type() const { return aggregate_elem_type_; }
|
||||
@@ -483,7 +483,7 @@ static void start_element(void* user, const xmlChar* tag, const xmlChar** attrs)
|
||||
auto idx = current->attribute_index(tagname);
|
||||
if (idx == -1) {
|
||||
auto inverses = current->all_inverse_attributes();
|
||||
auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::entity::inverse_attribute* attr) {
|
||||
auto found = std::find_if(inverses.begin(), inverses.end(), [&tagname](const IfcParse::inverse_attribute* attr) {
|
||||
return attr->name() == tagname;
|
||||
});
|
||||
if (found == inverses.end()) {
|
||||
|
||||
+102
-10
@@ -136,8 +136,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
}
|
||||
|
||||
{
|
||||
const std::vector<const IfcParse::entity::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
|
||||
std::vector<const IfcParse::entity::attribute*>::const_iterator it = attrs.begin();
|
||||
const std::vector<const IfcParse::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
|
||||
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
if ((*it)->name() == name) {
|
||||
return 1;
|
||||
@@ -146,8 +146,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
}
|
||||
|
||||
{
|
||||
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
if ((*it)->name() == name) {
|
||||
return 2;
|
||||
@@ -178,12 +178,12 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
return std::vector<std::string>(1, "wrappedValue");
|
||||
}
|
||||
|
||||
const std::vector<const IfcParse::entity::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
|
||||
const std::vector<const IfcParse::attribute*> attrs = $self->declaration().as_entity()->all_attributes();
|
||||
|
||||
std::vector<std::string> attr_names;
|
||||
attr_names.reserve(attrs.size());
|
||||
|
||||
std::vector<const IfcParse::entity::attribute*>::const_iterator it = attrs.begin();
|
||||
std::vector<const IfcParse::attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
attr_names.push_back((*it)->name());
|
||||
}
|
||||
@@ -196,12 +196,12 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
return std::vector<std::string>(0);
|
||||
}
|
||||
|
||||
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
|
||||
std::vector<std::string> attr_names;
|
||||
attr_names.reserve(attrs.size());
|
||||
|
||||
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
attr_names.push_back((*it)->name());
|
||||
}
|
||||
@@ -260,8 +260,8 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
}
|
||||
|
||||
IfcEntityList::ptr get_inverse(const std::string& a) {
|
||||
const std::vector<const IfcParse::entity::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
std::vector<const IfcParse::entity::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
const std::vector<const IfcParse::inverse_attribute*> attrs = $self->declaration().as_entity()->all_inverse_attributes();
|
||||
std::vector<const IfcParse::inverse_attribute*>::const_iterator it = attrs.begin();
|
||||
for (; it != attrs.end(); ++it) {
|
||||
if ((*it)->name() == a) {
|
||||
return self->data().getInverse(
|
||||
@@ -586,6 +586,98 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas
|
||||
}
|
||||
%}
|
||||
|
||||
%extend IfcParse::named_type {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return repr(self.declared_type())
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::simple_type {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<%s>" % self.declared_type()
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::aggregation_type {
|
||||
std::string type_of_aggregation() const {
|
||||
static const char* const aggr_strings = ["array", "bag", "list", "set"];
|
||||
return aggr_strings[(int) type_of_aggregation_];
|
||||
}
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
format_bound = lambda i: "?" if i == -1 else str(i)
|
||||
return "<%s [%s:%s] of %r>" % (
|
||||
self.type_of_aggregation(),
|
||||
format_bound(self.bound1()),
|
||||
format_bound(self.bound2()),
|
||||
self.type_of_element()
|
||||
)
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::type_declaration {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<type %s: %r>" % (self.name(), self.declared_type())
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::select_type {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<select %s: (%s)>" % (self.name(), " | ".join(map(repr, self.select_list())))
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::enumeration_type {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<enumeration %s: (%s)>" % (self.name(), ", ".join(self.enumeration_items()))
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::attribute {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<attribute %s%s: %s>" % (self.name(), "?" if self.optional() else "", self.type_of_attribute())
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::inverse_attribute {
|
||||
std::string type_of_aggregation() const {
|
||||
static const char* const aggr_strings = ["bag", "set", ""];
|
||||
return aggr_strings[(int) type_of_aggregation_];
|
||||
}
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
format_bound = lambda i: "?" if i == -1 else str(i)
|
||||
return "<inverse %s: %s [%s:%s] of %r for %r>" % (
|
||||
self.name(),
|
||||
self.type_of_aggregation(),
|
||||
format_bound(self.bound1()),
|
||||
format_bound(self.bound2()),
|
||||
self.entity_reference(),
|
||||
self.attribute_reference()
|
||||
)
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::entity {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<entity %s>" % (self.name())
|
||||
%}
|
||||
}
|
||||
|
||||
%extend IfcParse::schema_definition {
|
||||
%pythoncode %{
|
||||
def __repr__(self):
|
||||
return "<schema %s>" % (self.name())
|
||||
%}
|
||||
}
|
||||
|
||||
%{
|
||||
static std::stringstream ifcopenshell_log_stream;
|
||||
%}
|
||||
|
||||
@@ -111,7 +111,10 @@
|
||||
PyObject* pythonize(const bool& t) { return PyBool_FromLong(t); }
|
||||
PyObject* pythonize(const double& t) { return PyFloat_FromDouble(t); }
|
||||
PyObject* pythonize(const std::string& t) { return PyUnicode_FromString(t.c_str()); }
|
||||
PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); }
|
||||
PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); }
|
||||
PyObject* pythonize(const IfcParse::attribute* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__attribute, 0); }
|
||||
PyObject* pythonize(const IfcParse::entity* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__entity, 0); }
|
||||
PyObject* pythonize(const IfcParse::declaration* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcParse__declaration, 0); }
|
||||
// NB: This cannot be temporary as a Python object is constructed from a pointer to the address of this object
|
||||
PyObject* pythonize(const IfcGeom::Material& t) { return SWIG_NewPointerObj(SWIG_as_voidptr(&t), SWIGTYPE_p_IfcGeom__Material, 0); }
|
||||
|
||||
|
||||
@@ -10,6 +10,33 @@
|
||||
$result = SWIG_Python_str_FromChar(IfcUtil::ArgumentTypeToString($1));
|
||||
}
|
||||
|
||||
%typemap(out) IfcParse::declaration* {
|
||||
if ($1->as_entity()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_entity()), SWIGTYPE_p_IfcParse__entity, 0);
|
||||
} else if ($1->as_type_declaration()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_type_declaration()), SWIGTYPE_p_IfcParse__type_declaration, 0);
|
||||
} else if ($1->as_select_type()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_select_type()), SWIGTYPE_p_IfcParse__select_type, 0);
|
||||
} else if ($1->as_enumeration_type()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_enumeration_type()), SWIGTYPE_p_IfcParse__enumeration_type, 0);
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) IfcParse::parameter_type* {
|
||||
if ($1->as_named_type()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_named_type()), SWIGTYPE_p_IfcParse__named_type, 0);
|
||||
} else if ($1->as_simple_type()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_simple_type()), SWIGTYPE_p_IfcParse__simple_type, 0);
|
||||
} else if ($1->as_aggregation_type()) {
|
||||
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1->as_aggregation_type()), SWIGTYPE_p_IfcParse__aggregation_type, 0);
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) IfcParse::simple_type::data_type {
|
||||
static const char* const data_type_strings[] = {"binary", "boolean", "integer", "logical", "number", "real", "string"};
|
||||
$result = SWIG_Python_str_FromChar(data_type_strings[(int)$1]);
|
||||
}
|
||||
|
||||
%typemap(out) std::pair<IfcUtil::ArgumentType, Argument*> {
|
||||
// The SWIG %exception directive does not take care
|
||||
// of our typemap. So the attribute conversion block
|
||||
@@ -106,3 +133,6 @@ CREATE_VECTOR_TYPEMAP_OUT(unsigned int)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(double)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(std::string)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(IfcGeom::Material)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::attribute const *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::entity const *)
|
||||
CREATE_VECTOR_TYPEMAP_OUT(IfcParse::declaration const *)
|
||||
|
||||
Reference in New Issue
Block a user