111 lines
4.7 KiB
C++
111 lines
4.7 KiB
C++
#ifndef FOREIGN_NODE_COMPLETER_HPP
|
|
#define FOREIGN_NODE_COMPLETER_HPP
|
|
|
|
#include "matador/object/internal/shadow_schema.hpp"
|
|
#include "matador/object/schema_node.hpp"
|
|
#include "matador/object/join_columns_collector.hpp"
|
|
#include "matador/object/object_ptr.hpp"
|
|
|
|
#include "matador/logger/log_manager.hpp"
|
|
|
|
#include <stack>
|
|
|
|
namespace matador::object {
|
|
|
|
/**
|
|
* Processes the given node and ensures
|
|
* that all foreign nodes needed by the given node
|
|
* relations are attached in schema.
|
|
*
|
|
* @tparam Type Type of node to complete
|
|
*/
|
|
class foreign_node_completer final {
|
|
private:
|
|
using node_ptr = std::shared_ptr<schema_node>;
|
|
|
|
public:
|
|
template<class Type>
|
|
static void complete(const std::shared_ptr<schema_node> &node) {
|
|
internal::shadow_schema shadow(node->schema_);
|
|
foreign_node_completer completer(shadow);
|
|
|
|
completer.complete_node<Type>(node);
|
|
}
|
|
|
|
template<class PrimaryKeyType>
|
|
static void on_primary_key(const char * /*id*/, PrimaryKeyType &/*pk*/, std::enable_if_t<std::is_integral_v<PrimaryKeyType> && !std::is_same_v<bool, PrimaryKeyType>> * = nullptr) {}
|
|
static void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t /*size*/) {}
|
|
static void on_revision(const char * /*id*/, uint64_t &/*rev*/) {}
|
|
template<typename AttributeType>
|
|
static void on_attribute(const char * /*id*/, AttributeType &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
|
template<typename AttributeType>
|
|
static void on_attribute(const char * /*id*/, std::optional<AttributeType> &/*val*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {}
|
|
|
|
template<class ForeignPointerType>
|
|
void on_belongs_to(const char *id, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/);
|
|
template<class ForeignPointerType>
|
|
static void on_has_one(const char * /*id*/, ForeignPointerType &/*obj*/, const utils::foreign_attributes &/*attr*/) {}
|
|
|
|
template<class CollectionType>
|
|
void on_has_many(const char *id, CollectionType &, const char *join_column, const utils::foreign_attributes &attr, std::enable_if_t<is_object_ptr<typename CollectionType::value_type>::value> * = nullptr);
|
|
template<class CollectionType>
|
|
void on_has_many(const char * /*id*/, CollectionType &, const char * /*join_column*/, const utils::foreign_attributes & /*attr*/, std::enable_if_t<!is_object_ptr<typename CollectionType::value_type>::value> * = nullptr) {}
|
|
|
|
template<class CollectionType>
|
|
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<class CollectionType>
|
|
void on_has_many_to_many(const char *id, CollectionType &collection, const utils::foreign_attributes &attr);
|
|
|
|
private:
|
|
explicit foreign_node_completer(internal::shadow_schema &shadow);
|
|
|
|
template<typename Type>
|
|
void complete_node(const std::shared_ptr<schema_node> &node) {
|
|
nodes_.push(node);
|
|
|
|
Type obj;
|
|
access::process(*this, obj);
|
|
nodes_.pop();
|
|
}
|
|
|
|
template<typename Type>
|
|
void attach_node() {
|
|
if (schema_.schema_contains(typeid(Type))) {
|
|
return;
|
|
}
|
|
const auto node = schema_node::make_node<Type>(schema_.schema(), "");
|
|
if (auto result = schema_.attach_node(node)) {
|
|
complete<Type>(result.value());
|
|
}
|
|
}
|
|
private:
|
|
std::stack<node_ptr> nodes_;
|
|
internal::shadow_schema &schema_;
|
|
logger::logger log_;
|
|
join_columns_collector join_columns_collector_{};
|
|
};
|
|
|
|
|
|
template<class ForeignPointerType>
|
|
void foreign_node_completer::on_belongs_to( const char* /*id*/, ForeignPointerType&, const utils::foreign_attributes& ) {
|
|
attach_node<typename ForeignPointerType::value_type>();
|
|
}
|
|
|
|
template<class CollectionType>
|
|
void foreign_node_completer::on_has_many( const char* /*id*/, CollectionType&, const char* /*join_column*/, const utils::foreign_attributes& /*attr*/, std::enable_if_t<is_object_ptr<typename CollectionType::value_type>::value>* ) {
|
|
attach_node<typename CollectionType::value_type::value_type>();
|
|
}
|
|
|
|
template<class CollectionType>
|
|
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<typename CollectionType::value_type::value_type>();
|
|
}
|
|
|
|
template<class CollectionType>
|
|
void foreign_node_completer::on_has_many_to_many( const char* /*id*/, CollectionType& /*collection*/, const utils::foreign_attributes& /*attr*/ ) {
|
|
attach_node<typename CollectionType::value_type::value_type>();
|
|
}
|
|
|
|
}
|
|
#endif //FOREIGN_NODE_COMPLETER_HPP
|