#ifndef FOREIGN_NODE_COMPLETER_HPP #define FOREIGN_NODE_COMPLETER_HPP #include "matador/object/internal/shadow_repository.hpp" #include "matador/object/repository_node.hpp" #include "matador/object/join_columns_collector.hpp" #include "matador/object/object_ptr.hpp" #include "matador/utils/primary_key_attribute.hpp" #include "matador/logger/log_manager.hpp" #include namespace matador::object { /** * Processes the given node and ensures * that all foreign nodes needed by the given node * relations are attached in schema. */ class foreign_node_completer final { private: using node_ptr = std::shared_ptr; public: template static void complete(const std::shared_ptr &node) { internal::shadow_repository shadow(node->repo_); foreign_node_completer completer(shadow); completer.complete_node(node); } template static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, const utils::primary_key_attribute& /*attr*/ = utils::default_pk_attributes) {} static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {} template static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} template static 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*/); 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 *join_column, const utils::foreign_attributes &attr, std::enable_if_t::value> * = nullptr); template void on_has_many(const char * /*id*/, CollectionType &, const char * /*join_column*/, const utils::foreign_attributes & /*attr*/, std::enable_if_t::value> * = nullptr) {} template void on_has_many_to_many(const char *id, CollectionType &collection, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr); template 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); template void complete_node(const std::shared_ptr &node) { nodes_.push(node); Type obj; access::process(*this, obj); 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)) { complete(result.value()); } } private: std::stack nodes_; internal::shadow_repository &repo_; logger::logger log_; join_columns_collector join_columns_collector_{}; }; template void foreign_node_completer::on_belongs_to( const char* /*id*/, ForeignPointerType&, const utils::foreign_attributes& ) { attach_node(); } template void foreign_node_completer::on_has_one( const char*, ForeignPointerType&, const utils::foreign_attributes& ) { attach_node(); } template void foreign_node_completer::on_has_many( const char* /*id*/, CollectionType&, const char* /*join_column*/, const utils::foreign_attributes& /*attr*/, std::enable_if_t::value>* ) { attach_node(); } template 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*/ ) { attach_node(/*id*/); } template void foreign_node_completer::on_has_many_to_many( const char* id, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) { attach_node(/*id*/); } } #endif //FOREIGN_NODE_COMPLETER_HPP