mapping::type: Better containers hierarchy

This commit is contained in:
lganzzzo 2021-11-07 02:42:05 +02:00
parent 11e80b8a4a
commit 512769c5ce
29 changed files with 762 additions and 347 deletions

View File

@ -82,10 +82,12 @@ add_library(oatpp
oatpp/core/data/mapping/TypeResolver.hpp
oatpp/core/data/mapping/type/Any.cpp
oatpp/core/data/mapping/type/Any.hpp
oatpp/core/data/mapping/type/Collection.hpp
oatpp/core/data/mapping/type/Enum.cpp
oatpp/core/data/mapping/type/Enum.hpp
oatpp/core/data/mapping/type/List.cpp
oatpp/core/data/mapping/type/List.hpp
oatpp/core/data/mapping/type/Map.hpp
oatpp/core/data/mapping/type/PairList.cpp
oatpp/core/data/mapping/type/PairList.hpp
oatpp/core/data/mapping/type/Object.cpp

View File

@ -187,7 +187,7 @@ namespace oatpp {
/**
* Abstract Fields
*/
typedef data::mapping::type::PairListObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractPairList> AbstractFields;
typedef Fields<oatpp::Void> AbstractFields;
/**
* Mapping-Enabled UnorderedMap<Key, Value>. &id:oatpp::data::mapping::type::UnorderedMap;.
@ -204,7 +204,7 @@ namespace oatpp {
/**
* Abstract UnorderedFields
*/
typedef data::mapping::type::UnorderedMapObjectWrapper<oatpp::String, oatpp::Void, data::mapping::type::__class::AbstractUnorderedMap> AbstractUnorderedFields;
typedef UnorderedFields<oatpp::Void> AbstractUnorderedFields;
}

View File

@ -68,13 +68,13 @@ public:
"Error. Data not found for key '" + *key + "'.");
}
if(it->second.getValueType() != WrapperType::Class::getType()) {
if(!WrapperType::Class::getType()->extends(it->second.getValueType())) {
throw std::runtime_error("[oatpp::data::Bundle::get()]: Error. Type mismatch for key '" + *key +
"'. Stored '" +
std::string(it->second.getValueType()->classId.name) +
"' vs requested '" + std::string(WrapperType::Class::getType()->classId.name) + "'.");
}
return it->second.template staticCast<WrapperType>();
return it->second.template cast<WrapperType>();
}
/**

View File

@ -110,7 +110,7 @@ public:
template<class Wrapper>
Wrapper readFromCaret(oatpp::parser::Caret& caret) const {
auto type = Wrapper::Class::getType();
return read(caret, type).template staticCast<Wrapper>();
return read(caret, type).template cast<Wrapper>();
}
/**
@ -125,7 +125,7 @@ public:
Wrapper readFromString(const oatpp::String& str) const {
auto type = Wrapper::Class::getType();
oatpp::parser::Caret caret(str);
auto result = read(caret, type).template staticCast<Wrapper>();
auto result = read(caret, type).template cast<Wrapper>();
if(!result) {
throw oatpp::parser::ParsingError(caret.getErrorMessage(), caret.getErrorCode(), caret.getPosition());
}

View File

@ -0,0 +1,189 @@
/***************************************************************************
*
* 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_mapping_type_Collection_hpp
#define oatpp_data_mapping_type_Collection_hpp
#include "./Type.hpp"
#include <unordered_set>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
/**
* Abstract Collection. <br>
* Ex.: Vector, List, Set.
*/
class Collection {
public:
/**
* Iterator.
*/
struct Iterator {
/**
* Default virtual destructor.
*/
virtual ~Iterator() = default;
/**
* Get current item.
* @return
*/
virtual type::Void get() = 0;
/**
* Iterate to next item.
*/
virtual void next() = 0;
/**
* Check if iterator finished.
* @return
*/
virtual bool finished() = 0;
};
public:
/**
* Polymorphic Dispatcher
*/
class PolymorphicDispatcher {
public:
/**
* Virtual destructor.
*/
virtual ~PolymorphicDispatcher() = default;
/**
* Create Collection.
* @return
*/
virtual type::Void createObject() const = 0;
/**
* Get type of collection items.
* @return
*/
virtual const type::Type* getItemType() const = 0;
/**
* Add item.
* @param object - Collection.
* @param item - Item to add.
*/
virtual void addItem(const type::Void& object, const type::Void& item) const = 0;
/**
* Begin collection iteration.
* @param object - Collection.
* @return
*/
virtual std::unique_ptr<Iterator> beginIteration(const type::Void& object) const = 0;
};
template<class ContainerType, class ItemType>
struct Inserter {
static void insert(ContainerType* c, const ItemType& i) {
c->emplace_back(i);
}
};
};
template<class ContainerType, class ItemType, class Clazz>
class StandardCollection {
public:
struct Iterator : public Collection::Iterator {
typename ContainerType::iterator iterator;
typename ContainerType::iterator end;
type::Void get() override {
return *iterator;
}
void next() override {
std::advance(iterator, 1);
}
bool finished() override {
return iterator == end;
}
};
public:
class PolymorphicDispatcher : public Collection::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<ContainerType>(), Clazz::getType());
}
const type::Type* getItemType() const override {
const type::Type* collectionType = Clazz::getType();
return collectionType->params[0];
}
void addItem(const type::Void& object, const type::Void& item) const override {
ContainerType* collection = static_cast<ContainerType*>(object.get());
const auto& collectionItem = item.template cast<ItemType>();
Collection::Inserter<ContainerType, ItemType>::insert(collection, collectionItem);
}
std::unique_ptr<Collection::Iterator> beginIteration(const type::Void& object) const override {
ContainerType* collection = static_cast<ContainerType*>(object.get());
auto iterator = new Iterator();
iterator->iterator = collection->begin();
iterator->end = collection->end();
return std::unique_ptr<Collection::Iterator>(iterator);
}
};
};
template<class ItemType>
struct Collection::Inserter<std::unordered_set<ItemType>, ItemType> {
static void insert(std::unordered_set<ItemType>* c, const ItemType& i) {
c->template emplace(i);
}
};
}
}}}}
#endif //oatpp_data_mapping_type_Collection_hpp

