query/include/matador/object/repository_node.hpp

121 lines
3.8 KiB
C++

#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 <memory>
namespace matador::object {
class basic_object_info;
class repository;
class repository_node final {
public:
using node_ptr = std::shared_ptr<repository_node>;
template < typename Type >
static std::shared_ptr<repository_node> make_node(repository& repo, const std::string& name) {
auto node = std::shared_ptr<repository_node>(new repository_node(repo, name, typeid(Type)));
primary_key_resolver resolver;
auto pk_info = resolver.resolve<Type>();
auto ref_column = determine_reference_column(typeid(Type), name, pk_info, repo);
const auto attributes = attribute_definition_generator::generate<Type>(repo);
auto info = std::make_unique<object_info<Type>>(
node,
attributes,
std::move(pk_info.pk),
ref_column,
// obj,
[]{ return std::make_unique<Type>(); }
);
node->info_ = std::move(info);
return node;
}
template < typename Type, typename CreatorFunc >
static utils::result<node_ptr, utils::error> make_relation_node(repository& repo, const std::string& name, CreatorFunc &&creator) {
const auto result = make_and_attach_node(repo, name, typeid(Type));
if (!result) {
return result;
}
auto obj = creator();
auto info = std::make_unique<object_info<Type>>(
result.value(),
attribute_definition_generator::generate(*obj, repo),
std::move(creator)
);
result.value()->info_ = std::move(info);
return result;
}
static std::shared_ptr<repository_node> make_null_node(repository& repo);
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 <typename Type>
object_info_ref<Type> info() const {
return std::ref(static_cast<const object_info<Type>&>(*info_));
}
[[nodiscard]] const repository& schema() const;
[[nodiscard]] bool has_children() const;
private:
explicit repository_node(repository& repo);
repository_node(repository& repo, const std::type_index& ti);
repository_node(repository& repo, std::string name, const std::type_index& ti);
void unlink();
static utils::result<node_ptr, utils::error> make_and_attach_node(repository& repo, const std::string& name, const std::type_index& ti);
static std::shared_ptr<attribute_definition> determine_reference_column(const std::type_index& ti,
const std::string& table_name,
const primary_key_info& pk_info,
repository& repo);
private:
friend class repository;
template<typename Type>
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<basic_object_info> info_;
std::shared_ptr<repository_node> parent_;
std::shared_ptr<repository_node> previous_sibling_;
std::shared_ptr<repository_node> next_sibling_;
std::shared_ptr<repository_node> first_child_;
std::shared_ptr<repository_node> last_child_;
std::string name_;
size_t depth_{0};
};
}
#endif //SCHEMA_NODE_HPP