From 504e11149110e0200d9d5ab76946629b0534b07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sascha=20K=C3=BChl?= Date: Sun, 9 Feb 2025 20:49:00 +0100 Subject: [PATCH] reference column progress --- .../matador/object/attribute_definition.hpp | 27 ++-- .../object/attribute_definition_generator.hpp | 4 +- include/matador/object/basic_object_info.hpp | 8 +- include/matador/object/object_info.hpp | 15 +- include/matador/object/schema.hpp | 101 ++++++++++++- include/matador/object/schema_node.hpp | 17 +-- source/core/object/attribute_definition.cpp | 139 +++++++----------- .../object/attribute_definition_generator.cpp | 2 +- source/core/object/basic_object_info.cpp | 20 ++- source/core/object/schema.cpp | 47 +++--- source/core/object/schema_node.cpp | 77 ++++++---- 11 files changed, 269 insertions(+), 188 deletions(-) diff --git a/include/matador/object/attribute_definition.hpp b/include/matador/object/attribute_definition.hpp index 04352e5..d19747a 100644 --- a/include/matador/object/attribute_definition.hpp +++ b/include/matador/object/attribute_definition.hpp @@ -1,6 +1,8 @@ #ifndef QUERY_COLUMN_DEFINITION_HPP #define QUERY_COLUMN_DEFINITION_HPP +#include + #include "matador/utils/basic_type_converter.hpp" #include "matador/utils/basic_types.hpp" #include "matador/utils/default_type_traits.hpp" @@ -43,11 +45,11 @@ public: attribute_definition(std::string name, utils::basic_type type, const utils::field_attributes&, null_option null_opt, size_t index = 0); template - attribute_definition(std::string name, std::string ref_table, std::string ref_column, const utils::field_attributes& attr, null_option null_opt) - : attribute_definition(std::move(name), utils::data_type_traits::type(attr.size()), ref_table, ref_column, attr, null_opt) + attribute_definition(std::string name, const std::shared_ptr &ref_column, const utils::field_attributes& attr, null_option null_opt) + : attribute_definition(std::move(name), utils::data_type_traits::type(attr.size()), ref_column, attr, null_opt) {} - attribute_definition(std::string name, utils::basic_type type, size_t index, std::string ref_table, std::string ref_column, const utils::field_attributes& attr, null_option null_opt); + attribute_definition(std::string name, utils::basic_type type, size_t index, const std::shared_ptr &ref_column, const utils::field_attributes& attr, null_option null_opt); [[nodiscard]] const std::string& name() const; [[nodiscard]] std::string full_name() const; @@ -56,8 +58,7 @@ public: [[nodiscard]] const utils::field_attributes& attributes() const; [[nodiscard]] bool is_nullable() const; [[nodiscard]] utils::basic_type type() const; - [[nodiscard]] const std::string& ref_table() const; - [[nodiscard]] const std::string& ref_column() const; + [[nodiscard]] std::shared_ptr reference_column() const; [[nodiscard]] bool is_foreign_reference() const; [[nodiscard]] bool is_integer() const; @@ -124,8 +125,9 @@ private: utils::field_attributes attributes_; null_option null_option_{null_option::NOT_NULL}; utils::value value_; - std::string ref_table_; - std::string ref_column_; + std::shared_ptr reference_column_; + // std::string ref_table_; + // std::string ref_column_; }; /** @@ -156,19 +158,20 @@ template <> attribute_definition make_pk_column(const std::string &name, size_t size); template < typename Type > -attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column) +attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { - return {name, utils::data_type_traits::type(size), ref_table, ref_column, { size, utils::constraints::FOREIGN_KEY }}; + return {name, utils::data_type_traits::type(size), ref_column, { size, utils::constraints::FOREIGN_KEY }}; } template < typename Type > -[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::string &ref_table, const std::string &ref_column) +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, const std::shared_ptr &ref_column) { - return {name, utils::data_type_traits::type(0), 0, ref_table, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; + return {name, utils::data_type_traits::type(0), 0, ref_column, { 0, utils::constraints::FOREIGN_KEY }, null_option::NOT_NULL}; } template <> -attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, const std::string &ref_column); +attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column); } + #endif //QUERY_COLUMN_DEFINITION_HPP diff --git a/include/matador/object/attribute_definition_generator.hpp b/include/matador/object/attribute_definition_generator.hpp index 830dd93..6865b9b 100644 --- a/include/matador/object/attribute_definition_generator.hpp +++ b/include/matador/object/attribute_definition_generator.hpp @@ -83,7 +83,7 @@ public: template void on_belongs_to(const char *id, Pointer &x, const utils::foreign_attributes &/*attr*/) { - const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + const auto ref_column = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); } template @@ -100,7 +100,7 @@ public: void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} private: - std::pair determine_foreign_ref(const std::type_index &ti); + std::shared_ptr determine_foreign_ref(const std::type_index &ti); private: size_t index_ = 0; diff --git a/include/matador/object/basic_object_info.hpp b/include/matador/object/basic_object_info.hpp index 8c4f8ad..5d1178c 100644 --- a/include/matador/object/basic_object_info.hpp +++ b/include/matador/object/basic_object_info.hpp @@ -17,14 +17,16 @@ public: [[nodiscard]] std::type_index type_index() const; [[nodiscard]] std::string name() const; [[nodiscard]] const object_definition& definition() const; + [[nodiscard]] std::shared_ptr reference_column() const; protected: - basic_object_info(schema_node &node, std::type_index type_index, object_definition &&definition); + basic_object_info(schema_node &node, std::type_index type_index, object_definition &&definition, std::shared_ptr &&reference_column); protected: - schema_node &node_; /**< prototype node of the represented object type */ - std::type_index type_index_; /**< type index of the represented object type */ + schema_node &node_; /**< prototype node of the represented object type */ + std::type_index type_index_; /**< type index of the represented object type */ object_definition definition_; + std::shared_ptr reference_column_; }; using basic_object_info_ref = std::reference_wrapper; diff --git a/include/matador/object/object_info.hpp b/include/matador/object/object_info.hpp index f8aeff0..6befa7f 100644 --- a/include/matador/object/object_info.hpp +++ b/include/matador/object/object_info.hpp @@ -5,30 +5,31 @@ #include "matador/object/object_definition.hpp" namespace matador::object { - class schema_node; template class object_info final : public basic_object_info { public: - explicit object_info(schema_node &node, object_definition &&definition) - : basic_object_info(node, typeid(Type), std::move(definition)) {} + explicit object_info(schema_node &node, object_definition &&definition, + std::shared_ptr &&ref_column) + : basic_object_info(node, typeid(Type), std::move(definition), std::move(ref_column)) { + } - const Type &prototype() const { return prototype_; } + const Type &prototype() const { return prototype_; } private: - Type prototype_; + Type prototype_; }; template using object_info_ref = std::reference_wrapper>; namespace detail { -struct null_type {}; +struct null_type { +}; } using null_info = object_info; - } #endif //OBJECT_INFO_HPP diff --git a/include/matador/object/schema.hpp b/include/matador/object/schema.hpp index e64aeb3..e8673fa 100644 --- a/include/matador/object/schema.hpp +++ b/include/matador/object/schema.hpp @@ -9,11 +9,69 @@ #include "matador/utils/error.hpp" #include +#include #include -#include +#include namespace matador::object { +utils::error make_error(error_code ec, const std::string& msg); + +class schema; + +template +class type_analyzer final { +public: + using value_type = Type; + + static void analyze(schema &scm) { + type_analyzer analyzer(scm); + + Type obj; + const auto ti = std::type_index(typeid(Type)); + analyzer.known_types_.emplace(ti); + access::process(analyzer, obj); + analyzer.known_types_.erase(ti); + } + + template < class PrimaryKeyType > + void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, std::enable_if_t && !std::is_same_v>* = nullptr) {} + void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t /*size*/) {} + void on_revision(const char * /*id*/, uint64_t &/*rev*/) {} + + template + void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + + template + void on_attribute(const char * /*id*/, std::optional &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + + template + void on_belongs_to(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) { + // const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + // columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); + } + + template + void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/); + + template + void on_has_many(const char * /*id*/, CollectionType &, const char *, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_many_to_many(const char * /*id*/, CollectionType &/*col*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} + template + void on_has_many_to_many(const char * /*id*/, ContainerType &/*col*/, const utils::foreign_attributes &/*attr*/) {} + +private: + explicit type_analyzer(schema& schema) + : schema_(schema) {}; + + +private: + schema &schema_; + std::unordered_set known_types_; +}; + + class schema { public: typedef const_schema_node_iterator const_iterator; /**< Shortcut for the list const iterator. */ @@ -24,7 +82,14 @@ public: explicit schema( const std::string& name = ""); template - [[nodiscard]] utils::result attach(const std::string name, const std::string &parent = "") { + [[nodiscard]] utils::result attach(const std::string& name, const std::string &parent = "") { + if (has_node(name)) { + return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + name + "' already exists")); + } + + // analyze node (collect unknown types by type index) + type_analyzer::analyze(*this); + auto node = schema_node::make_node(*this, name); auto result = attach_node(node, parent); @@ -37,14 +102,13 @@ public: template [[nodiscard]] utils::result attach(const std::string name) { - auto node = schema_node::make_node(*this, name); - - auto result = attach_node(node, std::type_index(typeid(ParentType))); + const auto ti = std::type_index(typeid(ParentType)); + auto result = find_node(ti); if (!result) { - return utils::failure(result.err()); + return utils::failure(make_error(error_code::NodeNotFound, "Parent node '" + std::string(ti.name()) + "' not found")); } - return utils::ok(); + return attach(name, (*result)->name()); } /** @@ -103,7 +167,7 @@ public: return utils::ok(basic_object_info_ref{result.value()->basic_info()}); } - [[nodiscard]] utils::result, utils::error> reference(const std::type_index &type_index) const; + [[nodiscard]] utils::result, utils::error> reference(const std::type_index &type_index) const; private: using node_ptr = std::shared_ptr; @@ -117,11 +181,16 @@ private: [[nodiscard]] utils::result, utils::error> find_node(const std::string &name) const; [[nodiscard]] utils::result, utils::error> find_node(const std::type_index &type_index) const; + [[nodiscard]] bool has_node(const std::string &name) const; + [[nodiscard]] bool has_node(const std::type_index& index) const; [[nodiscard]] bool has_node(const std::type_index& index, const std::string &name) const; static void push_back_child(const node_ptr &parent, const node_ptr &child); private: + template + friend class type_analyzer; + std::string name_; std::shared_ptr root_; @@ -129,6 +198,22 @@ private: t_type_index_node_map type_index_node_map_; }; +template +template +void type_analyzer::on_has_one(const char *, ForeignPointerType &, const utils::foreign_attributes &) { + auto ti = std::type_index(typeid(typename ForeignPointerType::value_type)); + if (schema_.has_node(ti)) { + return; + } + + auto info = std::make_unique>(); + + known_types_.insert(ti); + + // const auto [ref_table, ref_column] = determine_foreign_ref(std::type_index(typeid(typename Pointer::value_type))); + // columns_.push_back(fk_column_generator_.generate(id, *x, ref_table, ref_column)); +} + } #endif //SCHEMA_HPP diff --git a/include/matador/object/schema_node.hpp b/include/matador/object/schema_node.hpp index 870ccc5..48a286b 100644 --- a/include/matador/object/schema_node.hpp +++ b/include/matador/object/schema_node.hpp @@ -15,10 +15,7 @@ class schema_node final { public: using node_ptr = std::shared_ptr; - template < typename Type > - static std::shared_ptr make_node(schema& tree, const std::string& name) { - return std::shared_ptr(new schema_node(tree, name, static_cast(nullptr))); - } + static std::shared_ptr make_node(schema& tree, const std::string& name, std::unique_ptr &&info); schema_node(const schema_node& other) = delete; schema_node(schema_node&& other) = default; @@ -41,17 +38,7 @@ public: private: explicit schema_node(schema& tree); - template < typename Type > - schema_node(schema& tree, std::string name, Type *obj) - : schema_(tree) - , info_(std::make_unique>(*this, object_definition(attribute_definition_generator::generate(schema_)))) - , first_child_(std::shared_ptr(new schema_node(tree))) - , last_child_(std::shared_ptr(new schema_node(tree))) - , name_(std::move(name)) { - first_child_->next_sibling_ = last_child_; - last_child_->previous_sibling_ = first_child_; - } - + schema_node(schema& tree, std::string name, std::unique_ptr &&info); private: friend class schema; diff --git a/source/core/object/attribute_definition.cpp b/source/core/object/attribute_definition.cpp index b081819..3c7e941 100644 --- a/source/core/object/attribute_definition.cpp +++ b/source/core/object/attribute_definition.cpp @@ -4,173 +4,146 @@ #include namespace matador::object { - attribute_definition::attribute_definition(const char *name) : name_(name) - , attributes_(utils::null_attributes) -{} + , attributes_(utils::null_attributes) { +} attribute_definition::attribute_definition(std::string name) : name_(std::move(name)) - , attributes_(utils::null_attributes) -{} + , attributes_(utils::null_attributes) { +} -attribute_definition::attribute_definition(std::string name, const utils::basic_type type, const utils::field_attributes& attr, const null_option null_opt, const size_t index) +attribute_definition::attribute_definition(std::string name, const utils::basic_type type, + const utils::field_attributes &attr, const null_option null_opt, + const size_t index) : name_(std::move(name)) - , index_(index) - , attributes_(attr) - , null_option_(null_opt) - , value_(type, attr.size()) -{} + , index_(index) + , attributes_(attr) + , null_option_(null_opt) + , value_(type, attr.size()) { +} attribute_definition::attribute_definition(std::string name, - const utils::basic_type type, - const size_t index, - std::string ref_table, - std::string ref_column, - const utils::field_attributes& attr, const null_option null_opt) + const utils::basic_type type, + const size_t index, + const std::shared_ptr &ref_column, + const utils::field_attributes &attr, const null_option null_opt) : name_(std::move(name)) - , index_(index) - , attributes_(attr) - , null_option_(null_opt) - , value_(type, attr.size()) - , ref_table_(std::move(ref_table)) - , ref_column_(std::move(ref_column)) -{} + , index_(index) + , attributes_(attr) + , null_option_(null_opt) + , value_(type, attr.size()) + , reference_column_(ref_column) { +} -const std::string &attribute_definition::name() const -{ +const std::string &attribute_definition::name() const { return name_; } -std::string attribute_definition::full_name() const -{ +std::string attribute_definition::full_name() const { return table_ + "." + name_; } -std::string attribute_definition::table_name() const -{ +std::string attribute_definition::table_name() const { return table_; } -int attribute_definition::index() const -{ +int attribute_definition::index() const { return index_; } -const utils::field_attributes &attribute_definition::attributes() const -{ +const utils::field_attributes &attribute_definition::attributes() const { return attributes_; } -bool attribute_definition::is_nullable() const -{ +bool attribute_definition::is_nullable() const { return null_option_ == null_option::NULLABLE; } -utils::basic_type attribute_definition::type() const -{ +utils::basic_type attribute_definition::type() const { return value_.type(); } -const std::string &attribute_definition::ref_table() const -{ - return ref_table_; +std::shared_ptr attribute_definition::reference_column() const { + return reference_column_; } -const std::string &attribute_definition::ref_column() const -{ - return ref_column_; +bool attribute_definition::is_foreign_reference() const { + return reference_column_ != nullptr; } -bool attribute_definition::is_foreign_reference() const -{ - return !ref_column_.empty() && !ref_table_.empty(); -} - -bool attribute_definition::is_integer() const -{ +bool attribute_definition::is_integer() const { return value_.is_integer(); } -bool attribute_definition::is_floating_point() const -{ +bool attribute_definition::is_floating_point() const { return value_.is_floating_point(); } -bool attribute_definition::is_bool() const -{ +bool attribute_definition::is_bool() const { return value_.is_bool(); } -bool attribute_definition::is_string() const -{ +bool attribute_definition::is_string() const { return value_.is_string(); } -bool attribute_definition::is_varchar() const -{ +bool attribute_definition::is_varchar() const { return value_.is_varchar(); } -bool attribute_definition::is_date() const -{ +bool attribute_definition::is_date() const { return value_.is_date(); } -bool attribute_definition::is_time() const -{ +bool attribute_definition::is_time() const { return value_.is_time(); } -bool attribute_definition::is_blob() const -{ +bool attribute_definition::is_blob() const { return value_.is_blob(); } -bool attribute_definition::is_null() const -{ +bool attribute_definition::is_null() const { return value_.is_null(); } -void attribute_definition::type(utils::basic_type /*type*/) -{ +void attribute_definition::type(utils::basic_type /*type*/) { // type_ = type; -// utils::initialize_by_utils::basic_type(type, value_); + // utils::initialize_by_utils::basic_type(type, value_); } -std::string attribute_definition::str() const -{ +std::string attribute_definition::str() const { return value_.str(); } -std::ostream& operator<<(std::ostream &out, const attribute_definition &col) -{ +std::ostream &operator<<(std::ostream &out, const attribute_definition &col) { out << col.str(); return out; } -attribute_definition make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr, null_option null_opt) -{ +attribute_definition make_column(const std::string &name, utils::basic_type type, utils::field_attributes attr, + null_option null_opt) { return {name, type, attr, null_opt}; } template<> -attribute_definition make_column(const std::string &name, utils::field_attributes attr, null_option null_opt) -{ +attribute_definition make_column(const std::string &name, utils::field_attributes attr, + null_option null_opt) { return make_column(name, utils::data_type_traits::type(attr.size()), attr, null_opt); } template<> -attribute_definition make_pk_column(const std::string &name, size_t size) -{ +attribute_definition make_pk_column(const std::string &name, size_t size) { return make_column(name, {size, utils::constraints::FOREIGN_KEY}); } template<> -[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::string &ref_table, - const std::string &ref_column) -{ - return {name, utils::data_type_traits::type(size), 0, ref_table, ref_column, {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL}; +[[maybe_unused]] attribute_definition make_fk_column(const std::string &name, size_t size, const std::shared_ptr &ref_column) { + return { + name, utils::data_type_traits::type(size), 0, ref_column, + {size, utils::constraints::FOREIGN_KEY}, null_option::NOT_NULL + }; } } diff --git a/source/core/object/attribute_definition_generator.cpp b/source/core/object/attribute_definition_generator.cpp index 9f040a7..d700816 100644 --- a/source/core/object/attribute_definition_generator.cpp +++ b/source/core/object/attribute_definition_generator.cpp @@ -18,7 +18,7 @@ void attribute_definition_generator::on_revision(const char *id, uint64_t &rev) on_attribute(id, rev); } -std::pair attribute_definition_generator::determine_foreign_ref(const std::type_index &ti) +std::shared_ptr attribute_definition_generator::determine_foreign_ref(const std::type_index &ti) { return repo_.reference(ti).value(); } diff --git a/source/core/object/basic_object_info.cpp b/source/core/object/basic_object_info.cpp index f56f10f..71a2b7d 100644 --- a/source/core/object/basic_object_info.cpp +++ b/source/core/object/basic_object_info.cpp @@ -5,22 +5,30 @@ #include namespace matador::object { - -basic_object_info::basic_object_info(schema_node &node, const std::type_index type_index, object_definition &&definition) +basic_object_info::basic_object_info(schema_node &node, + const std::type_index type_index, + object_definition &&definition, + std::shared_ptr &&reference_column) : node_(node) , type_index_(type_index) -, definition_(std::move(definition)) {} +, definition_(std::move(definition)) +, reference_column_(std::move(reference_column)) { +} std::type_index basic_object_info::type_index() const { - return type_index_; + return type_index_; } std::string basic_object_info::name() const { - return node_.name(); + return node_.name(); } -const object_definition& basic_object_info::definition() const { +const object_definition &basic_object_info::definition() const { return definition_; } +std::shared_ptr basic_object_info::reference_column() const { + return reference_column_; +} + } // namespace matador::object diff --git a/source/core/object/schema.cpp b/source/core/object/schema.cpp index 12a6ef6..f43f54c 100644 --- a/source/core/object/schema.cpp +++ b/source/core/object/schema.cpp @@ -1,14 +1,13 @@ #include "matador/object/schema.hpp" namespace matador::object { - -utils::error make_error(const error_code ec, const std::string& msg) { +utils::error make_error(const error_code ec, const std::string &msg) { return utils::error(ec, msg); } -schema::schema( const std::string& name) -: name_(name) -, root_(std::shared_ptr(new schema_node(*this))) { +schema::schema(const std::string &name) + : name_(name) + , root_(std::shared_ptr(new schema_node(*this))) { root_->first_child_ = std::shared_ptr(new schema_node(*this)); root_->last_child_ = std::shared_ptr(new schema_node(*this)); root_->first_child_->next_sibling_ = root_->last_child_; @@ -35,16 +34,18 @@ std::string schema::name() const { return name_; } -utils::result, utils::error> schema::reference( const std::type_index& type_index ) const { - const auto result = find_node(type_index); - if (!result) { - return utils::failure(result.err()); - } - if (!result->get()->basic_info().definition().has_primary_key()) { - return utils::failure(make_error( error_code::Failure, "Primary key not found" )); - } +utils::result, utils::error> schema::reference(const std::type_index &type_index) const { + const auto result = find_node(type_index); + if (!result) { + return utils::failure(result.err()); + } - return utils::ok(std::make_pair(result->get()->name(), result->get()->basic_info().definition().primary_key()->name())); + const auto &node = *result; + if (!node->basic_info().definition().has_primary_key()) { + return utils::failure(make_error(error_code::Failure, "Primary key not found")); + } + + return utils::ok(std::make_pair(node->name(), node->basic_info().definition().primary_key()->name())); } utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, @@ -72,8 +73,8 @@ utils::result, utils::error> schema::attach_node(co return utils::ok(node); } -utils::result, utils::error> schema::attach_node( const std::shared_ptr& node, - const std::type_index& type_index ) { +utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, + const std::type_index &type_index) { if (has_node(node->type_index(), node->name())) { return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists.")); } @@ -100,10 +101,11 @@ utils::result, utils::error> schema::find_node(cons return utils::ok(i->second); } -utils::result, utils::error> schema::find_node( const std::type_index& type_index ) const { +utils::result, utils::error> schema::find_node(const std::type_index &type_index) const { const auto i = type_index_node_map_.find(type_index); if (i == type_index_node_map_.end()) { - return utils::failure(make_error(error_code::NodeNotFound, "Couldn't find node by type '" + std::string(type_index.name()) + "'")); + return utils::failure(make_error(error_code::NodeNotFound, + "Couldn't find node by type '" + std::string(type_index.name()) + "'")); } return utils::ok(i->second); } @@ -124,8 +126,15 @@ void schema::push_back_child(const node_ptr &parent, const node_ptr &child) { // child->depth = depth + 1; } +bool schema::has_node(const std::string &name) const { + return node_map_.count(name) > 0; +} + +bool schema::has_node(const std::type_index &index) const { + return type_index_node_map_.count(index) > 0; +} + bool schema::has_node(const std::type_index &index, const std::string &name) const { return node_map_.count(name) > 0 || type_index_node_map_.count(index) > 0; } - } // namespace matador::object diff --git a/source/core/object/schema_node.cpp b/source/core/object/schema_node.cpp index afee774..1c38fcc 100644 --- a/source/core/object/schema_node.cpp +++ b/source/core/object/schema_node.cpp @@ -3,11 +3,25 @@ #include "matador/object/schema_node.hpp" namespace matador::object { - -schema_node::schema_node(object::schema &tree) +schema_node::schema_node(schema &tree) : schema_(tree) -, info_(std::make_unique(*this, object_definition{})) -{} +, info_(std::make_unique(*this, object_definition{})) { +} + +schema_node::schema_node(schema &tree, std::string name, std::unique_ptr &&info) +: schema_(tree) +, info_(std::move(info)) +// , info_(std::make_unique>(*this, object_definition(attribute_definition_generator::generate(schema_)))) +, first_child_(std::shared_ptr(new schema_node(tree))) +, last_child_(std::shared_ptr(new schema_node(tree))) +, name_(std::move(name)) { + first_child_->next_sibling_ = last_child_; + last_child_->previous_sibling_ = first_child_; +} + +std::shared_ptr schema_node::make_node(schema &tree, const std::string &name, std::unique_ptr &&info) { + return std::shared_ptr(new schema_node(tree, name, std::move(info))); +} std::string schema_node::name() const { return name_; @@ -17,41 +31,40 @@ std::type_index schema_node::type_index() const { return info_->type_index(); } -const basic_object_info& schema_node::basic_info() const { +const basic_object_info &schema_node::basic_info() const { return *info_; } schema_node::node_ptr schema_node::next() const { - // if we have a child, child is the next iterator to return - // (if we don't do iterate over the siblings) - if (first_child_ && first_child_->next_sibling_ != last_child_) { - return first_child_->next_sibling_; - } - // if there is no child, we check for sibling - // if there is a sibling, this is our next iterator to return - // if not, we go back to the parent - auto *node = this; - while (node->parent_ && node->next_sibling_ == node->parent_->last_child_) { - node = node->parent_.get(); - } - return node->parent_ ? node->next_sibling_ : node->last_child_; + // if we have a child, child is the next iterator to return + // (if we don't do iterate over the siblings) + if (first_child_ && first_child_->next_sibling_ != last_child_) { + return first_child_->next_sibling_; + } + // if there is no child, we check for sibling + // if there is a sibling, this is our next iterator to return + // if not, we go back to the parent + auto *node = this; + while (node->parent_ && node->next_sibling_ == node->parent_->last_child_) { + node = node->parent_.get(); + } + return node->parent_ ? node->next_sibling_ : node->last_child_; } schema_node::node_ptr schema_node::prev() const { - // if node has a previous sibling, we set it - // as our next iterator. then we check if there - // are last children. if so, we set the last-last - // child as our iterator - if (previous_sibling_ && previous_sibling_->previous_sibling_) { - auto node = previous_sibling_; - while (node->last_child_ && node->first_child_->next_sibling_ != node->last_child_) { - node = node->last_child_->previous_sibling_; - } - return node; + // if node has a previous sibling, we set it + // as our next iterator. then we check if there + // are last children. if so, we set the last-last + // child as our iterator + if (previous_sibling_ && previous_sibling_->previous_sibling_) { + auto node = previous_sibling_; + while (node->last_child_ && node->first_child_->next_sibling_ != node->last_child_) { + node = node->last_child_->previous_sibling_; } - // if there is no previous sibling, our next iterator - // is the parent of the node - return parent_->parent_ ? parent_ : parent_->first_child_->next_sibling_; + return node; + } + // if there is no previous sibling, our next iterator + // is the parent of the node + return parent_->parent_ ? parent_ : parent_->first_child_->next_sibling_; } - }