View File

@ -472,7 +472,7 @@ Void EnumInterpreterAsString<T, notnull>::toInterpretation(const Void& enumValue
return Void(nullptr, String::Class::getType());
}
const auto& ow = enumValue.staticCast<EnumOW>();
const auto& ow = enumValue.template cast<EnumOW>();
const auto& entry = EnumOW::getEntryByValue(*ow);
return entry.name.toString();
}
@ -495,7 +495,7 @@ Void EnumInterpreterAsString<T, notnull>::fromInterpretation(const Void& interVa
}
try {
const auto &entry = EnumOW::getEntryByName(interValue.staticCast<String>());
const auto &entry = EnumOW::getEntryByName(interValue.template cast<String>());
return EnumOW(entry.value);
} catch (const std::runtime_error&) { // TODO - add a specific error for this.
error = EnumInterpreterError::ENTRY_NOT_FOUND;
@ -528,7 +528,7 @@ Void EnumInterpreterAsNumber<T, notnull>::toInterpretation(const Void& enumValue
return Void(nullptr, UTOW::Class::getType());
}
const auto& ow = enumValue.staticCast<EnumOW>();
const auto& ow = enumValue.template cast<EnumOW>();
return UTOW(static_cast<EnumUT>(*ow));
}
@ -555,7 +555,7 @@ Void EnumInterpreterAsNumber<T, notnull>::fromInterpretation(const Void& interVa
try{
const auto& entry = EnumOW::getEntryByUnderlyingValue(
interValue.staticCast<OW>()
interValue.template cast<OW>()
);
return EnumOW(entry.value);
} catch (const std::runtime_error&) { // TODO - add a specific error for this.

View File

@ -25,6 +25,7 @@
#ifndef oatpp_data_mapping_type_List_hpp
#define oatpp_data_mapping_type_List_hpp
#include "./Collection.hpp"
#include "./Type.hpp"
#include <list>
@ -39,29 +40,11 @@ namespace __class {
*/
class AbstractList {
public:
/**
* Class Id.
*/
static const ClassId CLASS_ID;
public:
/**
* Polymorphic Dispatcher
*/
class PolymorphicDispatcher {
public:
virtual ~PolymorphicDispatcher() = default;
virtual type::Void createObject() const = 0;
/**
* Add item.
* @param object - List to add item to.
* @param item - Item to add.
*/
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
@ -115,35 +98,19 @@ public:
template<class T>
using List = ListObjectWrapper<T, __class::List<T>>;
typedef ListObjectWrapper<type::Void, __class::AbstractList> AbstractList;
typedef List<Void> AbstractList;
namespace __class {
template<class T>
class List : public AbstractList {
public:
class PolymorphicDispatcher : public AbstractList::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<std::list<T>>(), getType());
}
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& list = object.staticCast<type::List<T>>();
const auto& listItem = item.staticCast<T>();
list->push_back(listItem);
}
};
private:
static Type createType() {
Type::Info info;
info.params.push_back(T::Class::getType());
info.polymorphicDispatcher = new PolymorphicDispatcher();
info.polymorphicDispatcher = new typename StandardCollection<std::list<T>, T, List>::PolymorphicDispatcher();
info.isCollection = true;
return Type(__class::AbstractList::CLASS_ID, info);
}

View File

@ -0,0 +1,212 @@
/***************************************************************************
*
* 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_mapping_type_Map_hpp
#define oatpp_data_mapping_type_Map_hpp
#include "./Type.hpp"
#include <list>
namespace oatpp { namespace data { namespace mapping { namespace type {
namespace __class {
/**
* Abstract Map. <br>
* Ex.: UnorderedMap, Fields.
*/
class Map {
public:
/**
* Iterator.
*/
struct Iterator {
/**
* Default virtual destructor.
*/
virtual ~Iterator() = default;
/**
* Get current item key.
* @return
*/
virtual type::Void getKey() = 0;
/**
* Get current item value.
* @return
*/
virtual type::Void getValue() = 0;
/**
* Iterate to next item.
*/
virtual void next() = 0;
/**
* Check if iterator finished.
* @return
*/
virtual bool finished() = 0;
};
public:
/**
* Polymorphic Dispatcher
*/
class PolymorphicDispatcher {
public:
/**
* Virtual destructor.
*/
virtual ~PolymorphicDispatcher() = default;
/**
* Create Map.
* @return
*/
virtual type::Void createObject() const = 0;
/**
* Get type of map keys.
* @return
*/
virtual const type::Type* getKeyType() const = 0;
/**
* Get type of map values.
* @return
*/
virtual const type::Type* getValueType() const = 0;
/**
* Add item.
* @param object - Map.
* @param key
* @param value
*/
virtual void addItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
/**
* Begin map iteration.
* @param object - Map.
* @return
*/
virtual std::unique_ptr<Iterator> beginIteration(const type::Void& object) const = 0;
};
template<class ContainerType, class KeyType, class ValueType>
struct Inserter {
static void insert(ContainerType* c, const KeyType& k, const ValueType& v) {
(*c)[k] = v;
}
};
};
template<class ContainerType, class KeyType, class ValueType, class Clazz>
class StandardMap {
public:
struct Iterator : public Map::Iterator {
typename ContainerType::iterator iterator;
typename ContainerType::iterator end;
type::Void getKey() override {
return iterator->first;
}
type::Void getValue() override {
return iterator->second;
}
void next() override {
std::advance(iterator, 1);
}
bool finished() override {
return iterator == end;
}
};
public:
class PolymorphicDispatcher : public Map::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<ContainerType>(), Clazz::getType());
}
const type::Type* getKeyType() const override {
const type::Type* mapType = Clazz::getType();
return mapType->params[0];
}
const type::Type* getValueType() const override {
const type::Type* mapType = Clazz::getType();
return mapType->params[1];
}
void addItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
ContainerType* map = static_cast<ContainerType*>(object.get());
const auto& mapKey = key.template cast<KeyType>();
const auto& mapValue = value.template cast<ValueType>();
Map::Inserter<ContainerType, KeyType, ValueType>::insert(map, mapKey, mapValue);
}
std::unique_ptr<Map::Iterator> beginIteration(const type::Void& object) const override {
ContainerType* map = static_cast<ContainerType*>(object.get());
auto iterator = new Iterator();
iterator->iterator = map->begin();
iterator->end = map->end();
return std::unique_ptr<Map::Iterator>(iterator);
}
};
};
template<class KeyType, class ValueType>
struct Map::Inserter<std::list<std::pair<KeyType, ValueType>>, KeyType, ValueType> {
static void insert(std::list<std::pair<KeyType, ValueType>>* c, const KeyType& k, const ValueType& v) {
c->push_back({k, v});
}
};
}
}}}}
#endif //oatpp_data_mapping_type_Map_hpp

