Change file permission of RCSResourceObject.h file
[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
33 #include <RCSResourceAttributes.h>
34 #include <RCSResponse.h>
35 #include <RCSRequest.h>
36
37 namespace OC
38 {
39     class OCResourceRequest;
40 }
41
42 namespace OIC
43 {
44     namespace Service
45     {
46
47         /**
48          * @brief Thrown when lock has not been acquired.
49          *
50          * @see RCSResourceObject::LockGuard
51          * @see RCSResourceObject::getAttributes
52          */
53         class NoLockException: public RCSException
54         {
55             public:
56                 NoLockException(std::string &&what) : RCSException { std::move(what) } {}
57         };
58
59         //! @cond
60         template < typename T >
61         class AtomicWrapper;
62         //! @endcond
63
64         /**
65          * RCSResourceObject represents a resource and handles any requests from clients
66          * automatically with attributes.
67          *
68          * It also provides an auto notification mechanism that notifies to the observers.
69          *
70          * Requests are handled automatically by defaultAction of RCSGetResponse and
71          * RCSSetResponse. You can override them and send your own response.
72          * <p>
73          * For simple resources, they are simply required to notify whenever attributes are changed
74          * by a set request. In this case, add an AttributeUpdatedListener with a key interested
75          * in instead of overriding SetRequestHandler.
76          * </p>
77          */
78         class RCSResourceObject
79         {
80             private:
81                 class WeakGuard;
82
83                 typedef AtomicWrapper< std::thread::id > AtomicThreadId;
84
85             public:
86                 /**
87                  * Represents the policy of auto-notify function.
88                  * In accord with this policy, observers are notified of attributes
89                  * when the attributes are set.
90                  *
91                  * @note Attributes are set according to the execution of some functions which
92                  * modify attributes or receipt of set requests.
93                  *
94                  * @see RCSResourceObject::setAttribute
95                  * @see RCSResourceObject::removeAttribute
96                  * @see RCSResourceObject::getAttributes
97                  * @see RCSResourceObject::LockGuard
98                  */
99                 enum class AutoNotifyPolicy
100                 {
101                     NEVER,  /**< Never*/
102                     ALWAYS, /**< Always*/
103                     UPDATED /**< Only when attributes are changed*/
104                 };
105
106                 /**
107                  * Represents the policy of set-request handler.
108                  * In accord with this, the RCSResourceObject decides whether a set-request is
109                  * acceptable or not.
110                  */
111                 enum class SetRequestHandlerPolicy
112                 {
113                     NEVER,     /**< Requests will be ignored if attributes of the request contain
114                                     a new key or a value that has different type from the current
115                                     value of the key. */
116                     ACCEPTANCE /**< The attributes of the request will be applied unconditionally
117                                     even if there are new name or type conflicts. */
118                 };
119
120                 typedef std::shared_ptr< RCSResourceObject > Ptr;
121                 typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
122
123                 /**
124                  * This is a builder to create resource with properties and attributes.
125                  *
126                  * The resource will be observable and discoverable by default, to make them disable
127                  * set these properties explicitly with setDiscoverable and setObservable.
128                  */
129                 class Builder
130                 {
131                     public:
132                         /**
133                          * Constructs a Builder.
134                          *
135                          * @param uri Resource uri
136                          * @param type Resource type
137                          * @param interface Resource interface
138                          *
139                          */
140                         Builder(const std::string& uri, const std::string& type,
141                                 const std::string& interface);
142
143                         /**
144                          * Sets whether the resource is discoverable.
145                          *
146                          * @param discoverable whether to be discoverable.
147                          *
148                          */
149                         Builder& setDiscoverable(bool discoverable);
150
151                         /**
152                          * Sets the observable property of the resource.
153                          *
154                          * @param observable whether to be observable.
155                          *
156                          */
157                         Builder& setObservable(bool observable);
158
159                         /**
160                          * Sets attributes for the resource.
161                          *
162                          * @param attributes attributes to set
163                          *
164                          */
165                         Builder& setAttributes(const RCSResourceAttributes &attributes);
166
167                         /**
168                          * @overload
169                          */
170                         Builder& setAttributes(RCSResourceAttributes &&attributes);
171
172                         /**
173                          * Register a resource and returns a RCSResourceObject.
174                          *
175                          * @throw RCSPlatformException if resource registration is failed.
176                          *
177                          */
178                         RCSResourceObject::Ptr build();
179
180                     private:
181                         std::string m_uri;
182                         std::string m_type;
183                         std::string m_interface;
184                         uint8_t m_properties;
185                         RCSResourceAttributes m_resourceAttributes;
186                 };
187
188                 class LockGuard;
189
190                 /**
191                  * Callback definition for a handler to be invoked when a get request is received.
192                  *
193                  * The handler will be called first when a get request is received, before the
194                  * RCSResourceObject handles.
195                  *
196                  * @param request the request information
197                  * @param attributes attributes of the request
198                  *
199                  * @return response to be sent and that indicates how the request to be handled by
200                  *         the RCSResourceObject.
201                  *
202                  * @see setGetRequestHandler
203                  */
204                 typedef std::function < RCSGetResponse(const RCSRequest& request,
205                         RCSResourceAttributes& attributes) > GetRequestHandler;
206
207                 /**
208                  * Callback definition for a handler to be invoked when a set request is received.
209                  *
210                  * The handler will be called first when a get request is received, before the
211                  * RCSResourceObject handles. If the attributes are modified in the callback,
212                  * the modified attributes will be set in the RCSResourceObject if the request is
213                  * not ignored.
214                  *
215                  * @param request the request information
216                  * @param attributes attributes of the request
217                  *
218                  * @return response to be sent and that indicates how the request to be handled by
219                  *         the RCSResourceObject.
220                  *
221                  * @see setGetRequestHandler
222                  */
223                 typedef std::function < RCSSetResponse(const RCSRequest& request,
224                         RCSResourceAttributes& attributes) > SetRequestHandler;
225
226                 /**
227                  * Callback definition to be invoked when an attribute is updated.
228                  *
229                  * @param oldValue the value before being changed
230                  * @param newValue changed value
231                  */
232                 typedef std::function < void(const RCSResourceAttributes::Value& oldValue,
233                             const RCSResourceAttributes::Value& newValue) > AttributeUpdatedListener;
234
235             public:
236                 RCSResourceObject(RCSResourceObject&&) = delete;
237                 RCSResourceObject(const RCSResourceObject&) = delete;
238
239                 RCSResourceObject& operator=(RCSResourceObject&&) = delete;
240                 RCSResourceObject& operator=(const RCSResourceObject&) = delete;
241
242                 virtual ~RCSResourceObject();
243
244                 /**
245                  * Sets a particular attribute value.
246                  *
247                  * @param key key of attribute
248                  * @param value value to be mapped against the key
249                  *
250                  * @note Thread-safety is guaranteed for the attributes.
251                  */
252                 void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
253
254                 /**
255                  * @overload
256                  */
257                 void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
258
259                 /**
260                  * @overload
261                  */
262                 void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
263
264                 /**
265                  * @overload
266                  */
267                 void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
268
269                 /**
270                  * Returns an attribute value corresponding to a key.
271                  *
272                  * @param key key of the attribute
273                  *
274                  * @throws RCSInvalidKeyException If key is invalid.
275                  *
276                  * @note Thread-safety is guaranteed for the attributes.
277                  */
278                 RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
279
280                 /**
281                  * Returns the attribute value as T.
282                  *
283                  * @param key key of the attribute
284                  *
285                  * @throws RCSBadGetException If type of the underlying value is not T.
286                  * @throws RCSInvalidKeyException If @a key doesn't match the key of any value.
287                  *
288                  * @note Thread-safety is guaranteed for the attributes.
289                  */
290                 template< typename T >
291                 T getAttribute(const std::string& key) const
292                 {
293                     WeakGuard lock(*this);
294                     return m_resourceAttributes.at(key).get< T >();
295                 }
296
297                 /**
298                  * Removes a particular attribute of the resource.
299                  *
300                  * @param key key of the attribute.
301                  *
302                  * @return True if the key exists and matched attribute is removed, otherwise false.
303                  *
304                  * @note Thread-safety is guaranteed for the attributes.
305                  */
306                 bool removeAttribute(const std::string& key);
307
308                 /**
309                  * Checks whether a particular attribute exists or not.
310                  *
311                  * @param key key of the attribute
312                  *
313                  * @return True if the key exists, otherwise false.
314                  *
315                  * @note Thread-safety is guaranteed for the attributes.
316                  */
317                 bool containsAttribute(const std::string& key) const;
318
319                 /**
320                  * Returns reference to the attributes of the RCSResourceObject.
321                  *
322                  * @pre The call must be guarded by LockGuard.
323                  *
324                  *
325                  * @return Reference to the attributes
326                  *
327                  * @throws NoLockException If the call is not guarded by LockGuard.
328                  *
329                  * @note Here is the standard idiom for LockGuard:
330                  * @code
331                    {
332                       RCSResourceObject::LockGuard lock(rcsResourceObject);
333
334                       auto &attributes = server->getAttributes();
335                       ...
336                    }
337                  * @endcode
338                  */
339                 RCSResourceAttributes& getAttributes();
340
341                 /**
342                  * @overload
343                  */
344                 const RCSResourceAttributes& getAttributes() const;
345
346                 /**
347                  * Checks whether the resource is observable or not.
348                  */
349                 virtual bool isObservable() const;
350
351                 /**
352                  * Checks whether the resource is discoverable or not.
353                  */
354                 virtual bool isDiscoverable() const;
355
356                 /**
357                  * Sets the get request handler.
358                  * To remove handler, pass empty handler or nullptr.
359                  *
360                  * Default behavior is RCSGetResponse::defaultAction().
361                  *
362                  * @param handler a get request handler
363                  *
364                  * @see RCSGetResponse
365                  *
366                  */
367                 virtual void setGetRequestHandler(GetRequestHandler handler);
368
369                 /**
370                  * Sets the set request handler.
371                  * To remove handler, pass empty handler or nullptr.
372                  *
373                  * Default behavior is RCSSetResponse::defaultAction().
374                  *
375                  * @param handler a set request handler
376                  *
377                  * @see RCSSetResponse
378                  *
379                  */
380                 virtual void setSetRequestHandler(SetRequestHandler handler);
381
382                 /**
383                  * Adds a listener for a particular attribute updated.
384                  *
385                  * @param key the interested attribute's key
386                  * @param listener listener to be invoked
387                  *
388                  */
389                 virtual void addAttributeUpdatedListener(const std::string& key,
390                         AttributeUpdatedListener listener);
391
392                 /**
393                  * @overload
394                  */
395                 virtual void addAttributeUpdatedListener(std::string&& key,
396                         AttributeUpdatedListener listener);
397
398                 /**
399                  * Removes a listener for a particular attribute updated.
400                  *
401                  * @param key the key associated with the listener to be removed
402                  *
403                  * @return True if the listener added with same key exists and is removed.
404                  *
405                  */
406                 virtual bool removeAttributeUpdatedListener(const std::string& key);
407
408                 /**
409                  * Notifies all observers of the current attributes.
410                  *
411                  * @throws RCSPlatformException If the operation failed.
412                  */
413                 virtual void notify() const;
414
415                 /**
416                  * Sets auto notify policy
417                  *
418                  * @param policy policy to be set
419                  *
420                  */
421                 void setAutoNotifyPolicy(AutoNotifyPolicy policy);
422
423                 /**
424                  * Returns the current policy
425                  *
426                  */
427                 AutoNotifyPolicy getAutoNotifyPolicy() const;
428
429                 /**
430                  * Sets the policy for handling a set request.
431                  *
432                  * @param policy policy to be set
433                  *
434                  */
435                 void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
436
437                 /**
438                  * Returns the current policy.
439                  *
440                  */
441                 SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
442
443         private:
444             RCSResourceObject(uint8_t, RCSResourceAttributes&&);
445
446             OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest >);
447
448             OCEntityHandlerResult handleRequest(std::shared_ptr< OC::OCResourceRequest >);
449             OCEntityHandlerResult handleRequestGet(std::shared_ptr< OC::OCResourceRequest >);
450             OCEntityHandlerResult handleRequestSet(std::shared_ptr< OC::OCResourceRequest >);
451             OCEntityHandlerResult handleObserve(std::shared_ptr< OC::OCResourceRequest >);
452
453             void expectOwnLock() const;
454
455             std::thread::id getLockOwner() const noexcept;
456
457             void setLockOwner(std::thread::id&&) const noexcept;
458
459             void autoNotify(bool, AutoNotifyPolicy) const;
460             void autoNotify(bool) const;
461
462             bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
463
464             template< typename K, typename V >
465             void setAttributeInternal(K&&, V&&);
466
467             bool applyAcceptanceMethod(const RCSSetResponse&, const RCSResourceAttributes&);
468
469         private:
470             const uint8_t m_properties;
471
472             OCResourceHandle m_resourceHandle;
473
474             RCSResourceAttributes m_resourceAttributes;
475
476             GetRequestHandler m_getRequestHandler;
477             SetRequestHandler m_setRequestHandler;
478
479             AutoNotifyPolicy m_autoNotifyPolicy;
480             SetRequestHandlerPolicy m_setRequestHandlerPolicy;
481
482             std::unordered_map< std::string, std::shared_ptr< AttributeUpdatedListener > >
483                     m_attributeUpdatedListeners;
484
485             mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
486             mutable std::mutex m_mutex;
487
488             std::mutex m_mutexAttributeUpdatedListeners;
489
490         };
491
492         /**
493          * The class provides a convenient RAII-style mechanism for the attributes of a
494          * RCSResourceObject. When a LockGuard is created, it attempts to lock the attributes of
495          * the RCSResourceObject it is given. When control leaves the scope in which the LockGuard
496          * object was created, the LockGuard is destructed and the attributes is unlocked.
497          *
498          * Additionally when this is destructed, it tries to notify depending on AutoNotifyPolicy
499          * of the RCSResourceObject.
500          */
501         class RCSResourceObject::LockGuard
502         {
503         public:
504             LockGuard(const RCSResourceObject& rcsResourceObject);
505
506             LockGuard(const RCSResourceObject::Ptr);
507
508            /**
509             * Constructs a LockGuard with auto notify policy.
510             *
511             * @param object an object to be locked
512             * @param autoNotifyPolicy the policy to indicate how auto notification is handled
513             *        when the LockGuard is destructed.
514             *
515             */
516             LockGuard(const RCSResourceObject& object, AutoNotifyPolicy autoNotifyPolicy);
517
518            /**
519             * @overload
520             */
521             LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
522             ~LockGuard();
523
524             LockGuard(const LockGuard&) = delete;
525             LockGuard(LockGuard&&) = delete;
526
527             LockGuard& operator=(const LockGuard&) = delete;
528             LockGuard& operator=(LockGuard&&) = delete;
529
530         private:
531             void init();
532
533         private:
534             const RCSResourceObject& m_resourceObject;
535
536             AutoNotifyPolicy m_autoNotifyPolicy;
537
538             bool m_isOwningLock;
539
540             std::function<void()> m_autoNotifyFunc;
541         };
542
543         //! @cond
544         class RCSResourceObject::WeakGuard
545         {
546         public:
547             WeakGuard(const RCSResourceObject&);
548             ~WeakGuard();
549
550             WeakGuard(const WeakGuard&) = delete;
551             WeakGuard(WeakGuard&&) = delete;
552
553             WeakGuard& operator=(const WeakGuard&) = delete;
554             WeakGuard& operator=(WeakGuard&&) = delete;
555
556             bool hasLocked() const;
557
558         private:
559             bool m_isOwningLock;
560             const RCSResourceObject& m_resourceObject;
561         };
562         //! @endcond
563     }
564 }
565
566 #endif // SERVER_RCSRESOURCEOBJECT_H