Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / resource-encapsulation / include / RCSResourceAttributes.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 /**
22  * @file
23  *
24  * This file contains the "RCSResourceAttributes" class & its helper classes
25  */
26 #ifndef RES_ENCAPSULATION_RESOURCEATTRIBUTES_H
27 #define RES_ENCAPSULATION_RESOURCEATTRIBUTES_H
28
29 // To avoid conflict using different boost::variant configuration with OC.
30 // It causes compile errors.
31 #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
32 #define BOOST_MPL_LIMIT_LIST_SIZE 30
33 #define BOOST_MPL_LIMIT_VECTOR_SIZE 30
34
35 #include <functional>
36 #include <unordered_map>
37
38 #include <boost/variant.hpp>
39 #include <boost/mpl/contains.hpp>
40 #include <boost/mpl/find.hpp>
41 #include <boost/mpl/distance.hpp>
42 #include <boost/mpl/begin_end.hpp>
43 #include <boost/scoped_ptr.hpp>
44
45 #include <RCSException.h>
46
47 namespace OIC
48 {
49     namespace Service
50     {
51
52         /**
53         * RCSResourceAttributes represents the attributes for a resource.
54         *
55         * It provides similar usage to c++ standard containers. (iterator,
56         * operators and accessors)<br/>
57         * An attribute value can be one of various types. <br/>
58         *
59         * @note If client developer wants to get the RCSResourceAttributes for the resource of
60         *            interest following are the steps:
61         *            - first call the discover API of DiscoveryManager class.
62         *            - After getting the RemoteResourceObject, call getRemoteAttributes() API
63         *               of RemoteResourceObject class
64         *
65         * @see Value
66         * @see Type
67         * @see iterator
68         * @see const_iterator
69         * @see RCSDiscoveryManager
70         * @see RCSRemoteResourceObject
71         * @see RCSResourceObject
72         */
73         class RCSResourceAttributes
74         {
75         private:
76             template< typename T > struct IsSupportedTypeHelper;
77
78             typedef boost::variant<
79                 std::nullptr_t,
80                 int,
81                 double,
82                 bool,
83                 std::string,
84                 RCSResourceAttributes
85             > ValueVariant;
86
87             template< typename T, typename V = void,
88                     typename = typename std::enable_if<
89                         IsSupportedTypeHelper< T >::type::value, V >::type >
90             struct enable_if_supported
91             {
92                 typedef V type;
93             };
94
95             template< typename VISITOR >
96             class KeyValueVisitorHelper: public boost::static_visitor< >
97             {
98             public:
99                 KeyValueVisitorHelper(VISITOR& visitor) :
100                         m_visitor( visitor )
101                 {
102                 }
103
104                 template< typename T >
105                 void operator()(const std::string& key, const T& value) const
106                 {
107                     m_visitor(key, value);
108                 }
109
110             private:
111                 VISITOR& m_visitor;
112             };
113
114             template <typename T> struct IndexOfType;
115
116         public:
117
118             /**
119              * Trait class that identifies whether T is supported by the Value.
120              */
121             template< typename T >
122             struct is_supported_type: public std::conditional<
123                 IsSupportedTypeHelper< T >::type::value, std::true_type, std::false_type>::type { };
124
125             /**
126              * Identifier for types of Value.
127              *
128              * @see Type
129              */
130             enum class TypeId
131             {
132                 NULL_T, /**< nullptr_t */
133                 INT, /**< int */
134                 DOUBLE, /**< double */
135                 BOOL, /**< bool */
136                 STRING, /**< std::string */
137                 ATTRIBUTES, /**< RCSResourceAttributes */
138                 VECTOR /**< std::vector */
139             };
140
141             /**
142              * A Helper class to identify types of Value.
143              *
144              * @see RCSResourceAttributes
145              * @see Value
146              * @see TypeId
147              */
148             class Type
149             {
150             public:
151                 Type(const Type&) = default;
152                 Type(Type&&) = default;
153
154                 Type& operator=(const Type&) = default;
155                 Type& operator=(Type&&) = default;
156
157                 /**
158                  * Returns type identifier.
159                  *
160                  * @return Identifier of type.
161                  */
162                 TypeId getId() const;
163
164                 /**
165                  * Factory method to create Type instance from T.
166                  *
167                  * @return An instance that has TypeId for T.
168                  *
169                  * @note T must be supported by Value. Otherwise, it won't be compiled.
170                  *
171                  * @see is_supported_type
172                  */
173                 template < typename T >
174                 static Type typeOf(const T& value)
175                 {
176                     return Type(value);
177                 }
178
179                 //! @cond
180                 friend bool operator==(const Type&, const Type&);
181                 //! @endcond
182
183             private:
184                 template < typename T >
185                 explicit Type(const T&) :
186                     m_which{ IndexOfType< T >::value }
187                 {
188                 }
189
190             private:
191                 int m_which;
192             };
193
194             /**
195              * Value holds a value among various types at a time.
196              *
197              * Type helps identify type information of Value.
198              *
199              * @see RCSResourceAttributes
200              * @see Type
201              * @see is_supported_type
202              */
203             class Value
204             {
205             public:
206                 class ComparisonHelper;
207
208                 Value();
209                 Value(const Value&);
210                 Value(Value&&);
211
212                 /**
213                  * Constructs a Value if T is a supported type.<br/>
214                  *       Otherwise it won't be compiled.
215                  */
216                 template< typename T, typename = typename enable_if_supported< T >::type >
217                 Value(T&& value) :
218                         m_data{ new ValueVariant{ std::forward< T >(value) } }
219                 {
220                 }
221
222                 Value(const char* value);
223
224                 Value& operator=(const Value&);
225                 Value& operator=(Value&&);
226
227                 template< typename T, typename = typename enable_if_supported< T >::type >
228                 Value& operator=(T&& rhs)
229                 {
230                     *m_data = std::forward< T >(rhs);
231                     return *this;
232                 }
233
234                 Value& operator=(const char*);
235                 Value& operator=(std::nullptr_t);
236
237                 /**
238                  * Returns the underlying value as T.
239                  *
240                  * @return const reference to the underlying value.
241                  *
242                  * @throws BadGetException If type of the underlying value is not T.
243                  */
244                 template< typename T >
245                 typename std::add_lvalue_reference< const T >::type get() const
246                 {
247                     return checkedGet< T >();
248                 }
249
250                 /**
251                  * Returns the underlying value as T.
252                  *
253                  * @return reference to the underlying value.
254                  *
255                  * @throws BadGetException If type of the underlying value is not T.
256                  */
257                 template< typename T >
258                 typename std::add_lvalue_reference< T >::type get()
259                 {
260                     return checkedGet< T >();
261                 }
262
263                 /**
264                  * Returns Type information.
265                  *
266                  * @see Type
267                  */
268                 Type getType() const;
269
270                 /**
271                  * Returns a string representation.
272                  *
273                  */
274                 std::string toString() const;
275
276                 /**
277                  * Exchanges the content of the object by the content of the parameter.
278                  */
279                 void swap(Value&);
280
281                 //! @cond
282                 friend class RCSResourceAttributes;
283                 //! @endcond
284
285             private:
286                 template< typename T, typename = typename enable_if_supported< T >::type >
287                 typename std::add_lvalue_reference< T >::type checkedGet() const
288                 {
289                     try
290                     {
291                         return boost::get< T >(*m_data);
292                     }
293                     catch (const boost::bad_get&)
294                     {
295                         throw BadGetException{ "Wrong type" };
296                     }
297                 }
298
299                 template< typename T, typename U >
300                 bool equals(const U& rhs) const
301                 {
302                     try
303                     {
304                         return get< T >() == rhs;
305                     }
306                     catch (const BadGetException&)
307                     {
308                         return false;
309                     }
310                 }
311
312             private:
313                 boost::scoped_ptr< ValueVariant > m_data;
314             };
315
316             class KeyValuePair;
317             class iterator;
318             class const_iterator;
319
320         public:
321             RCSResourceAttributes() = default;
322             RCSResourceAttributes(const RCSResourceAttributes&) = default;
323             RCSResourceAttributes(RCSResourceAttributes&&) = default;
324
325             RCSResourceAttributes& operator=(const RCSResourceAttributes&) = default;
326             RCSResourceAttributes& operator=(RCSResourceAttributes&&) = default;
327
328             /**
329              * Returns an {@link iterator} referring to the first element.
330              */
331             iterator begin();
332
333             /**
334              * Returns an {@link iterator} referring to the <i>past-the-end element</i>.
335              */
336             iterator end();
337
338             /**
339              * @copydoc cbegin()
340              */
341             const_iterator begin() const;
342
343             /**
344              * @copydoc cend()
345              */
346             const_iterator end() const;
347
348             /**
349              * Returns a const_iterator referring to the first element.
350              */
351             const_iterator cbegin() const;
352
353             /**
354              * Returns a const_iterator referring to the <i>past-the-end element</i>.
355              */
356             const_iterator cend() const;
357
358             /**
359              * Accesses a value.
360              *
361              * If @a key matches the key of a value,
362              * returns a reference to its mapped value. <br/>
363              * If @a key doesn't match the key of any value,
364              * inserts a new value with that key and returns a reference to it.
365              * The element is a Value that has null.
366              *
367              * @param key Key of the element whose mapped value is accessed.
368              *
369              * @return A reference to the mapped value with @a key.
370              *
371              * @see at
372              */
373             Value& operator[](const std::string& key);
374
375             /**
376              * Accesses a value.
377              *
378              * If @a key matches the key of a value,
379              * returns a reference to its mapped value. <br/>
380              * If @a key doesn't match the key of any value,
381              * inserts a new value with that key and returns a reference to it.
382              * The value has null.
383              *
384              * @param key Key of the element whose mapped value is accessed.
385              *        This is moved instead of copied when a new value is inserted.
386              *
387              * @return A reference to the mapped value with @a key.
388              *
389              * @see at
390              */
391             Value& operator[](std::string&& key);
392
393             /**
394              * Accesses a value.
395              *
396              * If @a key matches the key of a value,
397              * returns a reference to its mapped value. <br/>
398              * If @a key doesn't match the key of any value, throws InvalidKeyException.
399              *
400              * @param key Key of the element whose mapped value is accessed.
401              *
402              * @throws InvalidKeyException If @a key doesn't match the key of any value.
403              *
404              * @return A reference to the mapped value with @a key.
405              *
406              * @see operator[]
407              */
408             Value& at(const std::string& key);
409
410             /**
411               * Accesses a value.
412               *
413               * If @a key matches the key of a value,
414               * returns a reference to its mapped value. <br/>
415               * If @a key doesn't match the key of any value, throws InvalidKeyException.
416               *
417               * @param key Key of the element whose mapped value is accessed.
418               *
419               * @throws InvalidKeyException If @a key doesn't match the key of any value.
420               *
421               * @return A const reference to the mapped value with @a key.
422               *
423               * @see operator[]
424               */
425             const Value& at(const std::string& key) const;
426
427             /**
428              * Removes all elements.
429              */
430             void clear();
431
432             /**
433              * Removes a single element.
434              *
435              * @param key Key of the element to be removed.
436              *
437              * @return true if an element is erased, false otherwise.
438              */
439             bool erase(const std::string& key);
440
441             /**
442              * Checks the container has an element with a Key equivalent to key.
443              *
444              * @param key Key to check.
445              *
446              * @return true if an element exists, false otherwise.
447              */
448             bool contains(const std::string& key) const;
449
450             /**
451              * Returns whether it is empty.
452              *
453              * @see size
454              */
455             bool empty() const;
456
457             /**
458              * Returns the number of elements.
459              *
460              * @see empty
461              */
462             size_t size() const;
463
464         private:
465             template< typename VISITOR >
466             void visit(VISITOR& visitor) const
467             {
468                 KeyValueVisitorHelper< VISITOR > helper{ visitor };
469
470                 for (const auto& i : m_values)
471                 {
472                     boost::variant< const std::string& > key{ i.first };
473                     boost::apply_visitor(helper, key, *i.second.m_data);
474                 }
475             }
476
477         private:
478             std::unordered_map< std::string, Value > m_values;
479
480             //! @cond
481             friend class ResourceAttributesConverter;
482
483             friend bool operator==(const RCSResourceAttributes&, const RCSResourceAttributes&);
484             //! @endcond
485         };
486
487         /**
488          * A helper class to avoid obscure comparisons of values which are supported
489          * by RCSResourceAttributes::Value caused by implicitly converting a value
490          * to a RCSResourceAttributes::Value.
491          *
492          * @see Value
493          * @see RCSResourceAttributes
494          * @see is_supported_type
495          */
496         class RCSResourceAttributes::Value::ComparisonHelper
497         {
498         public:
499             ComparisonHelper(const Value&);
500
501             template< typename T >
502             typename std::enable_if< is_supported_type< T >::value, bool >::type equals(
503                     const T& v) const
504             {
505                 return m_valueRef.equals< T >(v);
506             }
507
508             bool equals(const std::string& v) const
509             {
510                 return m_valueRef.equals< std::string >(v);
511             }
512
513             bool operator==(const ComparisonHelper&) const;
514
515         private:
516             const Value& m_valueRef;
517         };
518
519         template< typename T >
520         struct RCSResourceAttributes::IsSupportedTypeHelper
521         {
522             typedef boost::mpl::contains<ValueVariant::types, typename std::decay< T >::type> type;
523         };
524
525         template <typename T>
526         struct RCSResourceAttributes::IndexOfType
527         {
528             typedef typename boost::mpl::find< ValueVariant::types, T >::type iter;
529             typedef typename boost::mpl::begin< ValueVariant::types >::type mpl_begin;
530
531             static constexpr int value = boost::mpl::distance< mpl_begin, iter >::value;
532         };
533
534         /**
535          * @relates RCSResourceAttributes::Type
536          *
537          * Checks if the objects are equal, that is, whether types are exactly same.
538          *
539          * @return true if the objects are equal, false otherwise.
540          */
541         bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&);
542
543         /**
544          * @relates RCSResourceAttributes::Type
545          *
546          * Checks if the objects are not equal, that is, whether types are not exactly same.
547          *
548          * @return true if the objects are not equal, false otherwise.
549          */
550         bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&);
551
552         /**
553          * @relates RCSResourceAttributes::Value
554          *
555          * Checks if the contents are equal, that is,
556          * whether types are matched and underlying values are equal.
557          *
558          * @return true if the contents are equal, false otherwise.
559          */
560         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper&,
561                 const RCSResourceAttributes::Value::ComparisonHelper&);
562
563         /**
564          * @relates RCSResourceAttributes::Value
565          *
566          * Checks if the contents are not equal, that is,
567          * whether types are not matched or underlying values are not equal.
568          *
569          * @return true if the contents are not equal, false otherwise.
570          */
571         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper&,
572                 const RCSResourceAttributes::Value::ComparisonHelper&);
573
574         //! @cond
575         template< typename T >
576         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
577             std::is_constructible< std::string, T >::value, bool >::type
578         operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
579         {
580             return lhs.equals(rhs);
581         }
582
583         template< typename T >
584         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
585                     std::is_constructible< std::string, T >::value, bool >::type
586         operator==(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
587         {
588             return rhs == lhs;
589         }
590
591         template< typename T >
592         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
593                     std::is_constructible< std::string, T >::value, bool >::type
594         operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
595         {
596             return !(lhs == rhs);
597         }
598
599         template< typename T >
600         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
601                     std::is_constructible< std::string, T >::value, bool >::type
602         operator!=(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
603         {
604             return !(rhs == lhs);
605         }
606         //! @endcond
607
608         /**
609           * @relates RCSResourceAttributes
610           *
611           * Checks if the attributes are equal, that is, whether contents are equal.
612           *
613           * @return true if the attributes are equal, false otherwise.
614           */
615         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs);
616
617         /**
618           * @relates RCSResourceAttributes
619           *
620           * Checks if the attributes are not equal, that is, whether contents are not equal.
621           *
622           * @return true if the attributes are not equal, false otherwise.
623           */
624         bool operator!=(const RCSResourceAttributes&, const RCSResourceAttributes&);
625
626         /**
627          * KeyValuePair is a class to access attribute's key and value of an element pointed by
628          * iterators of RCSResourceAttributes.
629          *
630          *
631          * @see RCSResourceAttributes
632          * @see iterator
633          * @see const_iterator
634          */
635         class RCSResourceAttributes::KeyValuePair
636         {
637         private:
638             class KeyVisitor: public boost::static_visitor< const std::string& >
639             {
640             public:
641                 result_type operator()(iterator*) const;
642                 result_type operator()(const_iterator*) const;
643             };
644
645             class ValueVisitor: public boost::static_visitor< Value& >
646             {
647             public:
648                 result_type operator()(iterator*);
649                 result_type operator()(const_iterator*);
650             };
651
652             class ConstValueVisitor: public boost::static_visitor< const Value& >
653             {
654             public:
655                 result_type operator()(iterator*) const;
656                 result_type operator()(const_iterator*) const;
657             };
658
659         public:
660             const std::string& key() const;
661             const RCSResourceAttributes::Value& value() const;
662             RCSResourceAttributes::Value& value();
663
664         private:
665             KeyValuePair(const KeyValuePair&) = default;
666             KeyValuePair(boost::variant< iterator*, const_iterator* >&&);
667
668             KeyValuePair& operator=(const KeyValuePair&) = default;
669
670         private:
671             boost::variant< iterator*, const_iterator* > m_iterRef;
672
673             KeyVisitor m_keyVisitor;
674             ValueVisitor m_valueVisitor;
675             ConstValueVisitor m_constValueVisitor;
676
677             //! @cond
678             friend class iterator;
679             friend class const_iterator;
680             //! @endcond
681         };
682
683         /**
684          * A forward iterator to KeyValuePair.
685          *
686          * @see RCSResourceAttributes
687          * @see KeyValuePair
688          * @see const_iterator
689          */
690         class RCSResourceAttributes::iterator:
691                 public std::iterator< std::forward_iterator_tag, RCSResourceAttributes::KeyValuePair >
692         {
693         private:
694             typedef std::unordered_map< std::string, Value >::iterator base_iterator;
695
696         public:
697             iterator();
698             iterator(const iterator&) = default;
699
700             iterator& operator=(const iterator&) = default;
701
702             reference operator*();
703             pointer operator->();
704
705             iterator& operator++();
706             iterator operator++(int);
707
708             bool operator==(const iterator&) const;
709             bool operator!=(const iterator&) const;
710
711         private:
712             explicit iterator(base_iterator&&);
713
714         private:
715             base_iterator m_cur;
716             RCSResourceAttributes::KeyValuePair m_keyValuePair;
717
718             //! @cond
719             friend class RCSResourceAttributes;
720             //! @endcond
721         };
722
723
724         /**
725          * A forward iterator to const KeyValuePair.
726          *
727          * @see RCSResourceAttributes
728          * @see KeyValuePair
729          * @see iterator
730          */
731         class RCSResourceAttributes::const_iterator:
732                 public std::iterator < std::forward_iterator_tag,
733                                        const RCSResourceAttributes::KeyValuePair >
734         {
735         private:
736             typedef std::unordered_map< std::string, Value >::const_iterator base_iterator;
737
738         public:
739             const_iterator();
740             const_iterator(const const_iterator&) = default;
741             const_iterator(const RCSResourceAttributes::iterator&);
742
743             const_iterator& operator=(const const_iterator&) = default;
744             const_iterator& operator=(const RCSResourceAttributes::iterator&);
745
746             reference operator*() const;
747             pointer operator->() const;
748
749             const_iterator& operator++();
750             const_iterator operator++(int);
751
752             bool operator==(const const_iterator&) const;
753             bool operator!=(const const_iterator&) const;
754
755         private:
756             explicit const_iterator(base_iterator&&);
757
758         private:
759             base_iterator m_cur;
760             RCSResourceAttributes::KeyValuePair m_keyValuePair;
761
762             //! @cond
763             friend class RCSResourceAttributes;
764             //! @endcond
765         };
766
767     }
768 }
769
770 #endif // RES_ENCAPSULATION_RESOURCEATTRIBUTES_H