View File

@ -25,6 +25,7 @@
#ifndef oatpp_data_mapping_type_PairList_hpp
#define oatpp_data_mapping_type_PairList_hpp
#include "./Map.hpp"
#include "./Type.hpp"
#include <list>
@ -44,27 +45,6 @@ namespace __class {
* Class id.
*/
static const ClassId CLASS_ID;
public:
/**
* Polymorphic Dispatcher.
*/
class PolymorphicDispatcher {
public:
virtual ~PolymorphicDispatcher() = default;
virtual type::Void createObject() const = 0;
/**
* Add key-value pair to pair-list.
* @param object - pair list.
* @param key - key.
* @param value - value.
*/
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
};
};
template<class Key, class Value>
@ -147,31 +127,15 @@ namespace __class {
template<class Key, class Value>
class PairList : public AbstractPairList {
public:
class PolymorphicDispatcher : public AbstractPairList::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<std::list<std::pair<Key, Value>>>(), getType());
}
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
const auto& map = object.staticCast<type::PairList<Key, Value>>();
const auto& k = key.staticCast<Key>();
const auto& v = value.staticCast<Value>();
map->push_back({k, v});
}
};
private:
static Type createType() {
Type::Info info;
info.params.push_back(Key::Class::getType());
info.params.push_back(Value::Class::getType());
info.polymorphicDispatcher = new PolymorphicDispatcher();
info.polymorphicDispatcher = info.polymorphicDispatcher =
new typename __class::StandardMap<std::list<std::pair<Key, Value>>, Key, Value, PairList>::PolymorphicDispatcher();
info.isMap = true;
return Type(__class::AbstractPairList::CLASS_ID, info);
}

View File

