Merge commit 'Imported Upstream version 1.0.0' into tizen
[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         //! @cond
604         template< typename T >
605         struct RCSResourceAttributes::IsSupportedTypeHelper
606         {
607             typedef boost::mpl::contains< ValueVariant::types, typename std::decay< T >::type > type;
608         };
609
610         template < typename T >
611         struct RCSResourceAttributes::IndexOfType
612         {
613             static_assert(RCSResourceAttributes::is_supported_type< T >::value,
614                 "The type is not supported!");
615
616             typedef typename boost::mpl::find< ValueVariant::types, T >::type iter;
617             typedef typename boost::mpl::begin< ValueVariant::types >::type mpl_begin;
618
619             static constexpr int value = boost::mpl::distance< mpl_begin, iter >::value;
620         };
621
622         template < typename T > constexpr int RCSResourceAttributes::IndexOfType< T >::value;
623         //! @endcond
624
625         /**
626          * @relates RCSResourceAttributes::Type
627          *
628          * Checks if the objects are equal, that is, whether types are exactly same.
629          *
630          * @return true if the objects are equal, false otherwise.
631          */
632         bool operator==(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
633                 noexcept;
634
635         /**
636          * @relates RCSResourceAttributes::Type
637          *
638          * Checks if the objects are not equal, that is, whether types are not exactly same.
639          *
640          * @return true if the objects are not equal, false otherwise.
641          */
642         bool operator!=(const RCSResourceAttributes::Type&, const RCSResourceAttributes::Type&)
643                 noexcept;
644
645         /**
646          * @relates RCSResourceAttributes::Value
647          *
648          * Checks if the contents are equal, that is,
649          * whether types are matched and underlying values are equal.
650          *
651          * @return true if the contents are equal, false otherwise.
652          */
653         bool operator==(const RCSResourceAttributes::Value::ComparisonHelper&,
654                 const RCSResourceAttributes::Value::ComparisonHelper&);
655
656         /**
657          * @relates RCSResourceAttributes::Value
658          *
659          * Checks if the contents are not equal, that is,
660          * whether types are not matched or underlying values are not equal.
661          *
662          * @return true if the contents are not equal, false otherwise.
663          */
664         bool operator!=(const RCSResourceAttributes::Value::ComparisonHelper&,
665                 const RCSResourceAttributes::Value::ComparisonHelper&);
666
667         //! @cond
668         template< typename T >
669         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
670             std::is_constructible< std::string, T >::value, bool >::type
671         operator==(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
672         {
673             return lhs.equals(rhs);
674         }
675
676         template< typename T >
677         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
678                     std::is_constructible< std::string, T >::value, bool >::type
679         operator==(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
680         {
681             return rhs == lhs;
682         }
683
684         template< typename T >
685         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
686                     std::is_constructible< std::string, T >::value, bool >::type
687         operator!=(const RCSResourceAttributes::Value::ComparisonHelper& lhs, const T& rhs)
688         {
689             return !(lhs == rhs);
690         }
691
692         template< typename T >
693         typename std::enable_if< RCSResourceAttributes::is_supported_type< T >::value ||
694                     std::is_constructible< std::string, T >::value, bool >::type
695         operator!=(const T& lhs, const RCSResourceAttributes::Value::ComparisonHelper& rhs)
696         {
697             return !(rhs == lhs);
698         }
699         //! @endcond
700
701         /**
702           * @relates RCSResourceAttributes
703           *
704           * Checks if the attributes are equal, that is, whether contents are equal.
705           *
706           * @return true if the attributes are equal, false otherwise.
707           */
708         bool operator==(const RCSResourceAttributes& lhs, const RCSResourceAttributes& rhs);
709
710         /**
711           * @relates RCSResourceAttributes
712           *
713           * Checks if the attributes are not equal, that is, whether contents are not equal.
714           *
715           * @return true if the attributes are not equal, false otherwise.
716           */
717         bool operator!=(const RCSResourceAttributes&, const RCSResourceAttributes&);
718
719         /**
720          * KeyValuePair is a class to access attribute's key and value of an element pointed by
721          * iterators of RCSResourceAttributes.
722          *
723          *
724          * @see RCSResourceAttributes
725          * @see iterator
726          * @see const_iterator
727          */
728         class RCSResourceAttributes::KeyValuePair
729         {
730         private:
731             class KeyVisitor: public boost::static_visitor< const std::string& >
732             {
733             public:
734                 result_type operator()(iterator*) const noexcept;
735                 result_type operator()(const_iterator*) const noexcept;
736             };
737
738             class ValueVisitor: public boost::static_visitor< Value& >
739             {
740             public:
741                 result_type operator()(iterator*) noexcept;
742                 result_type operator()(const_iterator*);
743             };
744
745             class ConstValueVisitor: public boost::static_visitor< const Value& >
746             {
747             public:
748                 result_type operator()(iterator*) const noexcept;
749                 result_type operator()(const_iterator*) const noexcept;
750             };
751
752         public:
753             const std::string& key() const noexcept;
754             const RCSResourceAttributes::Value& value() const noexcept;
755             RCSResourceAttributes::Value& value();
756
757         private:
758             KeyValuePair(const KeyValuePair&) = default;
759             KeyValuePair(boost::variant< iterator*, const_iterator* >&&) noexcept;
760
761             KeyValuePair& operator=(const KeyValuePair&) = default;
762
763         private:
764             boost::variant< iterator*, const_iterator* > m_iterRef;
765
766             KeyVisitor m_keyVisitor;
767             ValueVisitor m_valueVisitor;
768             ConstValueVisitor m_constValueVisitor;
769
770             //! @cond
771             friend class iterator;
772             friend class const_iterator;
773             //! @endcond
774         };
775
776         /**
777          * A forward iterator to KeyValuePair.
778          *
779          * @see RCSResourceAttributes
780          * @see KeyValuePair
781          * @see const_iterator
782          */
783         class RCSResourceAttributes::iterator:
784                 public std::iterator< std::forward_iterator_tag, RCSResourceAttributes::KeyValuePair >
785         {
786         private:
787             typedef std::unordered_map< std::string, Value >::iterator base_iterator;
788
789         public:
790             iterator();
791             iterator(const iterator&) = default;
792
793             iterator& operator=(const iterator&) = default;
794
795             reference operator*();
796             pointer operator->();
797
798             iterator& operator++();
799             iterator operator++(int);
800
801             bool operator==(const iterator&) const;
802             bool operator!=(const iterator&) const;
803
804         private:
805             explicit iterator(base_iterator&&);
806
807         private:
808             base_iterator m_cur;
809             RCSResourceAttributes::KeyValuePair m_keyValuePair;
810
811             //! @cond
812             friend class RCSResourceAttributes;
813             //! @endcond
814         };
815
816
817         /**
818          * A forward iterator to const KeyValuePair.
819          *
820          * @see RCSResourceAttributes
821          * @see KeyValuePair
822          * @see iterator
823          */
824         class RCSResourceAttributes::const_iterator:
825                 public std::iterator < std::forward_iterator_tag,
826                                        const RCSResourceAttributes::KeyValuePair >
827         {
828         private:
829             typedef std::unordered_map< std::string, Value >::const_iterator base_iterator;
830
831         public:
832             const_iterator();
833             const_iterator(const const_iterator&) = default;
834             const_iterator(const RCSResourceAttributes::iterator&);
835
836             const_iterator& operator=(const const_iterator&) = default;
837             const_iterator& operator=(const RCSResourceAttributes::iterator&);
838
839             reference operator*() const;
840             pointer operator->() const;
841
842             const_iterator& operator++();
843             const_iterator operator++(int);
844
845             bool operator==(const const_iterator&) const;
846             bool operator!=(const const_iterator&) const;
847
848         private:
849             explicit const_iterator(base_iterator&&);
850
851         private:
852             base_iterator m_cur;
853             RCSResourceAttributes::KeyValuePair m_keyValuePair;
854
855             //! @cond
856             friend class RCSResourceAttributes;
857             //! @endcond
858         };
859
860     }
861 }
862
863 #endif // RES_ENCAPSULATION_RESOURCEATTRIBUTES_H