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