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