@ -81,6 +81,8 @@ Type::Type(const ClassId& pClassId, const Info& typeInfo)
, polymorphicDispatcher(typeInfo.polymorphicDispatcher)
, interpretationMap(typeInfo.interpretationMap)
, parent(typeInfo.parent)
, isCollection(typeInfo.isCollection)
, isMap(typeInfo.isMap)
{}
const Type::AbstractInterpretation* Type::findInterpretation(const std::vector<std::string>& names) const {

View File

@ -217,9 +217,7 @@ public:
}
template<class Wrapper>
Wrapper staticCast() const {
return Wrapper(std::static_pointer_cast<typename Wrapper::ObjectType>(m_ptr), m_valueType);
}
Wrapper cast() const;
inline T* operator->() const {
return m_ptr.operator->();
@ -413,11 +411,11 @@ public:
public:
Void toInterpretation(const Void& originalValue) const override {
return interpret(originalValue.staticCast<OriginalWrapper>());
return interpret(originalValue.template cast<OriginalWrapper>());
}
Void fromInterpretation(const Void& interValue) const override {
return reproduce(interValue.staticCast<InterWrapper>());
return reproduce(interValue.template cast<InterWrapper>());
}
const Type* getInterpretationType() const override {
@ -472,6 +470,16 @@ public:
* statically casted to parent type without any violations.
*/
const Type* parent = nullptr;
/**
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher;.
*/
bool isCollection = false;
/**
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher;.
*/
bool isMap = false;
};
public:
@ -516,6 +524,16 @@ public:
*/
const Type* const parent;
/**
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher;.
*/
const bool isCollection;
/**
* polymorphicDispatcher extends &id:oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher;.
*/
const bool isMap;
public:
/**
@ -535,6 +553,19 @@ public:
};
template <class T, class Clazz>
template<class Wrapper>
Wrapper ObjectWrapper<T, Clazz>::cast() const {
if(!Wrapper::Class::getType()->extends(m_valueType)) {
if(Wrapper::Class::getType() != __class::Void::getType() && m_valueType != __class::Void::getType()) {
throw std::runtime_error("[oatpp::data::mapping::type::ObjectWrapper::cast()]: Error. Invalid cast "
"from '" + std::string(m_valueType->classId.name) + "' to '" +
std::string(Wrapper::Class::getType()->classId.name) + "'.");
}
}
return Wrapper(std::static_pointer_cast<typename Wrapper::ObjectType>(m_ptr), Wrapper::Class::getType());
}
template <class T, class Clazz>
void ObjectWrapper<T, Clazz>::checkType(const Type* _this, const Type* other) {
if(!_this->extends(other)) {

View File

@ -25,6 +25,7 @@
#ifndef oatpp_data_mapping_type_UnorderedMap_hpp
#define oatpp_data_mapping_type_UnorderedMap_hpp
#include "./Map.hpp"
#include "./Type.hpp"
#include <unordered_map>
@ -44,27 +45,6 @@ namespace __class {
* Class Id.
*/
static const ClassId CLASS_ID;
public:
/**
* Polymorphic Dispatcher.
*/
class PolymorphicDispatcher {
public:
virtual ~PolymorphicDispatcher() = default;
virtual type::Void createObject() const = 0;
/**
* Add item.
* @param object - Unordered Map.
* @param key - Key.
* @param value - Value.
*/
virtual void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const = 0;
};
};
template<class Key, class Value>
@ -120,31 +100,15 @@ namespace __class {
template<class Key, class Value>
class UnorderedMap : public AbstractUnorderedMap {
public:
class PolymorphicDispatcher : public AbstractUnorderedMap::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<std::unordered_map<Key, Value>>(), getType());
}
void addPolymorphicItem(const type::Void& object, const type::Void& key, const type::Void& value) const override {
const auto& map = object.staticCast<type::UnorderedMap<Key, Value>>();
const auto& k = key.staticCast<Key>();
const auto& v = value.staticCast<Value>();
map[k] = v;
}
};
private:
static Type createType() {
Type::Info info;
info.params.push_back(Key::Class::getType());
info.params.push_back(Value::Class::getType());
info.polymorphicDispatcher = new PolymorphicDispatcher();
info.polymorphicDispatcher =
new typename __class::StandardMap<std::unordered_map<Key, Value>, Key, Value, UnorderedMap>::PolymorphicDispatcher();
info.isMap = true;
return Type(__class::AbstractUnorderedMap::CLASS_ID, info);
}

View File

@ -25,6 +25,7 @@
#ifndef oatpp_data_mapping_type_UnorderedSet_hpp
#define oatpp_data_mapping_type_UnorderedSet_hpp
#include "./Collection.hpp"
#include "./Type.hpp"
#include <unordered_set>
@ -43,26 +44,6 @@ namespace __class {
* Class Id.
*/
static const ClassId CLASS_ID;
public:
/**
* Polymorphic Dispatcher.
*/
class PolymorphicDispatcher {
public:
virtual ~PolymorphicDispatcher() = default;
virtual type::Void createObject() const = 0;
/**
* Add Item.
* @param object - UnorderedSet.
* @param item - Item.
*/
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
template<class T>
@ -117,35 +98,19 @@ public:
template<class T>
using UnorderedSet = UnorderedSetObjectWrapper<T, __class::UnorderedSet<T>>;
typedef UnorderedSetObjectWrapper<type::Void, __class::AbstractUnorderedSet> AbstractUnorderedSet;
typedef UnorderedSet<Void> AbstractUnorderedSet;
namespace __class {
template<class T>
class UnorderedSet : public AbstractUnorderedSet {
public:
class PolymorphicDispatcher : public AbstractUnorderedSet::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<std::unordered_set<T>>(), getType());
}
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& set = object.staticCast<type::UnorderedSet<T>>();
const auto& setItem = item.staticCast<T>();
set->insert(setItem);
}
};
private:
static Type createType() {
Type::Info info;
info.params.push_back(T::Class::getType());
info.polymorphicDispatcher = new PolymorphicDispatcher();
info.polymorphicDispatcher = new typename StandardCollection<std::unordered_set<T>, T, UnorderedSet>::PolymorphicDispatcher();
info.isCollection = true;
return Type(__class::AbstractUnorderedSet::CLASS_ID, info);
}

