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