123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 |
- /***************************************************************************
- *
- * Project _____ __ ____ _ _
- * ( _ ) /__\ (_ _)_| |_ _| |_
- * )(_)( /(__)\ )( (_ _)(_ _)
- * (_____)(__)(__)(__) |_| |_|
- *
- *
- * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ***************************************************************************/
- #ifndef oatpp_data_type_Object_hpp
- #define oatpp_data_type_Object_hpp
- #include "./Type.hpp"
- #include "./Any.hpp"
- #include "./Primitive.hpp"
- #include "./Enum.hpp"
- #include "./UnorderedMap.hpp"
- #include "./PairList.hpp"
- #include "./List.hpp"
- #include "./Vector.hpp"
- #include "./UnorderedSet.hpp"
- #include "oatpp/core/base/Countable.hpp"
- #include <type_traits>
- namespace oatpp { namespace data { namespace mapping { namespace type {
- /**
- * Base class of all object-like mapping-enabled structures ex.: oatpp::DTO.
- */
- class BaseObject : public oatpp::base::Countable {
- public:
- /**
- * Class to map object properties.
- */
- class Property {
- public:
- /**
- * Property Type Selector.
- */
- class TypeSelector {
- public:
- /**
- * Default destructor.
- */
- virtual ~TypeSelector() = default;
- /**
- * Select property type.
- * @param self - pointer to `this` object.
- * @return - &id:oatpp::Type;.
- */
- virtual const type::Type* selectType(BaseObject* self) = 0;
- };
- template<class DTOType>
- class FieldTypeSelector : public TypeSelector {
- public:
- const type::Type* selectType(BaseObject* self) override {
- return selectFieldType(static_cast<DTOType*>(self));
- }
- virtual const type::Type* selectFieldType(DTOType* self) = 0;
- };
- public:
- /**
- * Editional Info about Property.
- */
- struct Info {
- /**
- * Description.
- */
- std::string description = "";
- /**
- * Pattern.
- */
- std::string pattern = "";
- /**
- * Required.
- */
- bool required = false;
- /**
- * Type selector.
- * &l:Property::TypeSelector;.
- */
- TypeSelector* typeSelector = nullptr;
- };
- private:
- const v_int64 offset;
- public:
- /**
- * Constructor.
- * @param pOffset - memory offset of object field from object start address.
- * @param pName - name of the property.
- * @param pType - &l:Type; of the property.
- */
- Property(v_int64 pOffset, const char* pName, const Type* pType);
- /**
- * Property name.
- */
- const char* const name;
- /**
- * Property type.
- */
- const Type* const type;
- /**
- * Property additional info.
- */
- Info info;
- /**
- * Set value of object field mapped by this property.
- * @param object - object address.
- * @param value - value to set.
- */
- void set(BaseObject* object, const Void& value);
- /**
- * Get value of object field mapped by this property.
- * @param object - object address.
- * @return - value of the field.
- */
- Void get(BaseObject* object);
- /**
- * Get reference to ObjectWrapper of the object field.
- * @param object - object address.
- * @return - reference to ObjectWrapper of the object field.
- */
- Void& getAsRef(BaseObject* object);
- };
- /**
- * Object type properties table.
- */
- class Properties {
- private:
- std::unordered_map<std::string, Property*> m_map;
- std::list<Property*> m_list;
- public:
- /**
- * Add property to the end of the list.
- * @param property
- */
- Property* pushBack(Property* property);
- /**
- * Add all properties to the beginning of the list.
- * @param properties
- */
- void pushFrontAll(Properties* properties);
- /**
- * Get properties as unordered map for random access.
- * @return reference to std::unordered_map of std::string to &id:oatpp::data::mapping::type::BaseObject::Property;*.
- */
- const std::unordered_map<std::string, Property*>& getMap() const {
- return m_map;
- }
- /**
- * Get properties in ordered way.
- * @return std::list of &id:oatpp::data::mapping::type::BaseObject::Property;*.
- */
- const std::list<Property*>& getList() const {
- return m_list;
- }
- };
- private:
- void* m_basePointer = this;
- private:
- void set(v_int64 offset, const Void& value);
- Void get(v_int64 offset) const;
- Void& getAsRef(v_int64 offset) const;
- protected:
- void setBasePointer(void* basePointer);
- void* getBasePointer() const;
- };
- namespace __class {
- /**
- * AbstractObject class.
- */
- class AbstractObject {
- public:
- class PolymorphicDispatcher {
- public:
-
- virtual ~PolymorphicDispatcher() = default;
- virtual type::Void createObject() const = 0;
- virtual const type::BaseObject::Properties* getProperties() const = 0;
- };
- public:
- /**
- * Class id.
- */
- static const ClassId CLASS_ID;
- };
- /**
- * Template for Object class of type T.
- * @tparam T - object type.
- */
- template<class T>
- class Object : public AbstractObject {
- public:
- class PolymorphicDispatcher : public AbstractObject::PolymorphicDispatcher {
- public:
- type::Void createObject() const override {
- return type::Void(std::make_shared<T>(), getType());
- }
- const type::BaseObject::Properties* getProperties() const override {
- return propertiesGetter();
- }
- };
- private:
- static type::BaseObject::Properties* initProperties() {
- /* initializer */
- T obj;
- /* init parent properties */
- auto parentType = Object<typename T::Z__CLASS_EXTENDED>::getType();
- if(parentType->parent != nullptr) {
- auto dispatcher = static_cast<const AbstractObject::PolymorphicDispatcher*>(parentType->polymorphicDispatcher);
- dispatcher->getProperties();
- }
- /* extend parent properties */
- T::Z__CLASS_EXTEND(T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP(), T::Z__CLASS_EXTENDED::Z__CLASS_GET_FIELDS_MAP());
- return T::Z__CLASS::Z__CLASS_GET_FIELDS_MAP();
- }
- static const BaseObject::Properties* propertiesGetter() {
- static type::BaseObject::Properties* properties = initProperties();
- return properties;
- }
- static Type* createType() {
- Type::Info info;
- info.nameQualifier = T::Z__CLASS_TYPE_NAME();
- info.polymorphicDispatcher = new PolymorphicDispatcher();
- info.parent = T::getParentType();
- return new Type(CLASS_ID, info);
- }
- public:
- /**
- * Get type describing this class.
- * @return - &id:oatpp::data::mapping::type::Type;
- */
- static Type* getType() {
- static Type* type = createType();
- return type;
- }
-
- };
-
- }
- /**
- * ObjectWrapper for &l:DTO;. AKA `oatpp::Object<T>`.
- * @tparam ObjT - class extended from &l:DTO;.
- */
- template<class ObjT>
- class DTOWrapper : public ObjectWrapper<ObjT, __class::Object<ObjT>> {
- template<class Type>
- friend class DTOWrapper;
- public:
- typedef ObjT TemplateObjectType;
- typedef __class::Object<ObjT> TemplateObjectClass;
- public:
- OATPP_DEFINE_OBJECT_WRAPPER_DEFAULTS(DTOWrapper, TemplateObjectType, TemplateObjectClass)
- template<class OtherT>
- DTOWrapper(const OtherT& other)
- : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(other.m_ptr)
- {}
- template<class OtherT>
- DTOWrapper(OtherT&& other)
- : type::ObjectWrapper<ObjT, __class::Object<ObjT>>(std::move(other.m_ptr))
- {}
- static DTOWrapper createShared() {
- return std::make_shared<TemplateObjectType>();
- }
- template<class T>
- DTOWrapper& operator = (const DTOWrapper<T>& other) {
- this->m_ptr = other.m_ptr;
- return *this;
- }
- template<class T>
- DTOWrapper& operator = (DTOWrapper<T>&& other) {
- this->m_ptr = std::move(other.m_ptr);
- return *this;
- }
- template<typename T,
- typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
- >
- inline bool operator == (T){
- return this->m_ptr.get() == nullptr;
- }
- template<typename T,
- typename enabled = typename std::enable_if<std::is_same<T, std::nullptr_t>::value, void>::type
- >
- inline bool operator != (T){
- return this->m_ptr.get() != nullptr;
- }
- template<typename T,
- typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
- >
- inline bool operator == (const T &other) const {
- if(this->m_ptr.get() == other.m_ptr.get()) return true;
- if(!this->m_ptr || !other.m_ptr) return false;
- return *this->m_ptr == *other.m_ptr;
- }
- template<typename T,
- typename enabled = typename std::enable_if<std::is_same<T, DTOWrapper>::value, void>::type
- >
- inline bool operator != (const T &other) const {
- return !operator == (other);
- }
- static const std::unordered_map<std::string, BaseObject::Property*>& getPropertiesMap() {
- auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
- __class::Object<ObjT>::getType()->polymorphicDispatcher
- );
- return dispatcher->getProperties()->getMap();
- }
- static const std::list<BaseObject::Property*>& getPropertiesList() {
- auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
- __class::Object<ObjT>::getType()->polymorphicDispatcher
- );
- return dispatcher->getProperties()->getList();
- }
- static v_int64 getPropertiesCount() {
- auto dispatcher = static_cast<const __class::AbstractObject::PolymorphicDispatcher*>(
- __class::Object<ObjT>::getType()->polymorphicDispatcher
- );
- return dispatcher->getProperties()->getList().size();
- }
- ObjectWrapper<void>& operator[](const std::string& propertyName) {
- return getPropertiesMap().at(propertyName)->getAsRef(this->m_ptr.get());
- }
- };
- /**
- * Base class for all DTO objects.
- * For more info about Data Transfer Object (DTO) see [Data Transfer Object (DTO)](https://oatpp.io/docs/components/dto/).
- */
- class DTO : public BaseObject {
- template<class T>
- friend class __class::Object;
- private:
- typedef DTO Z__CLASS;
- typedef DTO Z__CLASS_EXTENDED;
- public:
- typedef oatpp::data::mapping::type::Void Void;
- typedef oatpp::data::mapping::type::Any Any;
- typedef oatpp::data::mapping::type::String String;
- typedef oatpp::data::mapping::type::Int8 Int8;
- typedef oatpp::data::mapping::type::UInt8 UInt8;
- typedef oatpp::data::mapping::type::Int16 Int16;
- typedef oatpp::data::mapping::type::UInt16 UInt16;
- typedef oatpp::data::mapping::type::Int32 Int32;
- typedef oatpp::data::mapping::type::UInt32 UInt32;
- typedef oatpp::data::mapping::type::Int64 Int64;
- typedef oatpp::data::mapping::type::UInt64 UInt64;
- typedef oatpp::data::mapping::type::Float32 Float32;
- typedef oatpp::data::mapping::type::Float64 Float64;
- typedef oatpp::data::mapping::type::Boolean Boolean;
- template <class T>
- using Object = DTOWrapper<T>;
- template <class T>
- using Enum = oatpp::data::mapping::type::Enum<T>;
- template <class T>
- using Vector = oatpp::data::mapping::type::Vector<T>;
- template <class T>
- using UnorderedSet = oatpp::data::mapping::type::UnorderedSet<T>;
- template <class T>
- using List = oatpp::data::mapping::type::List<T>;
- template <class Value>
- using Fields = oatpp::data::mapping::type::PairList<String, Value>;
- template <class Value>
- using UnorderedFields = oatpp::data::mapping::type::UnorderedMap<String, Value>;
- private:
- static const mapping::type::Type* getParentType();
- static const char* Z__CLASS_TYPE_NAME();
- static data::mapping::type::BaseObject::Properties* Z__CLASS_GET_FIELDS_MAP();
- static BaseObject::Properties* Z__CLASS_EXTEND(BaseObject::Properties* properties, BaseObject::Properties* extensionProperties);
- public:
- virtual v_uint64 defaultHashCode() const {
- return (v_uint64) reinterpret_cast<v_buff_usize>(this);
- }
- virtual bool defaultEquals(const DTO& other) const {
- return this == &other;
- }
- v_uint64 hashCode() const {
- return defaultHashCode();
- }
- bool operator==(const DTO& other) const {
- return defaultEquals(other);
- }
- };
-
- }}}}
- namespace std {
- template<class T>
- struct hash<oatpp::data::mapping::type::DTOWrapper<T>> {
- typedef oatpp::data::mapping::type::DTOWrapper<T> argument_type;
- typedef v_uint64 result_type;
- result_type operator()(argument_type const &ow) const noexcept {
- if(ow) {
- return ow->hashCode();
- }
- return 0;
- }
- };
- }
- #endif /* oatpp_data_type_Object_hpp */
|