View File

@ -25,6 +25,7 @@
#ifndef oatpp_data_mapping_type_Vector_hpp
#define oatpp_data_mapping_type_Vector_hpp
#include "./Collection.hpp"
#include "./Type.hpp"
#include <vector>
@ -43,26 +44,6 @@ namespace __class {
* Class Id.
*/
static const ClassId CLASS_ID;
public:
/**
* Polymorphic Dispatcher.
*/
class PolymorphicDispatcher {
public:
virtual ~PolymorphicDispatcher() = default;
virtual type::Void createObject() const = 0;
/**
* Add Item.
* @param object - Vector.
* @param item - Item to add.
*/
virtual void addPolymorphicItem(const type::Void& object, const type::Void& item) const = 0;
};
};
template<class T>
@ -113,35 +94,19 @@ public:
template<class T>
using Vector = VectorObjectWrapper<T, __class::Vector<T>>;
typedef VectorObjectWrapper<type::Void, __class::AbstractVector> AbstractVector;
typedef Vector<Void> AbstractVector;
namespace __class {
template<class T>
class Vector : public AbstractVector {
public:
class PolymorphicDispatcher : public AbstractVector::PolymorphicDispatcher {
public:
type::Void createObject() const override {
return type::Void(std::make_shared<std::vector<T>>(), getType());
}
void addPolymorphicItem(const type::Void& object, const type::Void& item) const override {
const auto& vector = object.staticCast<type::Vector<T>>();
const auto& vectorItem = item.staticCast<T>();
vector->push_back(vectorItem);
}
};
private:
static Type createType() {
Type::Info info;
info.params.push_back(T::Class::getType());
info.polymorphicDispatcher = new PolymorphicDispatcher();
info.polymorphicDispatcher = new typename StandardCollection<std::vector<T>, T, Vector>::PolymorphicDispatcher();
info.isCollection = true;
return Type(__class::AbstractVector::CLASS_ID, info);
}

View File

@ -56,12 +56,12 @@ Deserializer::Deserializer(const std::shared_ptr<Config>& config)
setDeserializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Deserializer::deserializeObject);
setDeserializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Deserializer::deserializeEnum);
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractVector>);
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractList>);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeList<oatpp::AbstractUnorderedSet>);
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeCollection);
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractFields>);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeKeyValue<oatpp::AbstractUnorderedFields>);
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Deserializer::deserializeMap);
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Deserializer::deserializeMap);
}
@ -287,6 +287,115 @@ oatpp::Void Deserializer::deserializeEnum(Deserializer* deserializer, parser::Ca
}
oatpp::Void Deserializer::deserializeCollection(Deserializer* deserializer, parser::Caret& caret, const Type* type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('[', 1)) {
auto dispatcher = static_cast<const data::mapping::type::__class::Collection::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto collection = dispatcher->createObject();
auto itemType = dispatcher->getItemType();
caret.skipBlankChars();
while(!caret.isAtChar(']') && caret.canContinue()){
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, itemType);
if(caret.hasError()){
return nullptr;
}
dispatcher->addItem(collection, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar(']', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeCollection()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
}
return nullptr;
};
return collection;
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeCollection()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
return nullptr;
}
}
oatpp::Void Deserializer::deserializeMap(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('{', 1)) {
auto dispatcher = static_cast<const data::mapping::type::__class::Map::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto map = dispatcher->createObject();
auto keyType = dispatcher->getKeyType();
if(keyType->classId != oatpp::String::Class::CLASS_ID){
throw std::runtime_error("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Invalid json map key. Key should be String");
}
auto valueType = dispatcher->getValueType();
caret.skipBlankChars();
while (!caret.isAtChar('}') && caret.canContinue()) {
caret.skipBlankChars();
auto key = Utils::parseString(caret);
if(caret.hasError()){
return nullptr;
}
caret.skipBlankChars();
if(!caret.canContinueAtChar(':', 1)){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. ':' - expected", ERROR_CODE_OBJECT_SCOPE_COLON_MISSING);
return nullptr;
}
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, valueType);
if(caret.hasError()){
return nullptr;
}
dispatcher->addItem(map, key, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar('}', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. '}' - expected", ERROR_CODE_OBJECT_SCOPE_CLOSE);
}
return nullptr;
}
return map;
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeMap()]: Error. '{' - expected", ERROR_CODE_OBJECT_SCOPE_OPEN);
}
return nullptr;
}
oatpp::Void Deserializer::deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){

View File

@ -163,53 +163,6 @@ private:
}
template<class Collection>
static oatpp::Void deserializeList(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
if(caret.isAtText("null", true)){
return oatpp::Void(type);
}
if(caret.canContinueAtChar('[', 1)) {
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto listWrapper = polymorphicDispatcher->createObject();
const auto& list = listWrapper.template staticCast<Collection>();
auto itemType = *type->params.begin();
caret.skipBlankChars();
while(!caret.isAtChar(']') && caret.canContinue()){
caret.skipBlankChars();
auto item = deserializer->deserialize(caret, itemType);
if(caret.hasError()){
return nullptr;
}
polymorphicDispatcher->addPolymorphicItem(listWrapper, item);
caret.skipBlankChars();
caret.canContinueAtChar(',', 1);
}
if(!caret.canContinueAtChar(']', 1)){
if(!caret.hasError()){
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. ']' - expected", ERROR_CODE_ARRAY_SCOPE_CLOSE);
}
return nullptr;
};
return oatpp::Void(list.getPtr(), list.getValueType());
} else {
caret.setError("[oatpp::parser::json::mapping::Deserializer::deserializeList()]: Error. '[' - expected", ERROR_CODE_ARRAY_SCOPE_OPEN);
return nullptr;
}
}
template<class Collection>
static oatpp::Void deserializeKeyValue(Deserializer* deserializer, parser::Caret& caret, const Type* const type) {
@ -221,7 +174,7 @@ private:
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
auto mapWrapper = polymorphicDispatcher->createObject();
const auto& map = mapWrapper.template staticCast<Collection>();
const auto& map = mapWrapper.template cast<Collection>();
auto it = type->params.begin();
auto keyType = *it ++;
@ -282,6 +235,10 @@ private:
static oatpp::Void deserializeString(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeAny(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeEnum(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeCollection(Deserializer* deserializer, parser::Caret& caret, const Type* type);
static oatpp::Void deserializeMap(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
static oatpp::Void deserializeObject(Deserializer* deserializer, parser::Caret& caret, const Type* const type);
private:

View File

@ -57,12 +57,12 @@ Serializer::Serializer(const std::shared_ptr<Config>& config)
setSerializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, &Serializer::serializeObject);
setSerializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::serializeEnum);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeList<oatpp::AbstractVector>);
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeList<oatpp::AbstractList>);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeList<oatpp::AbstractUnorderedSet>);
setSerializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeCollection);
setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeKeyValue<oatpp::AbstractFields>);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeKeyValue<oatpp::AbstractUnorderedFields>);
setSerializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, &Serializer::serializeMap);
setSerializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, &Serializer::serializeMap);
}
@ -136,6 +136,79 @@ void Serializer::serializeEnum(Serializer* serializer,
}
void Serializer::serializeCollection(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
auto dispatcher = static_cast<const data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);
stream->writeCharSimple('[');
bool first = true;
auto iterator = dispatcher->beginIteration(polymorph);
while (!iterator->finished()) {
const auto& value = iterator->get();
if(value || serializer->getConfig()->includeNullFields || serializer->getConfig()->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
serializer->serialize(stream, value);
}
iterator->next();
}
stream->writeCharSimple(']');
}
void Serializer::serializeMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)
{
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
auto dispatcher = static_cast<const data::mapping::type::__class::Map::PolymorphicDispatcher*>(
polymorph.getValueType()->polymorphicDispatcher
);
auto keyType = dispatcher->getKeyType();
if(keyType->classId != oatpp::String::Class::CLASS_ID){
throw std::runtime_error("[oatpp::parser::json::mapping::Serializer::serializeMap()]: Invalid json map key. Key should be String");
}
stream->writeCharSimple('{');
bool first = true;
auto iterator = dispatcher->beginIteration(polymorph);
while (!iterator->finished()) {
const auto& value = iterator->getValue();
if(value || serializer->m_config->includeNullFields || serializer->m_config->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
const auto& untypedKey = iterator->getKey();
const auto& key = oatpp::String(std::static_pointer_cast<std::string>(untypedKey.getPtr()));
serializeString(stream, key->data(), key->size(), serializer->m_config->escapeFlags);
stream->writeSimple(":", 1);
serializer->serialize(stream, value);
}
iterator->next();
}
stream->writeCharSimple('}');
}
void Serializer::serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph)

