Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / common / primitiveResource / src / RCSResourceAttributes.cpp
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 #include <RCSResourceAttributes.h>
22
23 #include <ResourceAttributesUtils.h>
24 #include <ResourceAttributesConverter.h>
25
26 #include <boost/lexical_cast.hpp>
27 #include <boost/mpl/advance.hpp>
28 #include <boost/mpl/size.hpp>
29 #include <boost/mpl/deref.hpp>
30
31 namespace
32 {
33
34     using namespace OIC::Service;
35
36     class ToStringVisitor: public boost::static_visitor< std::string >
37     {
38     public:
39         ToStringVisitor() = default;
40         ToStringVisitor(const ToStringVisitor&) = delete;
41         ToStringVisitor(ToStringVisitor&&) = delete;
42
43         ToStringVisitor& operator=(const ToStringVisitor&) = delete;
44         ToStringVisitor& operator=(ToStringVisitor&&) = delete;
45
46         template < typename T >
47         std::string operator()(const T& value) const
48         {
49             return boost::lexical_cast<std::string>(value);
50         }
51
52         std::string operator()(std::nullptr_t) const
53         {
54             return "";
55         }
56
57         std::string operator()(bool value) const
58         {
59             return value ? "true" : "false";
60         }
61
62         std::string operator()(const std::string& value) const
63         {
64             return value;
65         }
66
67         std::string operator()(const OIC::Service::RCSResourceAttributes&) const
68         {
69             return "Attributes";
70         }
71     };
72
73     class TypeVisitor: public boost::static_visitor< RCSResourceAttributes::Type >
74     {
75     public:
76         TypeVisitor() = default;
77         TypeVisitor(const TypeVisitor&) = delete;
78         TypeVisitor(TypeVisitor&&) = delete;
79
80         TypeVisitor& operator=(const TypeVisitor&) = delete;
81         TypeVisitor& operator=(TypeVisitor&&) = delete;
82
83         template< typename T >
84         RCSResourceAttributes::Type operator()(const T& value) const
85         {
86             return RCSResourceAttributes::Type::typeOf(value);
87         }
88
89     };
90
91     template< int >
92     struct Int2Type {};
93
94     template< typename T >
95     struct TypeInfoConverter;
96
97     template< >
98     struct TypeInfoConverter< int >
99     {
100         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::INT;
101     };
102
103     template< >
104     struct TypeInfoConverter< std::nullptr_t >
105     {
106         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::NULL_T;
107     };
108
109     template< >
110     struct TypeInfoConverter< double >
111     {
112         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::DOUBLE;
113     };
114
115     template< >
116     struct TypeInfoConverter< bool >
117     {
118         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::BOOL;
119     };
120
121     template< >
122     struct TypeInfoConverter< std::string >
123     {
124         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::STRING;
125     };
126
127     template< >
128     struct TypeInfoConverter< RCSResourceAttributes >
129     {
130         static constexpr RCSResourceAttributes::TypeId typeId = RCSResourceAttributes::TypeId::ATTRIBUTES;
131     };
132
133     struct TypeInfo
134     {
135         RCSResourceAttributes::TypeId typeId;
136
137         template< typename TRAIT >
138         constexpr TypeInfo(TRAIT) :
139                 typeId{ TRAIT::typeId }
140         {
141         }
142
143         template< typename VARIANT, int POS >
144         static constexpr TypeInfo get()
145         {
146             return TypeInfo(TypeInfoConverter<
147                         typename boost::mpl::deref<
148                             typename boost::mpl::advance<
149                                 typename boost::mpl::begin< typename VARIANT::types>::type,
150                                 boost::mpl::int_< POS >
151                             >::type
152                         >::type >{ });
153         }
154     };
155
156     template< typename VARIANT, int POS >
157     constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< POS >)
158     {
159         auto&& vec = getTypeInfo< VARIANT >(Int2Type< POS - 1 >{ });
160         vec.push_back(TypeInfo::get< VARIANT, POS >());
161         return vec;
162     }
163
164     template< typename VARIANT >
165     constexpr inline std::vector< TypeInfo > getTypeInfo(Int2Type< 0 >)
166     {
167         return { TypeInfo::get< VARIANT, 0 >() };
168     }
169
170     template< typename VARIANT >
171     inline TypeInfo getTypeInfo(int which)
172     {
173         static constexpr int variantEnd = boost::mpl::size< typename VARIANT::types >::value - 1;
174         static const std::vector< TypeInfo > typeInfos = getTypeInfo< VARIANT >(
175                 Int2Type< variantEnd >{ });
176
177         return typeInfos[which];
178     }
179
180 } // unnamed namespace
181
182
183 namespace OIC
184 {
185     namespace Service
186     {
187
188         RCSResourceAttributes::Value::ComparisonHelper::ComparisonHelper(const Value& v) :
189                 m_valueRef(v)
190         {
191         }
192
193         bool RCSResourceAttributes::Value::ComparisonHelper::operator==
194                 (const Value::ComparisonHelper& rhs) const
195         {
196             return *m_valueRef.m_data == *rhs.m_valueRef.m_data;
197         }
198
199         bool operator==(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs)
200         {
201             return lhs.m_which == rhs.m_which;
202         }
203
204         bool operator!=(const RCSResourceAttributes::Type& lhs, const RCSResourceAttributes::Type& rhs)
205         {
206             return !(lhs == rhs);
207         }
208
209         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
210                 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
211         {
212             return lhs.operator==(rhs);
213         }
214
215         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs,
216                 const RCSResourceAttributes::Value::ComparisonHelper& rhs)
217         {
218             return !lhs.operator==(rhs);
219         }
220
221         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
222         {
223             return lhs.m_values == rhs.m_values;
224         }
225
226         bool operator!=(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs)
227         {
228             return !(lhs == rhs);
229         }
230
231         auto RCSResourceAttributes::Type::getId() const -> TypeId
232         {
233             return ::getTypeInfo< ValueVariant >(m_which).typeId;
234         }
235
236         RCSResourceAttributes::Value::Value() :
237                 m_data{ new ValueVariant{} }
238         {
239         }
240
241         RCSResourceAttributes::Value::Value(const Value& from) :
242                 m_data{ new ValueVariant{ *from.m_data } }
243         {
244         }
245
246         RCSResourceAttributes::Value::Value(Value&& from) :
247                 m_data{ new ValueVariant{} }
248         {
249             m_data->swap(*from.m_data);
250         }
251
252         RCSResourceAttributes::Value::Value(const char* value) :
253                 m_data{ new ValueVariant{ std::string{ value } } }
254         {
255         }
256
257         auto RCSResourceAttributes::Value::operator=(const Value& rhs) -> Value&
258         {
259             *m_data = *rhs.m_data;
260             return *this;
261         }
262
263         auto RCSResourceAttributes::Value::operator=(Value&& rhs) -> Value&
264         {
265             *m_data = ValueVariant{};
266             m_data->swap(*rhs.m_data);
267             return *this;
268         }
269
270         auto RCSResourceAttributes::Value::operator=(const char* rhs) -> Value&
271         {
272             *m_data = std::string{ rhs };
273             return *this;
274         }
275
276         auto RCSResourceAttributes::Value::operator=(std::nullptr_t) -> Value&
277         {
278             *m_data = nullptr;
279             return *this;
280         }
281
282         auto RCSResourceAttributes::Value::getType() const -> Type
283         {
284             return boost::apply_visitor(TypeVisitor(), *m_data);
285         }
286
287         std::string RCSResourceAttributes::Value::toString() const
288         {
289             return boost::apply_visitor(ToStringVisitor(), *m_data);
290         }
291
292         void RCSResourceAttributes::Value::swap(Value& rhs)
293         {
294             m_data.swap(rhs.m_data);
295         }
296
297         auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
298                 iterator* iter) const -> result_type
299         {
300             return iter->m_cur->first;
301         }
302
303         auto RCSResourceAttributes::KeyValuePair::KeyVisitor::operator()(
304                 const_iterator* iter) const -> result_type
305         {
306             return iter->m_cur->first;
307         }
308
309         auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (iterator* iter)
310                 -> result_type
311         {
312             return iter->m_cur->second;
313         }
314
315         auto RCSResourceAttributes::KeyValuePair::ValueVisitor::operator() (const_iterator*)
316                 -> result_type
317         {
318             // should not reach here.
319             throw BadGetException("");
320         }
321
322         auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
323                 iterator*iter) const -> result_type
324         {
325             return iter->m_cur->second;
326         }
327
328         auto RCSResourceAttributes::KeyValuePair::ConstValueVisitor::operator()(
329                 const_iterator* iter) const -> result_type
330         {
331             return iter->m_cur->second;
332         }
333
334         auto RCSResourceAttributes::KeyValuePair::key() const -> const std::string&
335         {
336             return boost::apply_visitor(m_keyVisitor, m_iterRef);
337         }
338
339         auto RCSResourceAttributes::KeyValuePair::value() const -> const Value&
340         {
341             return boost::apply_visitor(m_constValueVisitor, m_iterRef);
342         }
343
344         auto RCSResourceAttributes::KeyValuePair::value() -> Value&
345         {
346             return boost::apply_visitor(m_valueVisitor, m_iterRef);
347         }
348
349         RCSResourceAttributes::KeyValuePair::KeyValuePair(boost::variant<iterator*,
350                 const_iterator*>&& ref) :
351                 m_iterRef{ ref }
352         {
353         }
354
355
356         RCSResourceAttributes::iterator::iterator() :
357                 m_cur{ base_iterator{ } },
358                 m_keyValuePair{ this }
359         {
360         }
361
362         RCSResourceAttributes::iterator::iterator(base_iterator&& iter) :
363                 m_cur{ std::move(iter) },
364                 m_keyValuePair{ this }
365         {
366         }
367
368         auto RCSResourceAttributes::iterator::operator*() -> KeyValuePair&
369         {
370             return m_keyValuePair;
371         }
372
373         auto RCSResourceAttributes::iterator::iterator::operator->() -> KeyValuePair*
374         {
375             return &m_keyValuePair;
376         }
377
378         auto RCSResourceAttributes::iterator::operator++() -> iterator&
379         {
380             ++m_cur;
381             return *this;
382         }
383
384         auto RCSResourceAttributes::iterator::operator++(int) -> iterator
385         {
386             iterator iter(*this);
387             ++(*this);
388             return iter;
389         }
390
391         bool RCSResourceAttributes::iterator::operator==(const iterator& rhs) const
392         {
393             return m_cur == rhs.m_cur;
394         }
395
396         bool RCSResourceAttributes::iterator::operator!=(const iterator& rhs) const
397         {
398             return !(*this == rhs);
399         }
400
401
402         RCSResourceAttributes::const_iterator::const_iterator() :
403                 m_cur{ base_iterator{} }, m_keyValuePair{ this }
404         {
405         }
406
407         RCSResourceAttributes::const_iterator::const_iterator(base_iterator&& iter) :
408                 m_cur{ iter }, m_keyValuePair{ this }
409         {
410         }
411
412         RCSResourceAttributes::const_iterator::const_iterator(
413                 const RCSResourceAttributes::iterator& iter) :
414                 m_cur{ iter.m_cur }, m_keyValuePair{ this }
415         {
416         }
417
418         auto RCSResourceAttributes::const_iterator::operator=(const RCSResourceAttributes::iterator& iter)
419             -> const_iterator& {
420             m_cur = iter.m_cur;
421             return *this;
422         }
423
424         auto RCSResourceAttributes::const_iterator::operator*() const -> reference
425         {
426             return m_keyValuePair;
427         }
428         auto RCSResourceAttributes::const_iterator::operator->() const -> pointer
429         {
430             return &m_keyValuePair;
431         }
432
433         auto RCSResourceAttributes::const_iterator::operator++() -> const_iterator&
434         {
435             ++m_cur;
436             return *this;
437         }
438
439         auto RCSResourceAttributes::const_iterator::operator++(int) -> const_iterator
440         {
441             const_iterator iter(*this);
442             ++(*this);
443             return iter;
444         }
445
446         bool RCSResourceAttributes::const_iterator::operator==(const const_iterator& rhs) const
447         {
448             return m_cur == rhs.m_cur;
449         }
450
451         bool RCSResourceAttributes::const_iterator::operator!=(const const_iterator& rhs) const
452         {
453             return !(*this == rhs);
454         }
455
456         auto RCSResourceAttributes::begin() -> iterator
457         {
458             return iterator{ m_values.begin() };
459         }
460
461         auto RCSResourceAttributes::end() -> iterator
462         {
463             return iterator{ m_values.end() };
464         }
465
466         auto RCSResourceAttributes::begin() const -> const_iterator
467         {
468             return const_iterator{ m_values.begin() };
469         }
470
471         auto RCSResourceAttributes::end() const -> const_iterator
472         {
473             return const_iterator{ m_values.end() };
474         }
475
476         auto RCSResourceAttributes::cbegin() const -> const_iterator
477         {
478             return const_iterator{ m_values.begin() };
479         }
480
481         auto RCSResourceAttributes::cend() const -> const_iterator
482         {
483             return const_iterator{ m_values.end() };
484         }
485
486         auto RCSResourceAttributes::operator[](const std::string& key) -> Value&
487         {
488             return m_values[key];
489         }
490
491         auto RCSResourceAttributes::operator[](std::string&& key) -> Value&
492         {
493             return m_values[std::move(key)];
494         }
495
496         auto RCSResourceAttributes::at(const std::string& key) -> Value&
497         {
498             try
499             {
500                 return m_values.at(key);
501             }
502             catch (const std::out_of_range&)
503             {
504                 throw InvalidKeyException{ "No attribute named '" + key + "'" };
505             }
506         }
507
508         auto RCSResourceAttributes::at(const std::string& key) const -> const Value&
509         {
510             try
511             {
512                 return m_values.at(key);
513             }
514             catch (const std::out_of_range&)
515             {
516                 throw InvalidKeyException{ "No attribute named '" + key + "'" };
517             }
518         }
519
520         void RCSResourceAttributes::clear()
521         {
522             return m_values.clear();
523         }
524
525         bool RCSResourceAttributes::erase(const std::string& key)
526         {
527             return m_values.erase(key) == 1U;
528         }
529
530         bool RCSResourceAttributes::contains(const std::string& key) const
531         {
532             return m_values.find(key) != m_values.end();
533         }
534
535         bool RCSResourceAttributes::empty() const
536         {
537             return m_values.empty();
538         }
539
540         size_t RCSResourceAttributes::size() const
541         {
542             return m_values.size();
543         }
544
545
546         bool acceptableAttributeValue(const RCSResourceAttributes::Value& dest,
547                 const RCSResourceAttributes::Value& value)
548         {
549             if (dest.getType() != value.getType())
550             {
551                 return false;
552             }
553
554             static_assert(RCSResourceAttributes::is_supported_type< RCSResourceAttributes >::value,
555                     "RCSResourceAttributes doesn't have RCSResourceAttributes recursively.");
556             if (dest.getType().getId() == RCSResourceAttributes::TypeId::ATTRIBUTES
557                     && !acceptableAttributes(dest.get< RCSResourceAttributes >(),
558                             value.get< RCSResourceAttributes >()))
559             {
560                 return false;
561             }
562
563             return true;
564         }
565
566         bool acceptableAttributes(const RCSResourceAttributes& dest, const RCSResourceAttributes& attr)
567         {
568             for (const auto& kv : attr)
569             {
570                 if (!dest.contains(kv.key()))
571                 {
572                     return false;
573                 }
574
575                 if (!acceptableAttributeValue(dest.at(kv.key()), kv.value()))
576                 {
577                     return false;
578                 }
579             }
580
581             return true;
582         }
583
584         AttrKeyValuePairs replaceAttributes(RCSResourceAttributes& dest,
585                 const RCSResourceAttributes& newAttrs)
586         {
587             AttrKeyValuePairs replacedList;
588
589             for (const auto& kv : newAttrs)
590             {
591                 if (dest[kv.key()] != kv.value())
592                 {
593                     RCSResourceAttributes::Value replacedValue;
594                     replacedValue.swap(dest[kv.key()]);
595                     dest[kv.key()] = kv.value();
596
597                     replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) });
598                 }
599             }
600
601             return replacedList;
602         }
603     }
604 }