Object.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #ifndef oatpp_data_type_Object_hpp
  25. #define oatpp_data_type_Object_hpp
  26. #include "./Type.hpp"
  27. #include "./Any.hpp"
  28. #include "./Primitive.hpp"
  29. #include "./Enum.hpp"
  30. #include "./UnorderedMap.hpp"
  31. #include "./PairList.hpp"
  32. #include "./List.hpp"
  33. #include "./Vector.hpp"
  34. #include "./UnorderedSet.hpp"
  35. #include "oatpp/core/base/Countable.hpp"
  36. #include <type_traits>
  37. namespace oatpp { namespace data { namespace mapping { namespace type {
  38. /**
  39. * Base class of all object-like mapping-enabled structures ex.: oatpp::DTO.
  40. */
  41. class BaseObject : public oatpp::base::Countable {
  42. public:
  43. /**
  44. * Class to map object properties.
  45. */
  46. class Property {
  47. public:
  48. /**
  49. * Property Type Selector.
  50. */
  51. class TypeSelector {
  52. public:
  53. /**
  54. * Default destructor.
  55. */
  56. virtual ~TypeSelector() = default;
  57. /**
  58. * Select property type.
  59. * @param self - pointer to `this` object.
  60. * @return - &id:oatpp::Type;.
  61. */
  62. virtual const type::Type* selectType(BaseObject* self) = 0;
  63. };
  64. template<class DTOType>
  65. class FieldTypeSelector : public TypeSelector {
  66. public:
  67. const type::Type* selectType(BaseObject* self) override {
  68. return selectFieldType(static_cast<DTOType*>(self));
  69. }
  70. virtual const type::Type* selectFieldType(DTOType* self) = 0;
  71. };
  72. public:
  73. /**
  74. * Editional Info about Property.
  75. */
  76. struct Info {
  77. /**
  78. * Description.
  79. */
  80. std::string description = "";
  81. /**
  82. * Pattern.
  83. */
  84. std::string pattern = "";
  85. /**
  86. * Required.
  87. */
  88. bool required = false;
  89. /**
  90. * Type selector.
  91. * &l:Property::TypeSelector;.
  92. */
  93. TypeSelector* typeSelector = nullptr;
  94. };
  95. private:
  96. const v_int64 offset;
  97. public:
  98. /**
  99. * Constructor.
  100. * @param pOffset - memory offset of object field from object start address.
  101. * @param pName - name of the property.
  102. * @param pType - &l:Type; of the property.
  103. */
  104. Property(v_int64 pOffset, const char* pName, const Type* pType);
  105. /**
  106. * Property name.
  107. */
  108. const char* const name;
  109. /**
  110. * Property type.
  111. */
  112. const Type* const type;
  113. /**
  114. * Property additional info.
  115. */
  116. Info info;
  117. /**
  118. * Set value of object field mapped by this property.
  119. * @param object - object address.
  120. * @param value - value to set.
  121. */
  122. void set(BaseObject* object, const Void& value);
  123. /**
  124. * Get value of object field mapped by this property.
  125. * @param object - object address.
  126. * @return - value of the field.
  127. */
  128. Void get(BaseObject* object);
  129. /**
  130. * Get reference to ObjectWrapper of the object field.
  131. * @param object - object address.
  132. * @return - reference to ObjectWrapper of the object field.
  133. */
  134. Void& getAsRef(BaseObject* object);
  135. };
  136. /**
  137. * Object type properties table.
  138. */
  139. class Properties {
  140. private:
  141. std::unordered_map<std::string, Property*> m_map;
  142. std::list<Property*> m_list;
  143. public:
  144. /**
  145. * Add property to the end of the list.
  146. * @param property
  147. */
  148. Property* pushBack(Property* property);
  149. /**
  150. * Add all properties to the beginning of the list.
  151. * @param properties
  152. */
  153. void pushFrontAll(Properties* properties);
  154. /**
  155. * Get properties as unordered map for random access.
  156. * @return reference to std::unordered_map of std::string to &id:oatpp::data::mapping::type::BaseObject::Property;*.
  157. */
  158. const std::unordered_map<std::string, Property*>& getMap() const {
  159. return m_map;
  160. }
  161. /**
  162. * Get properties in ordered way.
  163. * @return std::list of &id:oatpp::data::mapping::type::BaseObject::Property;*.
  164. */
  165. const std::list<Property*>& getList() const {
  166. return m_list;
  167. }
  168. };
  169. private:
  170. void* m_basePointer = this;
  171. private:
  172. void set(v_int64 offset, const Void& value);
  173. Void get(v_int64 offset) const;
  174. Void& getAsRef(v_int64 offset) const;
  175. protected:
  176. void setBasePointer(void* basePointer);
  177. void* getBasePointer() const;
  178. };
  179. namespace __class {
  180. /**
  181. * AbstractObject class.
  182. */
  183. class AbstractObject {
  184. public:
  185. class PolymorphicDispatcher {
  186. public:
  187. virtual ~PolymorphicDispatcher() = default;
  188. virtual type::Void createObject() const = 0;
  189. virtual const type::BaseObject::Properties* getProperties() const = 0;
  190. };
  191. public:
  192. /**
  193. * Class id.
  194. */
  195. static const ClassId CLASS_ID;
  196. };
  197. /**
  198. * Template for Object class of type T.
  199. * @tparam T - object type.
  200. */
  201. template<class T>
  202. class Object : public AbstractObject {
  203. public:
  204. class PolymorphicDispatcher : public AbstractObject::PolymorphicDispatcher {
  205. public:
  206. type::Void createObject() const override {
  207. return type::Void(std::make_shared<T>(), getType());
  208. }
  209. const type::BaseObject::Properties* getProperties() const override {
  210. return propertiesGetter();
  211. }
  212. };
  213. private:
  214. static type::BaseObject::Properties* initProperties() {
  215. /* initializer */
  216. T obj;
  217. /* init parent properties */
  218. auto parentType = Object<typename T::Z__CLASS_EXTENDED>::getType();
  219. if(parentType->parent != nullptr) {
  220. auto dispatcher = static_cast<const AbstractObject::PolymorphicDispatcher*>(parentType->polymorphicDispatcher);
  221. dispatcher->getProperties();
  222. }
  223. /* extend parent properties */
  224. T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
  225. return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
  226. }
  227. static const BaseObject::Properties* propertiesGetter() {
  228. static type::BaseObject::Properties* properties = initProperties();
  229. return properties;
  230. }
  231. static Type* createType() {
  232. Type::Info info;
  233. info.nameQualifier = T::Z__CLASS_TYPE_NAME();
  234. info.polymorphicDispatcher = new PolymorphicDispatcher();
  235. info.parent = T::getParentType();
  236. return new Type(CLASS_ID, info);
  237. }
  238. public:
  239. /**
  240. * Get type describing this class.
  241. * @return - &id:oatpp::data::mapping::type::Type;
  242. */
  243. static Type* getType() {
  244. static Type* type = createType();
  245. return type;
  246. }
  247. };
  248. }
  249. /**
  250. * ObjectWrapper for &l:DTO;. AKA `oatpp::Object<T>`.
  251. * @tparam ObjT - class extended from &l:DTO;.
  252. */
  253. template<class ObjT>
  254. class DTOWrapper : public ObjectWrapper<ObjT, __class::Object<ObjT>> {
  255. template<class Type>
  256. friend class DTOWrapper;
  257. public:
  258. typedef ObjT TemplateObjectType;
  259. typedef __class::Object<ObjT> TemplateObjectClass;
  260. public:
  261. OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(DTOWrapper, TemplateObjectType, TemplateObjectClass)
  262. template<class OtherT>
  263. DTOWrapper(const OtherT& other)
  264. : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(other.m_ptr)
  265. {}
  266. template<class OtherT>
  267. DTOWrapper(OtherT&& other)
  268. : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(std::move(other.m_ptr))
  269. {}
  270. static DTOWrapper createShared() {
  271. return std::make_shared<TemplateObjectType>();
  272. }
  273. template<class T>
  274. DTOWrapper& operator = (const DTOWrapper<T>& other) {
  275. this->m_ptr = other.m_ptr;
  276. return *this;
  277. }
  278. template<class T>
  279. DTOWrapper& operator = (DTOWrapper<T>&& other) {
  280. this->m_ptr = std::move(other.m_ptr);
  281. return *this;
  282. }
  283. template<typename T,
  284. typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
  285. >
  286. inline bool operator == (T){
  287. return this->m_ptr.get() == nullptr;
  288. }
  289. template<typename T,
  290. typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
  291. >
  292. inline bool operator != (T){
  293. return this->m_ptr.get() != nullptr;
  294. }
  295. template<typename T,
  296. typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
  297. >
  298. inline bool operator == (const T &other) const {
  299. if(this->m_ptr.get() == other.m_ptr.get()) return true;
  300. if(!this->m_ptr || !other.m_ptr) return false;
  301. return *this->m_ptr == *other.m_ptr;
  302. }
  303. template<typename T,
  304. typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
  305. >
  306. inline bool operator != (const T &other) const {
  307. return !operator == (other);
  308. }
  309. static const std::unordered_map<std::string, BaseObject::Property*>& getPropertiesMap() {
  310. auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
  311. __class::Object<ObjT>::getType()->polymorphicDispatcher
  312. );
  313. return dispatcher->getProperties()->getMap();
  314. }
  315. static const std::list<BaseObject::Property*>& getPropertiesList() {
  316. auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
  317. __class::Object<ObjT>::getType()->polymorphicDispatcher
  318. );
  319. return dispatcher->getProperties()->getList();
  320. }
  321. static v_int64 getPropertiesCount() {
  322. auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
  323. __class::Object<ObjT>::getType()->polymorphicDispatcher
  324. );
  325. return dispatcher->getProperties()->getList().size();
  326. }
  327. ObjectWrapper<void>& operator[](const std::string& propertyName) {
  328. return getPropertiesMap().at(propertyName)->getAsRef(this->m_ptr.get());
  329. }
  330. };
  331. /**
  332. * Base class for all DTO objects.
  333. * For more info about Data Transfer Object (DTO) see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/).
  334. */
  335. class DTO : public BaseObject {
  336. template<class T>
  337. friend class __class::Object;
  338. private:
  339. typedef DTO Z__CLASS;
  340. typedef DTO Z__CLASS_EXTENDED;
  341. public:
  342. typedef oatpp::data::mapping::type::Void Void;
  343. typedef oatpp::data::mapping::type::Any Any;
  344. typedef oatpp::data::mapping::type::String String;
  345. typedef oatpp::data::mapping::type::Int8 Int8;
  346. typedef oatpp::data::mapping::type::UInt8 UInt8;
  347. typedef oatpp::data::mapping::type::Int16 Int16;
  348. typedef oatpp::data::mapping::type::UInt16 UInt16;
  349. typedef oatpp::data::mapping::type::Int32 Int32;
  350. typedef oatpp::data::mapping::type::UInt32 UInt32;
  351. typedef oatpp::data::mapping::type::Int64 Int64;
  352. typedef oatpp::data::mapping::type::UInt64 UInt64;
  353. typedef oatpp::data::mapping::type::Float32 Float32;
  354. typedef oatpp::data::mapping::type::Float64 Float64;
  355. typedef oatpp::data::mapping::type::Boolean Boolean;
  356. template <class T>
  357. using Object = DTOWrapper<T>;
  358. template <class T>
  359. using Enum = oatpp::data::mapping::type::Enum<T>;
  360. template <class T>
  361. using Vector = oatpp::data::mapping::type::Vector<T>;
  362. template <class T>
  363. using UnorderedSet = oatpp::data::mapping::type::UnorderedSet<T>;
  364. template <class T>
  365. using List = oatpp::data::mapping::type::List<T>;
  366. template <class Value>
  367. using Fields = oatpp::data::mapping::type::PairList<String, Value>;
  368. template <class Value>
  369. using UnorderedFields = oatpp::data::mapping::type::UnorderedMap<String, Value>;
  370. private:
  371. static const mapping::type::Type* getParentType();
  372. static const char* Z__CLASS_TYPE_NAME();
  373. static data::mapping::type::BaseObject::Properties* Z__CLASS_GET_FIELDS_MAP();
  374. static BaseObject::Properties* Z__CLASS_EXTEND(BaseObject::Properties* properties, BaseObject::Properties* extensionProperties);
  375. public:
  376. virtual v_uint64 defaultHashCode() const {
  377. return (v_uint64) reinterpret_cast<v_buff_usize>(this);
  378. }
  379. virtual bool defaultEquals(const DTO& other) const {
  380. return this == &other;
  381. }
  382. v_uint64 hashCode() const {
  383. return defaultHashCode();
  384. }
  385. bool operator==(const DTO& other) const {
  386. return defaultEquals(other);
  387. }
  388. };
  389. }}}}
  390. namespace std {
  391. template<class T>
  392. struct hash<oatpp::data::mapping::type::DTOWrapper<T>> {
  393. typedef oatpp::data::mapping::type::DTOWrapper<T> argument_type;
  394. typedef v_uint64 result_type;
  395. result_type operator()(argument_type const &ow) const noexcept {
  396. if(ow) {
  397. return ow->hashCode();
  398. }
  399. return 0;
  400. }
  401. };
  402. }
  403. #endif /* oatpp_data_type_Object_hpp */