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