Use `URI` all caps in documentation
[iotivity.git] / service / resource-encapsulation / include / RCSResourceObject.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 RCSResourceObject
25  */
26 #ifndef SERVER_RCSRESOURCEOBJECT_H
27 #define SERVER_RCSRESOURCEOBJECT_H
28
29 #include <string>
30 #include <mutex>
31 #include <thread>
32 #include <map>
33
34 #include "RCSResourceAttributes.h"
35 #include "RCSResponse.h"
36
37 namespace OC
38 {
39     class OCResourceRequest;
40 }
41
42 namespace OIC
43 {
44     namespace Service
45     {
46
47         class RCSRequest;
48         class RCSRepresentation;
49         class InterfaceHandler;
50
51         /**
52          * @brief Thrown when lock has not been acquired.
53          *
54          * @see RCSResourceObject::LockGuard
55          * @see RCSResourceObject::getAttributes
56          */
57         class NoLockException: public RCSException
58         {
59             public:
60                 NoLockException(std::string what) : RCSException { std::move(what) } {}
61         };
62
63         //! @cond
64         template < typename T >
65         class AtomicWrapper;
66         //! @endcond
67
68         /**
69          * This class represents a resource and handles any requests from clients
70          * automatically with attributes.
71          *
72          * It also provides an auto notification mechanism that notifies to the observers.
73          *
74          * Requests are handled automatically by defaultAction of RCSGetResponse and
75          * RCSSetResponse. You can override them and send your own response.
76          * <p>
77          * For simple resources, they are simply required to notify whenever attributes are changed
78          * by a set request. In this case, add an AttributeUpdatedListener with a key interested
79          * in instead of overriding SetRequestHandler.
80          * </p>
81          */
82
83         class RCSResourceObject
84         {
85         private:
86
87             typedef AtomicWrapper< std::thread::id > AtomicThreadId;
88
89         //! @cond
90         class WeakGuard
91         {
92         public:
93             WeakGuard(const RCSResourceObject&);
94             ~WeakGuard();
95
96             WeakGuard(const WeakGuard&) = delete;
97             WeakGuard(WeakGuard&&) = delete;
98
99             WeakGuard& operator=(const WeakGuard&) = delete;
100             WeakGuard& operator=(WeakGuard&&) = delete;
101
102             bool hasLocked() const;
103
104         private:
105             bool m_isOwningLock;
106             const RCSResourceObject& m_resourceObject;
107         };
108         //! @endcond
109
110         public:
111
112             /**
113              * Represents the policy of auto-notify function.
114              * In accord with this policy, observers are notified of attributes
115              * when the attributes are set.
116              *
117              * @note Attributes are set according to the execution of some functions which
118              * modify attributes or receipt of set requests.
119              *
120              * @see RCSResourceObject::setAttribute
121              * @see RCSResourceObject::removeAttribute
122              * @see RCSResourceObject::getAttributes
123              * @see RCSResourceObject::LockGuard
124              */
125             enum class AutoNotifyPolicy
126             {
127                 NEVER,  /**< Never*/
128                 ALWAYS, /**< Always*/
129                 UPDATED /**< Only when attributes are changed*/
130             };
131
132             /**
133              * Represents the policy of set-request handler.
134              * In accord with this, the RCSResourceObject decides whether a set-request is
135              * acceptable or not.
136              */
137             enum class SetRequestHandlerPolicy
138             {
139                 NEVER,     /**< Requests will be ignored if attributes of the request contain
140                                 a new key or a value that has different type from the current
141                                 value of the key. */
142                 ACCEPTANCE /**< The attributes of the request will be applied unconditionally
143                                 even if there are new name or type conflicts. */
144             };
145
146             typedef std::shared_ptr< RCSResourceObject > Ptr;
147             typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
148
149             /**
150              * This is a builder to create resource with properties and attributes.
151              *
152              * The resource will be observable and discoverable by default, to make them disable
153              * set these properties explicitly with setDiscoverable and setObservable.
154              *
155              * "oic.if.baseline" is an interface that a resource always holds, by default,
156              * even it is not added manually.
157              */
158             class Builder
159             {
160             public:
161                 /**
162                  * Constructs a Builder.
163                  *
164                  * @param uri Resource URI
165                  * @param type Resource type
166                  * @param interface Resource interface
167                  *
168                  */
169                 Builder(std::string uri, std::string type, std::string interface);
170
171                 /**
172                  * Add an interface for the resource.
173                  *
174                  * @param interface new interface.
175                  */
176                 Builder& addInterface(std::string interface);
177
178                 /**
179                  * Add a type for the resource.
180                  *
181                  * @param type new type.
182                  */
183                 Builder& addType(std::string type);
184
185                 /**
186                  * Sets the default interface.
187                  * If it is not called, the interface passed to the constructor is the default.
188                  *
189                  * @param interface default interface name
190                  *
191                  */
192                 Builder& setDefaultInterface(std::string interface);
193
194                 /**
195                  * Sets whether the resource is discoverable.
196                  *
197                  * @param discoverable whether to be discoverable.
198                  *
199                  */
200                 Builder& setDiscoverable(bool discoverable);
201
202                 /**
203                  * Sets the observable property of the resource.
204                  *
205                  * @param observable whether to be observable.
206                  *
207                  */
208                 Builder& setObservable(bool observable);
209
210                 /**
211                  * Sets whether the resource should be secure or not.
212                  *
213                  * @param secureFlag whether to be secure or not.
214                  *
215                  */
216                 Builder& setSecureFlag(bool secureFlag);
217
218                 /**
219                  * Sets attributes for the resource.
220                  *
221                  * @param attributes attributes to set
222                  *
223                  */
224                 Builder& setAttributes(const RCSResourceAttributes &attributes);
225
226                 /**
227                  * @overload
228                  */
229                 Builder& setAttributes(RCSResourceAttributes &&attributes);
230
231                 /**
232                  * Register a resource and returns a RCSResourceObject.
233                  *
234                  * @throw RCSPlatformException if resource registration is failed.
235                  *
236                  */
237                 RCSResourceObject::Ptr build();
238
239             private:
240                 std::string m_uri;
241                 std::vector< std::string > m_types;
242                 std::vector< std::string > m_interfaces;
243                 std::string m_defaultInterface;
244                 uint8_t m_properties;
245                 RCSResourceAttributes m_resourceAttributes;
246             };
247
248             class LockGuard;
249
250             /**
251              * Callback definition for a handler to be invoked when a get request is received.
252              *
253              * The handler will be called first when a get request is received, before the
254              * RCSResourceObject handles.
255              *
256              * @param request the request information
257              * @param attributes attributes of the request
258              *
259              * @return response to be sent and that indicates how the request to be handled by
260              *         the RCSResourceObject.
261              *
262              * @see setGetRequestHandler
263              */
264             typedef std::function < RCSGetResponse(const RCSRequest& request,
265                     RCSResourceAttributes& attributes) > GetRequestHandler;
266
267             /**
268              * Callback definition for a handler to be invoked when a set request is received.
269              *
270              * The handler will be called first when a get request is received, before the
271              * RCSResourceObject handles. If the attributes are modified in the callback,
272              * the modified attributes will be set in the RCSResourceObject if the request is
273              * not ignored.
274              *
275              * @param request the request information
276              * @param attributes attributes of the request
277              *
278              * @return response to be sent and that indicates how the request to be handled by
279              *         the RCSResourceObject.
280              *
281              * @see setGetRequestHandler
282              */
283             typedef std::function < RCSSetResponse(const RCSRequest& request,
284                     RCSResourceAttributes& attributes) > SetRequestHandler;
285
286             /**
287              * Callback definition to be invoked when an attribute is updated.
288              *
289              * @param oldValue the value before being changed
290              * @param newValue changed value
291              */
292             typedef std::function < void(const RCSResourceAttributes::Value& oldValue,
293                         const RCSResourceAttributes::Value& newValue) > AttributeUpdatedListener;
294
295         public:
296             RCSResourceObject(RCSResourceObject&&) = delete;
297             RCSResourceObject(const RCSResourceObject&) = delete;
298
299             RCSResourceObject& operator=(RCSResourceObject&&) = delete;
300             RCSResourceObject& operator=(const RCSResourceObject&) = delete;
301
302             virtual ~RCSResourceObject();
303
304             /**
305              * Sets a particular attribute value.
306              *
307              * @param key key of attribute
308              * @param value value to be mapped against the key
309              *
310              * @note Thread-safety is guaranteed for the attributes.
311              */
312             void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
313
314             /**
315              * @overload
316              */
317             void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
318
319             /**
320              * @overload
321              */
322             void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
323
324             /**
325              * @overload
326              */
327             void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
328
329             /**
330              * Returns an attribute value corresponding to a key.
331              *
332              * @param key key of the attribute
333              *
334              * @throws RCSInvalidKeyException If key is invalid.
335              *
336              * @note Thread-safety is guaranteed for the attributes.
337              */
338             RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
339
340             /**
341              * Returns the attribute value as T.
342              *
343              * @param key key of the attribute
344              *
345              * @throws RCSBadGetException If type of the underlying value is not T.
346              * @throws RCSInvalidKeyException If @a key doesn't match the key of any value.
347              *
348              * @note Thread-safety is guaranteed for the attributes.
349              */
350             template< typename T >
351             T getAttribute(const std::string& key) const
352             {
353                 RCSResourceObject::WeakGuard lock(*this);
354                 return m_resourceAttributes.at(key).get< T >();
355             }
356
357             /**
358              * Removes a particular attribute of the resource.
359              *
360              * @param key key of the attribute.
361              *
362              * @return True if the key exists and matched attribute is removed, otherwise false.
363              *
364              * @note Thread-safety is guaranteed for the attributes.
365              */
366             bool removeAttribute(const std::string& key);
367
368             /**
369              * Checks whether a particular attribute exists or not.
370              *
371              * @param key key of the attribute
372              *
373              * @return True if the key exists, otherwise false.
374              *
375              * @note Thread-safety is guaranteed for the attributes.
376              */
377             bool containsAttribute(const std::string& key) const;
378
379             /**
380              * Returns reference to the attributes of the RCSResourceObject.
381              *
382              * @pre The call must be guarded by LockGuard.
383              *
384              *
385              * @return Reference to the attributes
386              *
387              * @throws NoLockException If the call is not guarded by LockGuard.
388              *
389              * @note Here is the standard idiom for LockGuard:
390              * @code
391                {
392                   RCSResourceObject::LockGuard lock(rcsResourceObject);
393
394                   auto &attributes = server->getAttributes();
395                   ...
396                }
397              * @endcode
398              */
399             RCSResourceAttributes& getAttributes();
400
401             /**
402              * @overload
403              */
404             const RCSResourceAttributes& getAttributes() const;
405
406             /**
407              * Checks whether the resource is observable or not.
408              */
409             virtual bool isObservable() const;
410
411             /**
412              * Checks whether the resource is discoverable or not.
413              */
414             virtual bool isDiscoverable() const;
415
416             /**
417              * Sets the get request handler.
418              * To remove handler, pass empty handler or nullptr.
419              *
420              * Default behavior is RCSGetResponse::defaultAction().
421              *
422              * @param handler a get request handler
423              *
424              * @see RCSGetResponse
425              *
426              */
427             virtual void setGetRequestHandler(GetRequestHandler handler);
428
429             /**
430              * Sets the set request handler.
431              * To remove handler, pass empty handler or nullptr.
432              *
433              * Default behavior is RCSSetResponse::defaultAction().
434              *
435              * @param handler a set request handler
436              *
437              * @see RCSSetResponse
438              *
439              */
440             virtual void setSetRequestHandler(SetRequestHandler handler);
441
442             /**
443              * Adds a listener for a particular attribute updated.
444              *
445              * @param key the interested attribute's key
446              * @param listener listener to be invoked
447              *
448              */
449             virtual void addAttributeUpdatedListener(const std::string& key,
450                     AttributeUpdatedListener listener);
451
452             /**
453              * @overload
454              */
455             virtual void addAttributeUpdatedListener(std::string&& key,
456                     AttributeUpdatedListener listener);
457
458             /**
459              * Removes a listener for a particular attribute updated.
460              *
461              * @param key the key associated with the listener to be removed
462              *
463              * @return True if the listener added with same key exists and is removed.
464              *
465              */
466             virtual bool removeAttributeUpdatedListener(const std::string& key);
467
468             /**
469              * Notifies all observers of the current attributes.
470              *
471              * @throws RCSPlatformException If the operation failed.
472              */
473             virtual void notify() const;
474
475             /**
476              * Sets auto notify policy
477              *
478              * @param policy policy to be set
479              *
480              */
481             void setAutoNotifyPolicy(AutoNotifyPolicy policy);
482
483             /**
484              * Returns the current policy
485              *
486              */
487             AutoNotifyPolicy getAutoNotifyPolicy() const;
488
489             /**
490              * Sets the policy for handling a set request.
491              *
492              * @param policy policy to be set
493              *
494              */
495             void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
496
497             /**
498              * Returns the current policy.
499              *
500              */
501             SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
502
503             /**
504              * Bind a resource to this resource.
505              * Binding another resource makes this resource work as a collection resource,
506              * by default.
507              *
508              * @param resource a resource to be bound to this resource.
509              *
510              * @throws RCSInvalidParameterException If resource is nullptr or itself.
511              * @throws RCSPlatformException If the operation failed.
512              *
513              * @see unbindResource
514              */
515             void bindResource(const RCSResourceObject::Ptr& resource);
516
517             /**
518              * Unbind a resource from this resource.
519              * If there is no bound resource left, the resource will run as a normal resource.
520              *
521              * @param resource a resource to be unbound from this resource.
522              *
523              * @throws RCSInvalidParameterException If resource is nullptr or itself.
524              * @throws RCSPlatformException If the operation failed.
525              *
526              * @see bindResource
527              */
528             void unbindResource(const RCSResourceObject::Ptr& resource);
529
530             /**
531              * Returns all bound resources to this resource.
532              */
533             std::vector< RCSResourceObject::Ptr > getBoundResources() const;
534
535             /**
536              * Returns the URI of the resource.
537              */
538             std::string getUri() const;
539
540             /**
541              * Returns the default interface of the resource
542              *
543              * @see Builder::setDefaultInterface
544              */
545             std::string getDefaultInterface() const;
546
547             /**
548              * Returns all interfaces added for the resource.
549              *
550              * @see Builder::addInterface
551              */
552             std::vector< std::string > getInterfaces() const;
553
554             /**
555              * Returns all types added for the resource.
556              *
557              * @see Builder::addType
558              */
559             std::vector< std::string > getTypes() const;
560
561             /**
562              * Returns the resource handle of the resource.
563              */
564              OCResourceHandle getResourceHandle() const;
565
566         private:
567             RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&);
568
569             void init(OCResourceHandle, const std::vector< std::string >&,
570                     const std::vector< std::string >&, const std::string&);
571
572             static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&,
573                     const std::shared_ptr< OC::OCResourceRequest >&);
574
575             OCEntityHandlerResult handleRequest(const RCSRequest&);
576             OCEntityHandlerResult handleRequestGet(const RCSRequest&);
577             OCEntityHandlerResult handleRequestSet(const RCSRequest&);
578             OCEntityHandlerResult handleObserve(const RCSRequest&);
579
580             template <typename RESPONSE, typename RESPONSE_BUILDER>
581             OCEntityHandlerResult sendResponse(const RCSRequest&,
582                      const RESPONSE&, const RESPONSE_BUILDER&);
583
584             void expectOwnLock() const;
585
586             std::thread::id getLockOwner() const noexcept;
587
588             void setLockOwner(std::thread::id&&) const noexcept;
589
590             void autoNotify(bool, AutoNotifyPolicy) const;
591             void autoNotify(bool) const;
592
593             bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
594
595             template< typename K, typename V >
596             void setAttributeInternal(K&&, V&&);
597
598             bool applyAcceptanceMethod(const RCSSetResponse&, const RCSResourceAttributes&);
599
600             InterfaceHandler findInterfaceHandler(const std::string&) const;
601
602             RCSRepresentation getRepresentation(const RCSRequest&) const;
603
604         private:
605             const uint8_t m_properties;
606
607             const std::string m_uri;
608             std::vector< std::string > m_interfaces;
609             std::vector< std::string > m_types;
610             std::string m_defaultInterface;
611
612             OCResourceHandle m_resourceHandle;
613
614             RCSResourceAttributes m_resourceAttributes;
615
616             std::shared_ptr< GetRequestHandler > m_getRequestHandler;
617             std::shared_ptr< SetRequestHandler > m_setRequestHandler;
618
619             AutoNotifyPolicy m_autoNotifyPolicy;
620             SetRequestHandlerPolicy m_setRequestHandlerPolicy;
621
622             std::unordered_map< std::string, std::shared_ptr< AttributeUpdatedListener > >
623                     m_attributeUpdatedListeners;
624
625             mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
626             mutable std::mutex m_mutex;
627
628             std::mutex m_mutexAttributeUpdatedListeners;
629
630             mutable std::mutex m_mutexForBoundResources;
631
632             std::vector< RCSResourceObject::Ptr > m_boundResources;
633
634             std::map< std::string, InterfaceHandler > m_interfaceHandlers;
635
636             friend class RCSSeparateResponse;
637         };
638
639         /**
640          * The class provides a convenient RAII-style mechanism for the attributes of a
641          * RCSResourceObject. When a LockGuard is created, it attempts to lock the attributes of
642          * the RCSResourceObject it is given. When control leaves the scope in which the LockGuard
643          * object was created, the LockGuard is destructed and the attributes is unlocked.
644          *
645          * Additionally when it is destructed and only when destructed not by stack unwinding
646          * caused by an exception, it tries to notify depending on AutoNotifyPolicy.
647          *
648          * @note The destrcutor can throw an exception if auto notify failed.
649          */
650         class RCSResourceObject::LockGuard
651         {
652         public:
653             LockGuard(const RCSResourceObject& rcsResourceObject);
654
655             LockGuard(const RCSResourceObject::Ptr);
656
657            /**
658             * Constructs a LockGuard with auto notify policy.
659             *
660             * @param object an object to be locked
661             * @param autoNotifyPolicy the policy to indicate how auto notification is handled
662             *        when the LockGuard is destructed.
663             *
664             */
665             LockGuard(const RCSResourceObject& object, AutoNotifyPolicy autoNotifyPolicy);
666
667            /**
668             * @overload
669             */
670             LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
671
672             /**
673              * @throws RCSPlatformException If auto notify operation failed.
674              *
675              * @note The exception will never be thrown while stack unwinding.
676              */
677             ~LockGuard() noexcept(false);
678
679             LockGuard(const LockGuard&) = delete;
680             LockGuard(LockGuard&&) = delete;
681
682             LockGuard& operator=(const LockGuard&) = delete;
683             LockGuard& operator=(LockGuard&&) = delete;
684
685         private:
686             void init();
687
688         private:
689             const RCSResourceObject& m_resourceObject;
690
691             AutoNotifyPolicy m_autoNotifyPolicy;
692
693             bool m_isOwningLock;
694
695             std::function<void()> m_autoNotifyFunc;
696         };
697
698     }
699 }
700
701 #endif // SERVER_RCSRESOURCEOBJECT_H