diff --git a/include/matador/object/foreign_node_completer.hpp b/include/matador/object/foreign_node_completer.hpp index 6f8c37e..f323de6 100644 --- a/include/matador/object/foreign_node_completer.hpp +++ b/include/matador/object/foreign_node_completer.hpp @@ -194,30 +194,31 @@ void foreign_node_completer::on_has_many(const char * /*id*/, template template -void foreign_node_completer::on_has_many_to_many(const char *id, CollectionType & /*collection*/, - const char *join_column, - const char *inverse_join_column, +void foreign_node_completer::on_has_many_to_many(const char * /*id*/, + CollectionType & /*collection*/, + const char * /*join_column*/, + const char * /*inverse_join_column*/, const utils::foreign_attributes & /*attr*/) { - if (!repo_.expecting_relation_node(id)) { - repo_.expect_relation_node(id, typeid(typename CollectionType::value_type::value_type)); - } else { - attach_relation_node(id, join_column, inverse_join_column); - repo_.remove_expected_relation_node(id); - } + // if (!repo_.expecting_relation_node(id)) { + // repo_.expect_relation_node(id, typeid(typename CollectionType::value_type::value_type)); + // } else { + // attach_relation_node(id, join_column, inverse_join_column); + // repo_.remove_expected_relation_node(id); + // } } template template -void foreign_node_completer::on_has_many_to_many(const char *id, +void foreign_node_completer::on_has_many_to_many(const char * /*id*/, CollectionType & /*collection*/, const utils::foreign_attributes & /*attr*/) { - if (!repo_.expecting_relation_node(id)) { - repo_.expect_relation_node(id, typeid(typename CollectionType::value_type::value_type)); - } else { - const auto join_columns = join_columns_collector_.collect(); - attach_relation_node(id, join_columns.join_column, join_columns.inverse_join_column); - repo_.remove_expected_relation_node(id); - } + // if (!repo_.expecting_relation_node(id)) { + // repo_.expect_relation_node(id, typeid(typename CollectionType::value_type::value_type)); + // } else { + // const auto join_columns = join_columns_collector_.collect(); + // attach_relation_node(id, join_columns.join_column, join_columns.inverse_join_column); + // repo_.remove_expected_relation_node(id); + // } } template diff --git a/include/matador/object/relation_completer.hpp b/include/matador/object/relation_completer.hpp index 71f88fa..e6ff927 100644 --- a/include/matador/object/relation_completer.hpp +++ b/include/matador/object/relation_completer.hpp @@ -2,6 +2,7 @@ #define RELATION_COMPLETER_HPP #include "matador/object/internal/shadow_repository.hpp" +#include "matador/object/foreign_node_completer.hpp" #include "matador/object/many_to_many_relation.hpp" #include "matador/object/join_columns_collector.hpp" #include "matador/object/object_ptr.hpp" @@ -143,6 +144,9 @@ private: nodes_.pop(); } + template + void attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column); + static void register_relation_endpoints(const endpoint_ptr &endpoint, const endpoint_ptr &other_endpoint); static void link_relation_endpoints(const endpoint_ptr &endpoint, @@ -244,47 +248,12 @@ void relation_completer::on_has_many_to_many(const char *id, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) { - using relation_value_type = many_to_many_relation; - using value_type = typename CollectionType::value_type::value_type; - - // Check if the object_ptr type is already inserted in the schema (by id) - auto result = schema_.find_node(typeid(value_type)); - if (!result) { - // Todo: throw internal error or attach node - return; + if (!schema_.expecting_relation_node(id)) { + schema_.expect_relation_node(id, typeid(typename CollectionType::value_type::value_type)); + } else { + attach_relation_node(id, join_column, inverse_join_column); + schema_.remove_expected_relation_node(id); } - - const auto foreign_node = result.value(); - result = schema_.find_node(id); - if (result) { - return; - } - // Relation not found. - auto creator = [join_column, inverse_join_column] { - return std::make_unique(join_column, inverse_join_column); - }; - - auto node = repository_node::make_node(schema_.repo(), id, std::move(creator)); - result = schema_.attach_node(node); - if (!result) { - // Todo: throw internal error - return; - } - - const auto local_endpoint = std::make_shared(id, relation_type::HasMany, node); - const auto join_endpoint = std::make_shared(join_column, relation_type::BelongsTo, nodes_.top()); - const auto inverse_join_endpoint = std::make_shared(inverse_join_column, relation_type::BelongsTo, foreign_node); - const auto foreign_endpoint = std::make_shared(id, relation_type::HasMany, node); - // register relation endpoint in local node - nodes_.top()->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), local_endpoint); - // register relation endpoint in foreign node - foreign_node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); - // register endpoints in relation node - node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint); - node->info_->register_relation_endpoint(typeid(typename CollectionType::value_type::value_type), inverse_join_endpoint); - // link endpoints - link_relation_endpoints(local_endpoint, join_endpoint); - link_relation_endpoints(foreign_endpoint, inverse_join_endpoint); } template @@ -372,6 +341,54 @@ void relation_completer::on_belongs_to(const char *id, } } +template +template +void relation_completer::attach_relation_node(const std::string &name, const std::string &join_column, const std::string &inverse_join_column) { + using relation_value_type = many_to_many_relation; + using value_type = NodeType; + + // Check if the object_ptr type is already inserted in the schema (by id) + auto result = schema_.find_node(typeid(value_type)); + if (!result) { + // Todo: throw internal error or attach node + return; + } + + const auto foreign_node = result.value(); + result = schema_.find_node(name); + if (result) { + return; + } + // Relation does not exist. Create it. + auto creator = [join_column, inverse_join_column] { + return std::make_unique(join_column, inverse_join_column); + }; + + auto node = repository_node::make_node(schema_.repo(), name, std::move(creator)); + result = schema_.attach_node(node); + if (!result) { + // Todo: throw internal error + return; + } + + foreign_node_completer::template complete(result.value()); + + const auto local_endpoint = std::make_shared(name, relation_type::HasMany, node); + const auto join_endpoint = std::make_shared(join_column, relation_type::BelongsTo, nodes_.top()); + const auto inverse_join_endpoint = std::make_shared(inverse_join_column, relation_type::BelongsTo, foreign_node); + const auto foreign_endpoint = std::make_shared(name, relation_type::HasMany, node); + // register relation endpoint in local node + nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); + // register relation endpoint in foreign node + foreign_node->info_->register_relation_endpoint(nodes_.top()->type_index(), foreign_endpoint); + // register endpoints in relation node + node->info_->register_relation_endpoint(nodes_.top()->type_index(), join_endpoint); + node->info_->register_relation_endpoint(typeid(value_type), inverse_join_endpoint); + // link endpoints + link_relation_endpoints(local_endpoint, join_endpoint); + link_relation_endpoints(foreign_endpoint, inverse_join_endpoint); +} + template void relation_completer::register_relation_endpoints(const endpoint_ptr &endpoint, const endpoint_ptr &other_endpoint) { diff --git a/include/matador/object/repository.hpp b/include/matador/object/repository.hpp index 3236f45..6bdbc33 100644 --- a/include/matador/object/repository.hpp +++ b/include/matador/object/repository.hpp @@ -46,7 +46,7 @@ public: return utils::failure(result.err()); } foreign_node_completer::template complete(node); - // relation_completer::complete(node); + relation_completer::complete(node); } else if (!has_node(name)) { it->second->update_name(name); nodes_by_name_[name] = it->second;