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