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