#ifndef MATADOR_COLLECTION_PROXY_HPP #define MATADOR_COLLECTION_PROXY_HPP #include #include "matador/object/object_ptr.hpp" #include "matador/utils/identifier.hpp" #include namespace matador::object { class abstract_collection_resolver { public: virtual ~abstract_collection_resolver() = default; [[nodiscard]] const std::type_index& type() const { return type_; } protected: explicit abstract_collection_resolver(const std::type_index& ti) : type_(ti) {} public: const std::type_index type_; }; template class collection_resolver : public abstract_collection_resolver { public: collection_resolver() : abstract_collection_resolver(typeid(Type)) {} virtual std::shared_ptr resolve(const utils::identifier& id) = 0; }; template class collection_proxy final { public: collection_proxy(std::weak_ptr> resolver, utils::identifier owner_id) : owner_id_(std::move(owner_id)), resolver_(std::move(resolver)) {} collection_proxy(std::weak_ptr> resolver, std::vector> items) : items_(std::move(items)), resolver_(std::move(resolver)) {} explicit collection_proxy(std::vector> items) : items_(std::move(items)) {} [[nodiscard]] const utils::identifier& owner_id() const { return owner_id_; } const std::vector>& items() const { return items_; } std::vector>& items() { return items_; } private: void resolve() const { if (loaded_) { return; } std::lock_guard lock(mutex_); auto resolver = resolver_.lock(); if (!resolver) { return; // Todo: Add states (Detached, Attached, Transient) - if attached an no resolver is available throw runtime exception // throw std::runtime_error("Detached proxy (session expired)"); } items_ = resolver->resolve(owner_id_); } private: const utils::identifier owner_id_; std::atomic_bool loaded_{false}; std::vector> items_; std::weak_ptr> resolver_{}; mutable std::mutex mutex_{}; }; } #endif //MATADOR_COLLECTION_PROXY_HPP