diff --git a/include/matador/object/foreign_node_completer.hpp b/include/matador/object/foreign_node_completer.hpp index f771b69..01e8ff2 100644 --- a/include/matador/object/foreign_node_completer.hpp +++ b/include/matador/object/foreign_node_completer.hpp @@ -2,6 +2,7 @@ #define FOREIGN_NODE_COMPLETER_HPP #include "matador/object/internal/shadow_repository.hpp" +#include "matador/object/internal/observer_list_copy_creator.hpp" #include "matador/object/many_to_many_relation.hpp" #include "matador/object/repository_node.hpp" #include "matador/object/join_columns_collector.hpp" @@ -35,9 +36,9 @@ private: using node_ptr = std::shared_ptr; public: - static void complete(const std::shared_ptr &node, Observers... observers) { + static void complete(const std::shared_ptr &node, const std::vector>> &observers) { internal::shadow_repository shadow(node->repo_); - foreign_node_completer completer(shadow, observers...); + foreign_node_completer completer(shadow, observers); completer.complete_node(node); } @@ -77,11 +78,10 @@ public: static void on_has_many_to_many(const char * /*id*/, CollectionType &/*collection*/, const utils::foreign_attributes &/*attr*/) {} private: - explicit foreign_node_completer(internal::shadow_repository &shadow, Observers... observers) + explicit foreign_node_completer(internal::shadow_repository &shadow, const std::vector>> &observers) : repo_(shadow) - , log_(logger::create_logger("node_completer")) { - // observers_.emplace_back(observers...); - } + , log_(logger::create_logger("node_completer")) + , observers_(observers) {} void complete_node(const std::shared_ptr &node) { nodes_.push(node); @@ -91,75 +91,22 @@ private: nodes_.pop(); } - template - void attach_node(const std::string &name) { - if (repo_.contains(typeid(Type))) { - return; - } - const auto node = repository_node::make_node(repo_.repo(), name); - if (auto result = repo_.attach_node(node)) { - foreign_node_completer::complete(result.value()); - } - } - template void attach_node() { if (repo_.contains(typeid(Type))) { return; } - const auto node = repository_node::make_node(repo_.repo(), "", []{ return std::make_unique(); }); - if (auto result = repo_.attach_node(node)) { - foreign_node_completer::complete(result.value()); - } - } + auto observers = internal::observer_list_copy_creator::copy_create(observers_); - template - void 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 = Type; - - // Check if the object_ptr type is already inserted in the schema (by id) - auto result = repo_.find_node(typeid(value_type)); - if (!result) { - // Todo: throw internal error or attach node + if (repo_.is_node_announced(typeid(Type))) { return; } - - const auto foreign_node = result.value(); - result = repo_.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(repo_.repo(), name, std::move(creator)); - result = repo_.attach_node(node); - if (!result) { - // Todo: throw internal error - return; - } - - foreign_node_completer::complete(result.value()); - - // auto& node = 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); + const auto node = repository_node::make_node(repo_.repo(), "", []{ return std::make_unique(); }, std::move(observers)); + repo_.push_announce_node(typeid(Type), node); + // if (auto result = repo_.attach_node(node)) { + // foreign_node_completer::complete(result.value(), {}); + // } } private: @@ -178,7 +125,7 @@ private: internal::shadow_repository &repo_; logger::logger log_; join_columns_collector join_columns_collector_{}; - // const std::vector...> observers_; + const std::vector>>& observers_; }; @@ -190,7 +137,7 @@ void foreign_node_completer::on_belongs_to(const char * template typename ...Observers> template -void foreign_node_completer::on_has_one(const char *, ForeignPointerType &, const utils::foreign_attributes &) { +void foreign_node_completer::on_has_one(const char * /*id*/, ForeignPointerType &, const utils::foreign_attributes &) { attach_node(); } diff --git a/include/matador/object/internal/observer_list_copy_creator.hpp b/include/matador/object/internal/observer_list_copy_creator.hpp new file mode 100644 index 0000000..1eaba10 --- /dev/null +++ b/include/matador/object/internal/observer_list_copy_creator.hpp @@ -0,0 +1,57 @@ +#ifndef MATADOR_OBSERVER_LIST_COPY_CREATOR_HPP +#define MATADOR_OBSERVER_LIST_COPY_CREATOR_HPP + +#include "matador/object/observer.hpp" + +#include +#include + +namespace matador::object::internal { +template class... ObserverType> +class observer_list_copy_creator +{ +public: + using source_observer_vector = std::vector>>; + using observer_vector = std::vector>>; + using iterator = typename observer_vector::iterator; + + static observer_vector copy_create(const source_observer_vector &source_observers) { + observer_list_copy_creator creator(source_observers); + + return std::move(creator.observers_); + } + +private: + explicit observer_list_copy_creator(const source_observer_vector &source_observers) + : source_observers_(source_observers) { + if constexpr (sizeof...(ObserverType) != 0) { + copy_observer(); + } + } + + template