View File

@ -132,58 +132,6 @@ private:
stream->writeSimple("null", 4);
}
}
template<class Collection>
static void serializeList(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
const auto& list = polymorph.staticCast<Collection>();
stream->writeCharSimple('[');
bool first = true;
for(auto& value : *list) {
if(value || serializer->getConfig()->includeNullFields || serializer->getConfig()->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
serializer->serialize(stream, value);
}
}
stream->writeCharSimple(']');
}
template<class Collection>
static void serializeKeyValue(Serializer* serializer, data::stream::ConsistentOutputStream* stream, const oatpp::Void& polymorph) {
if(!polymorph) {
stream->writeSimple("null", 4);
return;
}
const auto& map = polymorph.staticCast<Collection>();
stream->writeCharSimple('{');
bool first = true;
for(auto& pair : *map) {
const auto& value = pair.second;
if(value || serializer->m_config->includeNullFields || serializer->m_config->alwaysIncludeNullCollectionElements) {
(first) ? first = false : stream->writeSimple(",", 1);
const auto& key = pair.first;
serializeString(stream, key->data(), key->size(), serializer->m_config->escapeFlags);
stream->writeSimple(":", 1);
serializer->serialize(stream, value);
}
}
stream->writeCharSimple('}');
}
static void serializeString(oatpp::data::stream::ConsistentOutputStream* stream,
const char* data,
@ -202,6 +150,14 @@ private:
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeCollection(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeMap(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);
static void serializeObject(Serializer* serializer,
data::stream::ConsistentOutputStream* stream,
const oatpp::Void& polymorph);

View File

@ -391,7 +391,7 @@ struct ApiClient::TypeInterpretation<data::mapping::type::EnumObjectWrapper<T, I
);
}
return ApiClient::TypeInterpretation<UTOW>::toString(typeName, value.template staticCast<UTOW>());
return ApiClient::TypeInterpretation<UTOW>::toString(typeName, value.template cast<UTOW>());
}

