Support defined types with instance references in parser (IfcPropertySetDefinitionSet; #6330)

This commit is contained in:
Thomas Krijnen
2025-04-11 15:52:40 +02:00
parent ffffcc576e
commit 952400bd58
3 changed files with 82 additions and 14 deletions
+74 -6
View File
@@ -720,8 +720,14 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
const auto* decl = schema_->declaration_by_name(TokenFunc::asStringRef(next));
parse_context ps;
tokens->Next();
load(0, nullptr, ps, -1);
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl, boost::none));
// The only case we know where a defined type contains entity
// instance references is IfcPropertySetDefinitionSet. For
// that purpose we propagate the entity_instance_name to
// register inverses to the host entity (and not the defined
// type) and to be able to actually register the references in
// the 2nd pass.
load(entity_instance_name, entity, ps, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index);
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(entity_instance_name, references_to_resolve, decl, boost::none, attribute_index == -1 ? (int)attribute_index_within_data : attribute_index));
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
context.push(simple_type_instance);
simple_type_instance->file_ = this;
@@ -1428,10 +1434,40 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
if (it == byid_.end()) {
Logger::Error("Instance reference #" + std::to_string(*name) + " used by instance #" + std::to_string(ref) + " at attribute index " + std::to_string(refattr) + " not found at offset " + std::to_string(name->file_offset));
} else {
byid_[p.first.name_]->data().storage_.set(p.first.index_, it->second);
auto* storage = &byid_[p.first.name_]->data().storage_;
auto attr_index = p.first.index_;
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
if (!inst->declaration().as_entity()) {
storage = &inst->data().storage_;
attr_index = 0;
}
}
if (storage->has<Blank>(attr_index)) {
storage->set(attr_index, it->second);
} else {
Logger::Error("Duplicate definition for instance reference");
}
}
} else if (auto* inst = boost::get<IfcUtil::IfcBaseClass*>(v)) {
byid_[p.first.name_]->data().storage_.set(p.first.index_, *inst);
auto* storage = &byid_[p.first.name_]->data().storage_;
auto attr_index = p.first.index_;
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
if (!inst->declaration().as_entity()) {
storage = &inst->data().storage_;
attr_index = 0;
}
}
if (storage->has<Blank>(attr_index)) {
storage->set(attr_index, *inst);
} else {
Logger::Error("Duplicate definition for instance reference");
}
}
} else if (auto* v = boost::get<std::vector<reference_or_simple_type>>(&p.second)) {
aggregate_of_instance::ptr instances(new aggregate_of_instance);
@@ -1448,7 +1484,23 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
instances->push(*inst);
}
}
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
auto* storage = &byid_[p.first.name_]->data().storage_;
auto attr_index = p.first.index_;
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
if (!inst->declaration().as_entity()) {
storage = &inst->data().storage_;
attr_index = 0;
}
}
if (storage->has<Blank>(attr_index)) {
storage->set(attr_index, instances);
} else {
Logger::Error("Duplicate definition for instance reference");
}
} else if (auto* v = boost::get<std::vector<std::vector<reference_or_simple_type>>>(&p.second)) {
aggregate_of_aggregate_of_instance::ptr instances(new aggregate_of_aggregate_of_instance);
for (const auto& vi : *v) {
@@ -1467,7 +1519,23 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
}
instances->push(inner);
}
byid_[p.first.name_]->data().storage_.set(p.first.index_, instances);
auto* storage = &byid_[p.first.name_]->data().storage_;
auto attr_index = p.first.index_;
if (storage->has<IfcUtil::IfcBaseClass*>(attr_index)) {
auto inst = storage->get<IfcUtil::IfcBaseClass*>(attr_index);
if (!inst->declaration().as_entity()) {
storage = &inst->data().storage_;
attr_index = 0;
}
}
if (storage->has<Blank>(attr_index)) {
storage->set(attr_index, instances);
} else {
Logger::Error("Duplicate definition for instance reference");
}
}
}