#ifndef SCHEMA_NODE_HPP #define SCHEMA_NODE_HPP #include "matador/object/attribute_definition_generator.hpp" #include "matador/object/object_info.hpp" #include "matador/object/primary_key_resolver.hpp" #include namespace matador::object { class basic_object_info; class repository; class repository_node final { public: using node_ptr = std::shared_ptr; template < typename Type > static std::shared_ptr make_node(repository& repo, const std::string& name) { auto node = std::shared_ptr(new repository_node(repo, name, typeid(Type))); primary_key_resolver resolver; object_definition obj{name, {}}; auto pk_info = resolver.resolve(); auto ref_column = determine_reference_column(typeid(Type), name, pk_info, repo); const auto attributes = attribute_definition_generator::generate(repo); for (auto&& attr : attributes) { obj.append(std::move(attr)); } auto info = std::make_unique>( node, std::move(pk_info.pk), ref_column, std::move(obj), []{ return std::make_unique(); } ); node->info_ = std::move(info); return node; } template < typename Type, typename CreatorFunc > static utils::result make_relation_node(object::repository& tree, const std::string& name, CreatorFunc &&creator) { const auto result = make_and_attach_node(tree, name, typeid(Type)); if (!result) { return result; } auto obj = creator(); auto info = std::make_unique>( result.value(), object_definition{attribute_definition_generator::generate(*obj, tree)}, std::move(creator) ); result.value()->info_ = std::move(info); return result; } static std::shared_ptr make_null_node(repository& tree); repository_node(const repository_node& other) = delete; repository_node(repository_node&& other) = default; repository_node& operator=(const repository_node& other) = delete; repository_node& operator=(repository_node&& other) = delete; ~repository_node() = default; [[nodiscard]] std::string name() const; [[nodiscard]] std::type_index type_index() const; [[nodiscard]] node_ptr next() const; [[nodiscard]] node_ptr prev() const; [[nodiscard]] const basic_object_info& info() const; void update_name(const std::string& name); template object_info_ref info() const { return std::ref(static_cast&>(*info_)); } [[nodiscard]] const object::repository& schema() const; [[nodiscard]] bool has_children() const; private: explicit repository_node(object::repository& tree); repository_node(object::repository& tree, const std::type_index& ti); repository_node(object::repository& tree, std::string name, const std::type_index& ti); void unlink(); static utils::result make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti); static std::shared_ptr determine_reference_column(const std::type_index& ti, object_definition& obj, const primary_key_info& pk_info, repository& repo); private: friend class repository; template friend class relation_completer; friend class foreign_node_completer; friend class const_repository_node_iterator; repository &repo_; std::type_index type_index_; std::unique_ptr info_; std::shared_ptr parent_; std::shared_ptr previous_sibling_; std::shared_ptr next_sibling_; std::shared_ptr first_child_; std::shared_ptr last_child_; std::string name_; size_t depth_{0}; }; } #endif //SCHEMA_NODE_HPP