Rough merge of schema runtime representation

This commit is contained in:
Thomas Krijnen
2017-12-11 13:43:06 +01:00
12 changed files with 787 additions and 95 deletions
+26 -18
View File
@@ -32,20 +32,28 @@
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 {
class IFC_PARSE_API IfcBaseClass {
protected:
IfcAbstractEntity* data_;
public:
virtual ~IfcBaseClass() {}
IfcEntityInstanceData* entity;
virtual bool is(IfcSchema::Type::Enum v) const = 0;
virtual IfcSchema::Type::Enum type() const = 0;
virtual unsigned int getArgumentCount() const = 0;
virtual IfcUtil::ArgumentType getArgumentType(unsigned int i) const = 0;
virtual IfcSchema::Type::Enum getArgumentEntity(unsigned int i) const = 0;
virtual Argument* getArgument(unsigned int i) const = 0;
virtual const char* getArgumentName(unsigned int i) const = 0;
IfcBaseClass() : data_(0) {}
IfcBaseClass(IfcAbstractEntity* d) : data_(d) {}
virtual ~IfcBaseClass() {}
const IfcAbstractEntity& data() const { return *data_; }
IfcAbstractEntity& data() { return *data_; }
void data(IfcAbstractEntity* d);
virtual const IfcParse::declaration& declaration() const = 0;
template <class T>
T* as() {
@@ -64,19 +72,19 @@ namespace IfcUtil {
class IFC_PARSE_API IfcBaseEntity : public IfcBaseClass {
public:
Argument* getArgumentByName(const std::string& name) const;
std::vector<std::string> getAttributeNames() const;
std::vector<std::string> getInverseAttributeNames() const;
unsigned id() const { return entity->id(); }
IfcBaseEntity() : IfcBaseClass() {}
IfcBaseEntity(IfcAbstractEntity* d) : IfcBaseClass(d) {}
virtual const IfcParse::entity& declaration() const = 0;
};
// TODO: Investigate whether these should be template classes instead
class IFC_PARSE_API IfcBaseType : public IfcBaseEntity {
public:
unsigned int getArgumentCount() const;
Argument* getArgument(unsigned int i) const;
const char* getArgumentName(unsigned int i) const;
IfcSchema::Type::Enum getArgumentEntity(unsigned int /*i*/) const { return IfcSchema::Type::UNDEFINED; }
IfcBaseType() : IfcBaseClass() {}
IfcBaseType(IfcAbstractEntity* d) : IfcBaseClass(d) {}
virtual const IfcParse::type_declaration& declaration() const = 0;
};
}
+2
View File
@@ -65,6 +65,7 @@ private:
typedef std::map<IfcUtil::IfcBaseClass*, IfcUtil::IfcBaseClass*> entity_entity_map_t;
bool parsing_complete_;
const schema_definition* schema_;
entity_by_id_t byid;
entities_by_type_t bytype;
@@ -170,6 +171,7 @@ public:
void register_inverse(unsigned, Token);
void register_inverse(unsigned, IfcUtil::IfcBaseClass*);
void unregister_inverse(unsigned, IfcUtil::IfcBaseClass*);
const schema_definition* schema() const { return schema_; }
};
}
+1
View File
@@ -39,6 +39,7 @@
#include "../ifcparse/IfcSpfStream.h"
#include "../ifcparse/IfcFile.h"
#include "../ifcparse/IfcSIPrefix.h"
#include "../ifcparse/IfcSchema.h"
#ifdef USE_IFC4
#include "../ifcparse/Ifc4-latebound.h"
+21
View File
@@ -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);
}
+432
View File
@@ -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
+10 -7
View File
@@ -92,12 +92,6 @@ IfcEntityList::ptr IfcEntityList::unique() {
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
Argument::operator int() const { throw IfcParse::IfcException("Argument is not an integer"); }
Argument::operator bool() const { throw IfcParse::IfcException("Argument is not a boolean"); }
@@ -196,4 +190,13 @@ std::vector<std::string> IfcUtil::IfcBaseEntity::getInverseAttributeNames() cons
Argument* IfcUtil::IfcBaseEntity::getArgumentByName(const std::string& name) const {
unsigned int i = IfcSchema::Type::GetAttributeIndex(type(), name);
return getArgument(i);
}
}
IfcUtil::IfcBaseClass::~IfcBaseClass() {
delete data_;
}
void IfcUtil::IfcBaseClass::data(IfcAbstractEntity* d) {
delete data_;
data_ = d;
}