176 lines
4.7 KiB
C++
176 lines
4.7 KiB
C++
#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"
|
|
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
namespace matador::object {
|
|
|
|
// has many primitive
|
|
// relation<OwnerType, PrimitiveType>
|
|
// has many ptr
|
|
// relation<OwnerType, ObjectType>
|
|
// has many to many
|
|
// relation<OwnerType, ForeignType>
|
|
|
|
template < class RelationType >
|
|
struct relation_iterator_traits;
|
|
|
|
template < typename Type, typename OwnerType >
|
|
struct relation_iterator_traits<relation<OwnerType, Type>> {
|
|
|
|
};
|
|
|
|
template<typename Type, typename RelationType = Type>
|
|
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<RelationType>::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<RelationType>::iterator it_;
|
|
};
|
|
|
|
template<typename Type, typename RelationType = Type>
|
|
class abstract_collection_proxy {
|
|
public:
|
|
using value_type = Type;
|
|
using relation_type = RelationType;
|
|
using iterator = typename std::vector<value_type>::iterator;
|
|
using const_iterator = typename std::vector<value_type>::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<Type> begin() = 0;
|
|
// virtual collection_proxy_iterator<Type> end() = 0;
|
|
[[nodiscard]] virtual const utils::identifier& owner_id() const = 0;
|
|
|
|
protected:
|
|
std::vector<relation_type> items_;
|
|
};
|
|
|
|
template<typename Type>
|
|
class collection_proxy : public abstract_collection_proxy<Type> {
|
|
public:
|
|
using value_type = Type;
|
|
using iterator = typename abstract_collection_proxy<Type>::iterator;
|
|
using const_iterator = typename abstract_collection_proxy<Type>::const_iterator;
|
|
|
|
collection_proxy() = default;
|
|
|
|
// Lazy
|
|
collection_proxy(std::weak_ptr<collection_resolver<Type>> resolver, utils::identifier owner_id)
|
|
: owner_id_(std::move(owner_id)), resolver_(std::move(resolver)) {}
|
|
|
|
// Eager
|
|
collection_proxy(std::weak_ptr<collection_resolver<Type>> resolver, std::vector<Type> items)
|
|
: loaded_{true}, items_(std::move(items)), resolver_(std::move(resolver)) {}
|
|
|
|
// Transient
|
|
explicit collection_proxy(std::vector<Type> items)
|
|
: items_(std::move(items)) {}
|
|
|
|
[[nodiscard]] const utils::identifier& owner_id() const override {
|
|
return owner_id_;
|
|
}
|
|
|
|
iterator begin() override {
|
|
resolve();
|
|
return items_.begin();
|
|
}
|
|
iterator end() override {
|
|
resolve();
|
|
return items_.end();
|
|
}
|
|
|
|
const_iterator begin() const override {
|
|
resolve();
|
|
return items_.begin();
|
|
}
|
|
|
|
const_iterator end() const override {
|
|
resolve();
|
|
return items_.end();
|
|
}
|
|
// const std::vector<Type>& items() const {
|
|
// resolve();
|
|
// return items_;
|
|
// }
|
|
// std::vector<Type>& items() {
|
|
// resolve();
|
|
// return items_;
|
|
// }
|
|
private:
|
|
void resolve() {
|
|
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_);
|
|
loaded_ = true;
|
|
}
|
|
|
|
private:
|
|
const utils::identifier owner_id_;
|
|
std::atomic_bool loaded_{false};
|
|
std::vector<Type> items_;
|
|
std::weak_ptr<collection_resolver<Type>> resolver_{};
|
|
mutable std::mutex mutex_{};
|
|
};
|
|
|
|
template<typename Type, class OwnerType>
|
|
class collection_many_to_many_proxy {
|
|
public:
|
|
using value_type = Type;
|
|
using owner_type = OwnerType;
|
|
using relation_type = many_to_many_relation<value_type, owner_type>;
|
|
using iterator = typename std::vector<relation_type>::iterator;
|
|
using const_iterator = typename std::vector<relation_type>::const_iterator;
|
|
|
|
private:
|
|
std::vector<relation_type> relations_;
|
|
};
|
|
}
|
|
#endif //MATADOR_COLLECTION_PROXY_HPP
|