#pragma once #include #include "storage/model/properties/property.hpp" #include "storage/model/properties/property_family.hpp" #include "utils/option.hpp" template using prop_key_t = typename PropertyFamily::PropertyType::PropertyFamilyKey; template using type_key_t = typename PropertyFamily::PropertyType::template PropertyTypeKey; template class Properties { public: using sptr = std::shared_ptr; using prop_key_t = typename PropertyFamily::PropertyType::PropertyFamilyKey; template using type_key_t = typename PropertyFamily::PropertyType::template PropertyTypeKey; auto begin() const { return props.begin(); } auto cbegin() const { return props.cbegin(); } auto end() const { return props.end(); } auto cend() const { return props.cend(); } size_t size() const { return props.size(); } const Property &at(PropertyFamily &key) const; const Property &at(prop_key_t &key) const; template OptionPtr at(type_key_t &key) const { auto f_key = key.family_key(); auto it = props.find(f_key); if (it == props.end() || it->first.prop_type() != key.prop_type()) return OptionPtr(); return OptionPtr(&(it->second.get()->template as())); } template void set(type_key_t &key, Args &&... args) { auto value = std::make_shared(std::forward(args)...); // try to emplace the item // TODO: There is uneccesary copying of value here. auto result = props.emplace(std::make_pair(key, value)); if (!result.second) { // It is necessary to change key because the types from before and // now // could be different. prop_key_t &key_ref = const_cast(result.first->first); key_ref = key; result.first->second = std::move(value); } } void set(prop_key_t &key, Property::sptr value); void clear(prop_key_t &key); void clear(PropertyFamily &key); template void accept(Handler &handler) const { for (auto &kv : props) handler.handle(kv.first, *kv.second); handler.finish(); } template void for_all(Handler handler) const { for (auto &kv : props) handler(kv.first, kv.second); } private: using props_t = std::unordered_map>; props_t props; };