/src/oatpp/src/oatpp/data/mapping/ObjectMapper.hpp
Line | Count | Source |
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 | | |
25 | | #ifndef oatpp_data_mapping_ObjectMapper_hpp |
26 | | #define oatpp_data_mapping_ObjectMapper_hpp |
27 | | |
28 | | #include <utility> |
29 | | |
30 | | #include "oatpp/Types.hpp" |
31 | | |
32 | | #include "oatpp/data/stream/Stream.hpp" |
33 | | |
34 | | #include "oatpp/utils/parser/Caret.hpp" |
35 | | #include "oatpp/utils/parser/ParsingError.hpp" |
36 | | |
37 | | namespace oatpp { namespace data { namespace mapping { |
38 | | |
39 | | /** |
40 | | * Error stack |
41 | | */ |
42 | | struct ErrorStack { |
43 | | |
44 | | /** |
45 | | * stack |
46 | | */ |
47 | | std::list<oatpp::String> stack; |
48 | | |
49 | | /** |
50 | | * Push error |
51 | | * @param error |
52 | | */ |
53 | | void push(const oatpp::String& error); |
54 | | |
55 | | /** |
56 | | * Push all errors from other error stack. |
57 | | * @param errorStack |
58 | | */ |
59 | | void splice(ErrorStack& errorStack); |
60 | | |
61 | | /** |
62 | | * Stacktrace as string. |
63 | | * @return |
64 | | */ |
65 | | oatpp::String stacktrace() const; |
66 | | |
67 | | /** |
68 | | * Check if error stack is empty. |
69 | | * @return |
70 | | */ |
71 | | bool empty() const; |
72 | | |
73 | | }; |
74 | | |
75 | | /** |
76 | | * Mapping error |
77 | | */ |
78 | | class MappingError : public std::runtime_error { |
79 | | private: |
80 | | ErrorStack m_stack; |
81 | | public: |
82 | | |
83 | | /** |
84 | | * Constructor. |
85 | | * @param errorStack |
86 | | */ |
87 | | MappingError(const ErrorStack& errorStack); |
88 | | |
89 | | /** |
90 | | * Constructor. |
91 | | * @param errorStack |
92 | | */ |
93 | | MappingError(ErrorStack&& errorStack); |
94 | | |
95 | | /** |
96 | | * Get error stack |
97 | | * @return - See &id:oatpp::data::mapping::ErrorStack;. |
98 | | */ |
99 | | const ErrorStack& errorStack() const; |
100 | | |
101 | | /** |
102 | | * Get error stack |
103 | | * @return - See &id:oatpp::data::mapping::ErrorStack;. |
104 | | */ |
105 | | ErrorStack& errorStack(); |
106 | | |
107 | | }; |
108 | | |
109 | | /** |
110 | | * Abstract ObjectMapper class. |
111 | | */ |
112 | | class ObjectMapper { |
113 | | public: |
114 | | |
115 | | /** |
116 | | * Metadata for ObjectMapper. |
117 | | */ |
118 | | class Info { |
119 | | public: |
120 | | |
121 | | /** |
122 | | * Constructor |
123 | | */ |
124 | | Info(const oatpp::String& pMimeType, const oatpp::String& pMimeSubtype) |
125 | 2.63k | : httpContentType(pMimeType + "/" + pMimeSubtype) |
126 | 2.63k | , mimeType(pMimeType) |
127 | 2.63k | , mimeSubtype(pMimeSubtype) |
128 | 2.63k | {} |
129 | | |
130 | | /** |
131 | | * Value for Content-Type http header when DTO is serialized via specified ObjectMapper. |
132 | | */ |
133 | | const oatpp::String httpContentType; |
134 | | |
135 | | /** |
136 | | * Mime type |
137 | | */ |
138 | | const oatpp::String mimeType; |
139 | | |
140 | | /** |
141 | | * Mime subtype |
142 | | */ |
143 | | const oatpp::String mimeSubtype; |
144 | | |
145 | | }; |
146 | | private: |
147 | | Info m_info; |
148 | | public: |
149 | | |
150 | | /** |
151 | | * Constructor. |
152 | | * @param info - Metadata for ObjectMapper. |
153 | | */ |
154 | | ObjectMapper(const Info& info); |
155 | | |
156 | | /** |
157 | | * Get ObjectMapper metadata. |
158 | | * @return - ObjectMapper metadata. |
159 | | */ |
160 | | const Info& getInfo() const; |
161 | | |
162 | | /** |
163 | | * Serialize object to stream. Implement this method. |
164 | | * @param stream - &id:oatpp::data::stream::ConsistentOutputStream; to serialize object to. |
165 | | * @param errorStack - See &id:oatpp::data::mapping::ErrorStack;. |
166 | | * @param variant - Object to serialize. |
167 | | */ |
168 | | virtual void write(data::stream::ConsistentOutputStream* stream, const oatpp::Void& variant, ErrorStack& errorStack) const = 0; |
169 | | |
170 | | /** |
171 | | * Deserialize object. Implement this method. |
172 | | * @param caret - &id:oatpp::utils::parser::Caret; over serialized buffer. |
173 | | * @param type - pointer to object type. See &id:oatpp::data::type::Type;. |
174 | | * @param errorStack - See &id:oatpp::data::mapping::ErrorStack;. |
175 | | * @return - deserialized object wrapped in &id:oatpp::Void;. |
176 | | */ |
177 | | virtual oatpp::Void read(oatpp::utils::parser::Caret& caret, const oatpp::Type* type, ErrorStack& errorStack) const = 0; |
178 | | |
179 | | /** |
180 | | * Serialize object to String. |
181 | | * @param variant - Object to serialize. |
182 | | * @return - serialized object as &id:oatpp::String;. |
183 | | * @throws - &id:oatpp::data::mapping::MappingError; |
184 | | * @throws - depends on implementation. |
185 | | */ |
186 | | oatpp::String writeToString(const oatpp::Void& variant) const; |
187 | | |
188 | | /** |
189 | | * Deserialize object. |
190 | | * If nullptr is returned - check caret.getError() |
191 | | * @tparam Wrapper - ObjectWrapper type. |
192 | | * @param caret - &id:oatpp::utils::parser::Caret; over serialized buffer. |
193 | | * @return - deserialized Object. |
194 | | * @throws - &id:oatpp::data::mapping::MappingError; |
195 | | * @throws - depends on implementation. |
196 | | */ |
197 | | template<class Wrapper> |
198 | | Wrapper readFromCaret(oatpp::utils::parser::Caret& caret) const { |
199 | | auto type = Wrapper::Class::getType(); |
200 | | ErrorStack errorStack; |
201 | | const auto& result = read(caret, type, errorStack).template cast<Wrapper>(); |
202 | | if(!errorStack.empty()) { |
203 | | throw MappingError(std::move(errorStack)); |
204 | | } |
205 | | return result; |
206 | | } |
207 | | |
208 | | /** |
209 | | * Deserialize object. |
210 | | * @tparam Wrapper - ObjectWrapper type. |
211 | | * @param str - serialized data. |
212 | | * @return - deserialized Object. |
213 | | * @throws - &id:oatpp::data::mapping::MappingError; |
214 | | * @throws - depends on implementation. |
215 | | */ |
216 | | template<class Wrapper> |
217 | 2.63k | Wrapper readFromString(const oatpp::String& str) const { |
218 | 2.63k | auto type = Wrapper::Class::getType(); |
219 | 2.63k | oatpp::utils::parser::Caret caret(str); |
220 | 2.63k | ErrorStack errorStack; |
221 | 2.63k | const auto& result = read(caret, type, errorStack).template cast<Wrapper>(); |
222 | 2.63k | if(!errorStack.empty()) { |
223 | 1.75k | throw MappingError(std::move(errorStack)); |
224 | 1.75k | } |
225 | 878 | return result; |
226 | 2.63k | } |
227 | | |
228 | | }; |
229 | | |
230 | | }}} |
231 | | |
232 | | #endif /* oatpp_data_mapping_ObjectMapper_hpp */ |