View File

@ -562,7 +562,7 @@ struct ApiController::TypeInterpretation <data::mapping::type::EnumObjectWrapper
data::mapping::type::EnumInterpreterError error = data::mapping::type::EnumInterpreterError::OK;
const auto& result = I::fromInterpretation(parsedValue, error);
if(error == data::mapping::type::EnumInterpreterError::OK) {
return result.template staticCast<EnumOW>();
return result.template cast<EnumOW>();
}
success = false;
}

View File

@ -169,14 +169,14 @@ void EnumTest::onRun() {
OATPP_ASSERT(inter.getValueType() == oatpp::String::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto interValue = inter.staticCast<oatpp::String>();
auto interValue = inter.cast<oatpp::String>();
OATPP_ASSERT(interValue == "name-1");
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsString::Interpreter::fromInterpretation(interValue, e);
OATPP_ASSERT(voidValue.getValueType() == oatpp::Enum<Enum2>::AsString::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsString>();
auto value = voidValue.cast<oatpp::Enum<Enum2>::AsString>();
OATPP_ASSERT(value == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}
@ -188,14 +188,14 @@ void EnumTest::onRun() {
OATPP_ASSERT(inter.getValueType() == oatpp::Int32::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto interValue = inter.staticCast<oatpp::Int32>();
auto interValue = inter.cast<oatpp::Int32>();
OATPP_ASSERT(interValue == static_cast<v_int32>(Enum2::NAME_1));
oatpp::Void voidValue = oatpp::Enum<Enum2>::AsNumber::Interpreter::fromInterpretation(interValue, e);
OATPP_ASSERT(voidValue.getValueType() == oatpp::Enum<Enum2>::AsNumber::Class::getType());
OATPP_ASSERT(e == oatpp::data::mapping::type::EnumInterpreterError::OK);
auto value = voidValue.staticCast<oatpp::Enum<Enum2>::AsNumber>();
auto value = voidValue.cast<oatpp::Enum<Enum2>::AsNumber>();
OATPP_ASSERT(value == Enum2::NAME_1);
OATPP_LOGI(TAG, "OK");
}

View File

@ -214,7 +214,7 @@ void InterpretationTest::onRun() {
auto v = tr.resolveObjectPropertyValue(l, {"p1", "x"}, cache);
OATPP_ASSERT(v);
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 1);
OATPP_ASSERT(v.cast<oatpp::Int32>() == 1);
}
{
@ -226,7 +226,7 @@ void InterpretationTest::onRun() {
auto v = tr.resolveObjectPropertyValue(l, {"p1", "y"}, cache);
OATPP_ASSERT(v);
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 2);
OATPP_ASSERT(v.cast<oatpp::Int32>() == 2);
}
{
@ -238,7 +238,7 @@ void InterpretationTest::onRun() {
auto v = tr.resolveObjectPropertyValue(l, {"p1", "z"}, cache);
OATPP_ASSERT(v);
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
OATPP_ASSERT(v.staticCast<oatpp::Int32>() == 3);
OATPP_ASSERT(v.cast<oatpp::Int32>() == 3);
}
}

View File

@ -140,11 +140,11 @@ void ListTest::onRun() {
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::List<oatpp::String> list = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::List<oatpp::String>::Class::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
list.getValueType()->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(list, oatpp::String("d"));
polymorphicDispatcher->addItem(list, oatpp::String("d"));
OATPP_ASSERT(list->size() == 4);

View File

@ -146,6 +146,21 @@ class PolymorphicDto2 : public oatpp::DTO {
};
class PolymorphicDto3 : public oatpp::DTO {
DTO_INIT(PolymorphicDto3, DTO)
DTO_FIELD(String, type);
DTO_FIELD(Void, polymorph);
DTO_FIELD_TYPE_SELECTOR(polymorph) {
if(self->type == "str") return String::Class::getType();
if(self->type == "int") return Int32::Class::getType();
return Void::Class::getType();
}
};
#include OATPP_CODEGEN_END(DTO)
void runDtoInitializations() {
@ -484,13 +499,45 @@ void ObjectTest::onRun() {
OATPP_ASSERT(dtoClone->polymorph)
OATPP_ASSERT(dtoClone->polymorph.getValueType() == oatpp::Object<oatpp::DTO>::Class::getType())
auto polymorphClone = dtoClone->polymorph.staticCast<oatpp::Object<DtoTypeA>>();
auto polymorphClone = dtoClone->polymorph.cast<oatpp::Object<DtoTypeA>>();
OATPP_ASSERT(polymorphClone->fieldA == "type-A")
OATPP_LOGI(TAG, "OK");
}
{
OATPP_LOGI(TAG, "Test 17...");
oatpp::parser::json::mapping::ObjectMapper mapper;
auto dto = PolymorphicDto3::createShared();
dto->type = "str";
dto->polymorph = oatpp::String("Hello World!");
OATPP_ASSERT(dto->polymorph.getValueType() == oatpp::String::Class::getType())
auto json = mapper.writeToString(dto);
OATPP_LOGD(TAG, "json0='%s'", json->c_str())
auto dtoClone = mapper.readFromString<oatpp::Object<PolymorphicDto3>>(json);
auto jsonClone = mapper.writeToString(dtoClone);
OATPP_LOGD(TAG, "json1='%s'", jsonClone->c_str())
OATPP_ASSERT(json == jsonClone)
OATPP_ASSERT(dtoClone->polymorph)
OATPP_ASSERT(dtoClone->polymorph.getValueType() == oatpp::Void::Class::getType())
auto polymorphClone = dtoClone->polymorph.cast<oatpp::String>();
OATPP_ASSERT(polymorphClone == "Hello World!")
OATPP_LOGI(TAG, "OK");
}
}
}}}}}}

