#pragma once #include "../Base.h" #include "cru/base/ClonablePtr.h" #include "cru/base/Exception.h" #include "cru/xml/XmlNode.h" #include #include #include #include namespace cru::ui::mapper { template class BasicMapper; class CRU_UI_API MapperBase : public Object { public: explicit MapperBase(std::type_index type_index); CRU_DELETE_COPY(MapperBase) CRU_DELETE_MOVE(MapperBase) ~MapperBase() override = default; public: std::type_index GetTypeIndex() const { return type_index_; } template BasicMapper* StaticCast() { return static_cast*>(this); } template BasicMapper* DynamicCast() { return dynamic_cast*>(this); } virtual bool SupportMapFromString() { return false; } virtual bool SupportMapFromXml() { return false; } virtual bool XmlElementIsOfThisType(xml::XmlElementNode* node); protected: void SetAllowedTags(std::vector allowed_tags) { allowed_tags_ = std::move(allowed_tags); } private: std::type_index type_index_; std::vector allowed_tags_; }; template class CRU_UI_API BasicMapper : public MapperBase { public: static_assert(std::is_default_constructible_v, "T must be default constructible."); BasicMapper() : MapperBase(typeid(T)) {} CRU_DELETE_COPY(BasicMapper) CRU_DELETE_MOVE(BasicMapper) ~BasicMapper() override = default; virtual T MapFromString(String str) { if (!SupportMapFromString()) { throw Exception(u"This mapper does not support map from string."); } return DoMapFromString(str); } T MapFromXml(xml::XmlElementNode* node) { if (!SupportMapFromXml()) { throw Exception(u"This mapper does not support map from xml."); } if (!XmlElementIsOfThisType(node)) { throw Exception(u"This xml element is not of mapping type."); } return DoMapFromXml(node); } protected: virtual T DoMapFromString(String str) { return {}; } virtual T DoMapFromXml(xml::XmlElementNode* node) { return {}; } }; template using BasicSharedPtrMapper = BasicMapper>; template using BasicClonablePtrMapper = BasicMapper>; } // namespace cru::ui::mapper