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