#include #include "matador/object/schema.hpp" namespace matador::object { utils::error make_error(const error_code ec, const std::string &msg) { return utils::error(ec, msg); } schema::schema(std::string name) : name_(std::move(name)) , root_(schema_node::make_null_node(*this)) { root_->first_child_ = std::shared_ptr(new schema_node(*this)); root_->last_child_ = std::shared_ptr(new schema_node(*this)); root_->first_child_->next_sibling_ = root_->last_child_; root_->last_child_->previous_sibling_ = root_->first_child_; } schema::const_iterator schema::begin() const { return const_iterator(root_->first_child_->next_sibling_); } schema::const_iterator schema::end() const { return const_iterator(root_->last_child_); } bool schema::empty() const { return root_->first_child_ == root_->last_child_->previous_sibling_; } size_t schema::size() const { return static_cast(std::distance(begin(), end())); } std::string schema::name() const { return name_; } utils::result, utils::error> schema::reference(const std::type_index &type_index) const { const auto result = find_node(type_index); if (result) { return utils::ok((*result)->basic_info().reference_column()); } if (const auto it = expected_node_map_.find(type_index); it != expected_node_map_.end()) { return utils::ok(it->second->basic_info().reference_column()); } return utils::failure(result.err()); } utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, const std::string &parent) { if (has_node(node->type_index(), node->name())) { return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists.")); } // set node to root node auto parent_node = root_; if (!parent.empty()) { auto result = find_node(parent); if (!result.is_ok() && result.err().ec() != error_code::NodeNotFound) { return result; } parent_node = *result; } push_back_child(parent_node, node); // Todo: check return value node_map_.insert({node->name(), node})/*.first*/; type_index_node_map_.insert({node->type_index(), node}); return utils::ok(node); } utils::result, utils::error> schema::attach_node(const std::shared_ptr &node, const std::type_index &type_index) { if (has_node(node->type_index(), node->name())) { return utils::failure(make_error(error_code::NodeAlreadyExists, "Node '" + node->name() + "' already exists.")); } auto result = find_node(type_index); if (!result.is_ok() && result.err().ec() != error_code::NodeNotFound) { return result; } push_back_child(*result, node); // Todo: check return value node_map_.insert({node->name(), node})/*.first*/; type_index_node_map_.insert({node->type_index(), node}); return utils::ok(node); } utils::result, utils::error> schema::find_node(const std::string &name) const { // first search in the prototype map const auto i = node_map_.find(name); if (i == node_map_.end()) { return utils::failure(make_error(error_code::NodeNotFound, "Couldn't find node by name '" + name + "'")); } return utils::ok(i->second); } utils::result, utils::error> schema::find_node(const std::type_index &type_index) const { const auto i = type_index_node_map_.find(type_index); if (i == type_index_node_map_.end()) { return utils::failure(make_error(error_code::NodeNotFound, "Couldn't find node by type '" + std::string(type_index.name()) + "'")); } return utils::ok(i->second); } void schema::push_back_child(const node_ptr &parent, const node_ptr &child) { child->parent_ = parent; child->previous_sibling_ = parent->last_child_->previous_sibling_; child->next_sibling_ = parent->last_child_; /* * +-----------------------------<- (first) parent (last) -> ----------------------------+ * | | * first (next) -> <- (prev) child_1 (next) -> <- (prev) new_child (next) -> <- (prev) last * ^^^^^^^ inserted ^^^^^^ */ parent->last_child_->previous_sibling_->next_sibling_ = child; parent->last_child_->previous_sibling_ = child; // set depth // child->depth = depth + 1; } bool schema::has_node(const std::string &name) const { return node_map_.count(name) > 0; } bool schema::has_node(const std::type_index &index) const { return type_index_node_map_.count(index) > 0; } bool schema::has_node(const std::type_index &index, const std::string &name) const { return node_map_.count(name) > 0 || type_index_node_map_.count(index) > 0; } } // namespace matador::object