View File

@ -83,8 +83,14 @@ void ObjectWrapperTest::onRun() {
OATPP_LOGI(TAG, "Check valueType is NOT assigned from copy-assign operator...");
ObjectWrapper<std::string> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<std::string> pw2;
pw2 = pw1;
bool throws = false;
try {
pw2 = pw1;
} catch (std::runtime_error& e) {
throws = true;
}
OATPP_ASSERT(pw2.getValueType() == oatpp::data::mapping::type::__class::Void::getType());
OATPP_ASSERT(throws)
OATPP_LOGI(TAG, "OK");
}
@ -92,8 +98,14 @@ void ObjectWrapperTest::onRun() {
OATPP_LOGI(TAG, "Check valueType is NOT assigned from move-assign operator...");
ObjectWrapper<std::string> pw1(oatpp::data::mapping::type::__class::String::getType());
ObjectWrapper<std::string> pw2;
pw2 = std::move(pw1);
bool throws = false;
try {
pw2 = std::move(pw1);
} catch (std::runtime_error& e) {
throws = true;
}
OATPP_ASSERT(pw2.getValueType() == oatpp::data::mapping::type::__class::Void::getType());
OATPP_ASSERT(throws)
OATPP_LOGI(TAG, "OK");
}
@ -176,7 +188,7 @@ void ObjectWrapperTest::onRun() {
OATPP_ASSERT(v.getValueType() == oatpp::Int32::Class::getType());
oatpp::Int32 i = v.staticCast<oatpp::Int32>();
oatpp::Int32 i = v.cast<oatpp::Int32>();
OATPP_ASSERT(i.getValueType() == oatpp::Int32::Class::getType());
OATPP_ASSERT(i == 32);

View File

@ -148,11 +148,11 @@ void PairListTest::onRun() {
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::Fields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
auto polymorphicDispatcher = static_cast<const typename oatpp::Fields<String>::Class::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher*>(
map.getValueType()->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
polymorphicDispatcher->addItem(map, oatpp::String("key1"), oatpp::String("d"));
OATPP_ASSERT(map->size() == 4);

View File

@ -144,11 +144,11 @@ void UnorderedMapTest::onRun() {
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::UnorderedFields<String> map = {{"key1", "a"}, {"key2", "b"}, {"key3", "c"}};
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedFields<String>::Class::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Map::PolymorphicDispatcher*>(
map.getValueType()->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(map, oatpp::String("key1"), oatpp::String("d"));
polymorphicDispatcher->addItem(map, oatpp::String("key1"), oatpp::String("d"));
OATPP_ASSERT(map->size() == 3);

View File

@ -120,15 +120,15 @@ void UnorderedSetTest::onRun() {
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::UnorderedSet<oatpp::String> set = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::UnorderedSet<oatpp::String>::Class::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const typename oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
set.getValueType()->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("a"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("b"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("c"));
polymorphicDispatcher->addItem(set, oatpp::String("a"));
polymorphicDispatcher->addItem(set, oatpp::String("b"));
polymorphicDispatcher->addItem(set, oatpp::String("c"));
polymorphicDispatcher->addPolymorphicItem(set, oatpp::String("d"));
polymorphicDispatcher->addItem(set, oatpp::String("d"));
OATPP_ASSERT(set->size() == 4);

View File

@ -140,11 +140,11 @@ void VectorTest::onRun() {
OATPP_LOGI(TAG, "test polymorphicDispatcher...");
oatpp::Vector<oatpp::String> vector = {"a", "b", "c"};
auto polymorphicDispatcher = static_cast<const typename oatpp::Vector<oatpp::String>::Class::PolymorphicDispatcher*>(
auto polymorphicDispatcher = static_cast<const oatpp::data::mapping::type::__class::Collection::PolymorphicDispatcher*>(
vector.getValueType()->polymorphicDispatcher
);
polymorphicDispatcher->addPolymorphicItem(vector, oatpp::String("d"));
polymorphicDispatcher->addItem(vector, oatpp::String("d"));
OATPP_ASSERT(vector->size() == 4);