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