Merge branch '1.3-rel' (5fdb8a1)
[iotivity.git] / service / resource-encapsulation / src / common / primitiveResource / include / ResourceAttributesConverter.h
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #ifndef COMMON_RESOURCEATTRIBUTESCONVERTER_H
22 #define COMMON_RESOURCEATTRIBUTESCONVERTER_H
23
24 #include <RCSResourceAttributes.h>
25
26 #include <OCRepresentation.h>
27
28 namespace OIC
29 {
30     namespace Service
31     {
32         namespace Detail
33         {
34             template< int >
35             struct Int2Type {};
36
37             template < typename T >
38             struct TypeDef
39             {
40                 typedef T type;
41             };
42
43             template< OC::AttributeType TYPE >
44             struct OCBaseType;
45
46             template< >
47             struct OCBaseType< OC::AttributeType::Integer > : TypeDef< int >{ };
48
49             template< >
50             struct OCBaseType< OC::AttributeType::Double > : TypeDef< double > { };
51
52             template< >
53             struct OCBaseType< OC::AttributeType::Boolean > : TypeDef< bool > { };
54
55             template< >
56             struct OCBaseType< OC::AttributeType::String > : TypeDef< std::string > { };
57
58             template< >
59             struct OCBaseType< OC::AttributeType::Binary > : TypeDef< RCSByteString::DataType > { };
60
61             template< >
62             struct OCBaseType< OC::AttributeType::OCByteString > : TypeDef< OCByteString > { };
63
64             template< >
65             struct OCBaseType< OC::AttributeType::OCRepresentation >
66                 : TypeDef< OC::OCRepresentation >
67             {};
68
69             template< int DEPTH, typename BASE_TYPE >
70             struct SeqType
71             {
72                 typedef std::vector< typename SeqType< DEPTH - 1, BASE_TYPE >::type > type;
73             };
74
75             template< typename BASE_TYPE >
76             struct SeqType< 0, BASE_TYPE >
77             {
78                 typedef BASE_TYPE type;
79             };
80
81             template< int DEPTH, OC::AttributeType BASE_TYPE >
82             struct OCItemType
83             {
84                 typedef typename SeqType< DEPTH,
85                                         typename OCBaseType< BASE_TYPE >::type >::type type;
86             };
87
88             template< typename T >
89             struct TypeInfo
90             {
91                 typedef T type;
92                 typedef T base_type;
93                 constexpr static size_t depth = 0;
94             };
95
96             template< typename T >
97             struct TypeInfo< std::vector< T > >
98             {
99                 typedef T type;
100                 typedef typename TypeInfo< T >::base_type base_type;
101                 constexpr static size_t depth = 1 + TypeInfo< T >::depth;
102             };
103         }
104
105         class ResourceAttributesConverter
106         {
107         private:
108             ResourceAttributesConverter() = delete;
109
110             class ResourceAttributesBuilder
111             {
112             private:
113                 template < int DEPTH >
114                 void insertItem(Detail::Int2Type< DEPTH >,
115                         const OC::OCRepresentation::AttributeItem& item)
116                 {
117                     switch (item.base_type())
118                     {
119                         case OC::AttributeType::Null:
120                             return putValue(item.attrname(), nullptr);
121
122                         case OC::AttributeType::Integer:
123                             return insertItem< DEPTH, OC::AttributeType::Integer >(item);
124
125                         case OC::AttributeType::Double:
126                             return insertItem< DEPTH, OC::AttributeType::Double >(item);
127
128                         case OC::AttributeType::Boolean:
129                             return insertItem< DEPTH, OC::AttributeType::Boolean >(item);
130
131                         case OC::AttributeType::String:
132                             return insertItem< DEPTH, OC::AttributeType::String >(item);
133
134                         case OC::AttributeType::Binary:
135                             // OCRep support only 0-depth for binary type.
136                             // If RI changed, this line should be changed to DEPTH.
137                             return insertOcBinary< OC::AttributeType::Binary >
138                             (Detail::Int2Type< 0 >{ }, item);
139
140                         case OC::AttributeType::OCByteString:
141                             return insertOcBinary< OC::AttributeType::OCByteString >
142                             (Detail::Int2Type< DEPTH >{ }, item);
143
144                         case OC::AttributeType::OCRepresentation:
145                             return insertOcRep(Detail::Int2Type< DEPTH >{ }, item);
146
147                         default:
148                             assert("There must be no another base type!");
149                     }
150                 }
151
152                 template< int DEPTH, OC::AttributeType BASE_TYPE >
153                 void insertItem(const OC::OCRepresentation::AttributeItem& item)
154                 {
155                     typedef typename Detail::OCItemType< DEPTH, BASE_TYPE >::type ItemType;
156                     putValue(item.attrname(), item.getValue< ItemType >());
157                 }
158
159                 RCSResourceAttributes insertOcRep(Detail::Int2Type< 0 >,
160                         const OC::OCRepresentation& ocRep)
161                 {
162                     return ResourceAttributesConverter::fromOCRepresentation(ocRep);
163                 }
164
165                 template< int DEPTH, typename OCREPS,
166                     typename ATTRS = typename Detail::SeqType< DEPTH, RCSResourceAttributes >::type >
167                 ATTRS insertOcRep(Detail::Int2Type< DEPTH >, const OCREPS& ocRepVec)
168                 {
169                     ATTRS result;
170
171                     for (const auto& nested : ocRepVec)
172                     {
173                         result.push_back(insertOcRep(Detail::Int2Type< DEPTH - 1 >{ }, nested));
174                     }
175
176                     return result;
177                 }
178
179                 template< int DEPTH >
180                 void insertOcRep(Detail::Int2Type< DEPTH >,
181                         const OC::OCRepresentation::AttributeItem& item)
182                 {
183                     typedef typename Detail::OCItemType< DEPTH,
184                             OC::AttributeType::OCRepresentation >::type ItemType;
185
186                     putValue(item.attrname(),
187                             insertOcRep(Detail::Int2Type< DEPTH >{ }, item.getValue< ItemType >()));
188                 }
189
190                 template< typename OCREP >
191                 RCSByteString insertOcBinary(Detail::Int2Type< 0 >, const OCREP& ocBinary)
192                 {
193                     return RCSByteString(ocBinary);
194                 }
195
196                 template< int DEPTH, typename OCREPS,
197                     typename ATTRS = typename Detail::SeqType< DEPTH, RCSByteString >::type >
198                 ATTRS insertOcBinary(Detail::Int2Type< DEPTH >, const OCREPS& ocBinaryVec)
199                 {
200                     ATTRS result;
201
202                     for (const auto& nested : ocBinaryVec)
203                     {
204                         result.push_back(insertOcBinary(Detail::Int2Type< DEPTH - 1 >{ }, nested));
205                     }
206
207                     return result;
208                 }
209
210                 template< OC::AttributeType BASE_TYPE, int DEPTH >
211                 void insertOcBinary(Detail::Int2Type< DEPTH >,
212                         const OC::OCRepresentation::AttributeItem& item)
213                 {
214                     typedef typename Detail::OCItemType< DEPTH, BASE_TYPE >::type ItemType;
215
216                     putValue(item.attrname(),
217                              insertOcBinary(Detail::Int2Type< DEPTH >{ },
218                                             item.getValue< ItemType >()));
219                 }
220
221             public:
222                 ResourceAttributesBuilder() = default;
223
224                 void insertItem(const OC::OCRepresentation::AttributeItem& item)
225                 {
226                     switch (item.depth())
227                     {
228                         case 0:
229                             return insertItem(Detail::Int2Type< 0 >{ }, item);
230                         case 1:
231                             return insertItem(Detail::Int2Type< 1 >{ }, item);
232                         case 2:
233                             return insertItem(Detail::Int2Type< 2 >{ }, item);
234                         case 3:
235                             return insertItem(Detail::Int2Type< 3 >{ }, item);
236
237                         default:
238                             assert("There must be no another depth!");
239                     }
240                 }
241
242                 RCSResourceAttributes&& extract()
243                 {
244                     return std::move(m_target);
245                 }
246
247             private:
248                 template< typename T >
249                 void putValue(const std::string& key, T&& value)
250                 {
251                     m_target[key] = std::forward< T >(value);
252                 }
253
254             private:
255                 RCSResourceAttributes m_target;
256             };
257
258             class OCRepresentationBuilder
259             {
260             public:
261                 OCRepresentationBuilder() = default;
262
263                 template< typename T, typename B = typename Detail::TypeInfo< T >::base_type >
264                 typename std::enable_if< (
265                 !std::is_same< B, RCSResourceAttributes >::value &&
266                 !std::is_same< B, RCSByteString >::value
267                 )>::type
268                 operator()(const std::string& key, const T& value)
269                 {
270                     m_target[key] = value;
271                 }
272
273                 template< typename T, typename I = Detail::TypeInfo< T > >
274                 typename std::enable_if< std::is_same< typename I::base_type,
275                                                 RCSResourceAttributes >::value >::type
276                 operator()(const std::string& key, const T& value)
277                 {
278                     m_target[key] = convertAttributes(Detail::Int2Type< I::depth >{ }, value);
279                 }
280
281                 template< typename T, typename I = Detail::TypeInfo< T > >
282                 typename std::enable_if< std::is_same< typename I::base_type,
283                                                 RCSByteString >::value >::type
284                 operator()(const std::string& key, const T& value)
285                 {
286                     m_target[key] = convertByteString(Detail::Int2Type< I::depth >{ }, value);
287                 }
288
289                 void operator()(const std::string& key, const std::nullptr_t&)
290                 {
291                     m_target.setNULL(key);
292                 }
293
294                 OC::OCRepresentation convertAttributes(Detail::Int2Type< 0 >,
295                         const RCSResourceAttributes& attrs)
296                 {
297                     return ResourceAttributesConverter::toOCRepresentation(attrs);
298                 }
299
300                 template< int DEPTH, typename ATTRS, typename OCREPS = typename Detail::SeqType<
301                         DEPTH, OC::OCRepresentation >::type >
302                 OCREPS convertAttributes(Detail::Int2Type< DEPTH >, const ATTRS& attrs)
303                 {
304                     OCREPS result;
305
306                     for (const auto& nested : attrs)
307                     {
308                         result.push_back(
309                                 convertAttributes(Detail::Int2Type< DEPTH - 1 >{ }, nested));
310                     }
311
312                     return result;
313                 }
314
315                 OCByteString convertByteString(Detail::Int2Type< 0 >,
316                         const RCSByteString& byteString)
317                 {
318                     OCByteString blob;
319                     blob.len = byteString.size();
320                     blob.bytes = new uint8_t[blob.len];
321                     for (size_t i = 0; i < blob.len; ++i)
322                     {
323                         blob.bytes[i] = byteString[i];
324                     }
325
326                     return blob;
327                 }
328
329                 template< int DEPTH, typename ATTRS, typename OCREPS = typename Detail::SeqType<
330                         DEPTH, OCByteString >::type >
331                 OCREPS convertByteString(Detail::Int2Type< DEPTH >, const ATTRS& byteStringVec)
332                 {
333                     OCREPS result;
334
335                     for (const auto& nested : byteStringVec)
336                     {
337                         result.push_back(
338                                 convertByteString(Detail::Int2Type< DEPTH - 1 >{ }, nested));
339                     }
340
341                     return result;
342                 }
343
344                 OC::OCRepresentation&& extract()
345                 {
346                     return std::move(m_target);
347                 }
348
349             private:
350                 OC::OCRepresentation m_target;
351             };
352
353         public:
354             static RCSResourceAttributes fromOCRepresentation(
355                     const OC::OCRepresentation& ocRepresentation)
356             {
357                 ResourceAttributesBuilder builder;
358
359                 for (const auto& item : ocRepresentation)
360                 {
361                     builder.insertItem(item);
362                 }
363
364                 return builder.extract();
365             }
366
367             static OC::OCRepresentation toOCRepresentation(
368                     const RCSResourceAttributes& resourceAttributes)
369             {
370                 OCRepresentationBuilder builder;
371
372                 resourceAttributes.visit(builder);
373
374                 return builder.extract();
375             }
376         };
377
378     }
379 }
380
381 #endif // COMMON_RESOURCEATTRIBUTESCONVERTER_H