diff --git a/include/matador/object/collection.hpp b/include/matador/object/collection.hpp index bb6cbf1..aa7be07 100644 --- a/include/matador/object/collection.hpp +++ b/include/matador/object/collection.hpp @@ -25,19 +25,19 @@ public: } iterator begin() { - return proxy_->items().begin(); + return proxy_->begin(); } iterator end() { - return proxy_->items().end(); + return proxy_->end(); } const_iterator begin() const { - return proxy_->items().begin(); + return proxy_->begin(); } const_iterator end() const { - return proxy_->items().end(); + return proxy_->end(); } [[nodiscard]] size_t size() const { @@ -53,7 +53,7 @@ public: } private: - std::shared_ptr> proxy_; + std::shared_ptr> proxy_; }; } diff --git a/include/matador/object/collection_proxy.hpp b/include/matador/object/collection_proxy.hpp index ce98e9e..6b9ca45 100644 --- a/include/matador/object/collection_proxy.hpp +++ b/include/matador/object/collection_proxy.hpp @@ -1,8 +1,8 @@ #ifndef MATADOR_COLLECTION_PROXY_HPP #define MATADOR_COLLECTION_PROXY_HPP - #include "matador/object/collection_resolver.hpp" +#include "matador/object/many_to_many_relation.hpp" #include "matador/utils/identifier.hpp" @@ -12,14 +12,84 @@ namespace matador::object { +// has many primitive +// relation +// has many ptr +// relation +// has many to many +// relation -template -class collection_proxy final { +template < class RelationType > +struct relation_iterator_traits; + +template < typename Type, typename OwnerType > +struct relation_iterator_traits> { + +}; + +template +class collection_proxy_iterator { public: using value_type = Type; + using reference = Type&; + using pointer = Type*; + using iterator_category = std::forward_iterator_tag; + + collection_proxy_iterator() = default; + explicit collection_proxy_iterator(typename std::vector::iterator it) + : it_(it) {} + + reference operator*() { return *it_; } + pointer operator->() { return &*it_; } + collection_proxy_iterator& operator++() { + ++it_; + return *this; + } + bool operator==(const collection_proxy_iterator& other) const { + return it_ == other.it_; + } + bool operator!=(const collection_proxy_iterator& other) const { + return !operator==(other); + } + +private: + typename std::vector::iterator it_; +}; + +template +class abstract_collection_proxy { +public: + using value_type = Type; + using relation_type = RelationType; using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; + virtual ~abstract_collection_proxy() = default; + + virtual void push_back(const value_type& value) = 0; + + virtual iterator begin() = 0; + virtual iterator end() = 0; + virtual const_iterator begin() const = 0; + virtual const_iterator end() const = 0; + + [[nodiscard]] virtual size_t size() const = 0; + [[nodiscard]] virtual bool empty() const = 0; +// virtual collection_proxy_iterator begin() = 0; +// virtual collection_proxy_iterator end() = 0; + [[nodiscard]] virtual const utils::identifier& owner_id() const = 0; + +protected: + std::vector items_; +}; + +template +class collection_proxy : public abstract_collection_proxy { +public: + using value_type = Type; + using iterator = typename abstract_collection_proxy::iterator; + using const_iterator = typename abstract_collection_proxy::const_iterator; + collection_proxy() = default; // Lazy @@ -34,17 +104,36 @@ public: explicit collection_proxy(std::vector items) : items_(std::move(items)) {} - [[nodiscard]] const utils::identifier& owner_id() const { + [[nodiscard]] const utils::identifier& owner_id() const override { return owner_id_; } - const std::vector& items() const { + + iterator begin() override { resolve(); - return items_; + return items_.begin(); } - std::vector& items() { + iterator end() override { resolve(); - return items_; + return items_.end(); } + + const_iterator begin() const override { + resolve(); + return items_.begin(); + } + + const_iterator end() const override { + resolve(); + return items_.end(); + } + // const std::vector& items() const { + // resolve(); + // return items_; + // } + // std::vector& items() { + // resolve(); + // return items_; + // } private: void resolve() { if (loaded_) { @@ -70,5 +159,18 @@ private: std::weak_ptr> resolver_{}; mutable std::mutex mutex_{}; }; + +template +class collection_many_to_many_proxy { +public: + using value_type = Type; + using owner_type = OwnerType; + using relation_type = many_to_many_relation; + using iterator = typename std::vector::iterator; + using const_iterator = typename std::vector::const_iterator; + +private: + std::vector relations_; +}; } #endif //MATADOR_COLLECTION_PROXY_HPP \ No newline at end of file diff --git a/include/matador/object/many_to_many_relation.hpp b/include/matador/object/many_to_many_relation.hpp index 8bd1029..1b076b5 100644 --- a/include/matador/object/many_to_many_relation.hpp +++ b/include/matador/object/many_to_many_relation.hpp @@ -8,6 +8,48 @@ namespace matador::object { +template < class LocalType, class ForeignType > +class relation { +public: + relation() = default; + relation(std::string local_name, std::string remote_name) + : local_name_(std::move(local_name)) + , remote_name_(std::move(remote_name)) {} + relation(std::string local_name, std::string remote_name, const object_ptr& local, const ForeignType& remote) + : local_name_(std::move(local_name)) + , remote_name_(std::move(remote_name)) + , local_(local) + , remote_(remote) + {} + + template + void process(Operator &op) { + namespace field = matador::access; + field::belongs_to(op, local_name_.c_str(), local_, utils::CascadeNoneFetchLazy); + foreign_field(op); + } + + object_ptr local() const { return local_; } + const ForeignType& remote() const { return remote_; } + +private: + template + void foreign_field(Operator &op, std::enable_if_t::value>* /*unused*/) { + namespace field = matador::access; + field::attribute(op, remote_name_.c_str(), remote_); + } + template + void foreign_field(Operator &op, std::enable_if_t::value>* /*unused*/) { + namespace field = matador::access; + field::belongs_to(op, remote_name_.c_str(), remote_, utils::CascadeNoneFetchLazy); + } +private: + std::string local_name_; + std::string remote_name_; + object_ptr local_; + ForeignType remote_; +}; + template < class LocalType, class ForeignType > class many_to_many_relation { public: diff --git a/include/matador/object/relation_completer.hpp b/include/matador/object/relation_completer.hpp index 077ac75..2724b0e 100644 --- a/include/matador/object/relation_completer.hpp +++ b/include/matador/object/relation_completer.hpp @@ -172,7 +172,7 @@ void relation_completer::on_has_many(const char *id, Collect using relation_value_type = many_to_many_relation; // Check if the object_ptr type is already inserted in the schema (by id) - auto foreign_node = find_node(typeid(value_type)); + const auto foreign_node = find_node(typeid(value_type)); if (!foreign_node) { // Todo: throw internal error or attach node return; @@ -191,7 +191,7 @@ void relation_completer::on_has_many(const char *id, Collect const auto local_endpoint = std::make_shared(id, relation_type::HasMany, *foreign_node); nodes_.top()->info_->register_relation_endpoint(typeid(value_type), local_endpoint); } else { - // A relation table is necessary + // A relation table is necessary. // Endpoint was not found. // Always attach a many-to-many relation type. If later a // belongs-to relation handles this relation, the many-to-many @@ -222,8 +222,7 @@ template typename... Observers> template void relation_completer::on_has_many(const char *id, CollectionType &, const char *join_column, const utils::foreign_attributes &, - std::enable_if_t::value> - * /*unused*/) { + std::enable_if_t::value>* /*unused*/) { using value_type = typename CollectionType::value_type; using relation_value_type = many_to_relation;