Imported Upstream version 0.9.2
[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 resource object APIs provided to the developers.
25  * RCSResourceObject is a part of the server builder module.
26  */
27 #ifndef SERVER_RCSRESOURCEOBJECT_H
28 #define SERVER_RCSRESOURCEOBJECT_H
29
30 #include <string>
31 #include <mutex>
32 #include <thread>
33
34 #include <boost/atomic.hpp>
35
36 #include <RCSResourceAttributes.h>
37 #include <RCSResponse.h>
38 #include <RCSRequest.h>
39
40 namespace OC
41 {
42     class OCResourceRequest;
43 }
44
45 namespace OIC
46 {
47     namespace Service
48     {
49
50         /**
51          * @brief Thrown when lock has not been acquired.
52          *
53          * @see RCSResourceObject::LockGuard
54          * @see RCSResourceObject::getAttributes
55          */
56         class NoLockException: public RCSException
57         {
58             public:
59                 NoLockException(std::string &&what) : RCSException { std::move(what) } {}
60         };
61
62         /**
63          * @brief  RCSResourceObject represents a resource. It handles any requests from
64          *        clients automatically with attributes.
65          *        It also provides an auto notification mechanism that notifies to the observers.
66          *        <br/>
67          *         Requests are handled automatically by defaultAction of RCSGetResponse and
68          *        RCSSetResponse. You can override them and send your own response.
69          *        <br/>
70          *         For simple resources, you may want to know whenever attributes are changed
71          *        by a set request. In this case, add an AttributeUpdatedListener
72          *        with a key interested in instead of overriding SetRequestHandler.
73          */
74         class RCSResourceObject
75         {
76             private:
77                 class WeakGuard;
78
79             public:
80                 /**
81                  * @brief represents the policy of AutoNotify function.
82                  *        In accord with this policy, observers are notified of attributes that
83                  *        are changed or updated.
84                  * @note Attributes are changed or updated according to execution of some functions
85                  *       or receipt of 'set-request'.
86                  *       (functions - RCSResourceObject::setAttribute,
87                  *       RCSResourceObject::removeAttribute, RCSResourceObject::getAttributes)
88                  */
89                 enum class AutoNotifyPolicy
90                 {
91                     NEVER,  /**< Never notify.*/
92                     ALWAYS, /**< Always notify.*/
93                     UPDATED /**< When attributes are changed, notify.*/
94                 };
95
96                 /**
97                  * @brief represents the policy of Set-Request Handler.
98                  *        In accord with this policy, attributes of 'set-request' are created or
99                  *        ignored.
100                  */
101                 enum class SetRequestHandlerPolicy
102                 {
103                     NEVER,     /**< Server ignore when server is received set-request of attributes
104                                     of the new key. */
105                     ACCEPTANCE /**< Server creates attributes of the new key When server is received
106                                     set-request of attributes of the new key. */
107                 };
108
109                 typedef std::shared_ptr< RCSResourceObject > Ptr;
110                 typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
111
112                 /**
113                  * @class   Builder
114                  * @brief   This class provides APIs for resource creation, setting properties &
115                  *          attributes for the constructed resource.
116                  *          It provides the build() API
117                  *          which builds a resource and return pointer to RCSResourceObject class.
118                  *
119                  *@see build()
120                  */
121                 class Builder
122                 {
123                     public:
124                         /**
125                          * @brief Constructor.
126                          *           Sets the resource property values using initializers list.
127                          *
128                          * @param uri Resource URI value to be set
129                          * @param type Resource type value to be set
130                          * @param interface Interface value to be set
131                          *
132                          *NOTE : m_properties value is by default set to
133                          *       OC_DISCOVERABLE | OC_OBSERVABLE.
134                          *       OC_DISCOVERABLE and OC_OBSERVABLE are defined in octypes.h.
135                          */
136                         Builder(const std::string &uri, const std::string &type,
137                                 const std::string &interface);
138
139                         /**
140                         * Sets the discoverable(OC_DISCOVERABLE) property for the resource.
141                         *
142                         * @param discoverable Whether to be discovered.
143                         *
144                         * @return reference of this Builder
145                         *
146                         *@see OC_DISCOVERABLE
147                         */
148                         Builder &setDiscoverable(bool discoverable);
149
150                         /**
151                         * Sets the observable(OC_OBSERVABLE) property of the resource.
152                         *
153                         * @param observable Whether to be observed.
154                         *
155                         * @return reference of this Builder
156                         *
157                         *@see  OC_OBSERVABLE
158                         */
159                         Builder &setObservable(bool observable);
160
161                         /**
162                         * Sets attribute of the resource.
163                         *
164                         * @param attributes Resource attributes to set
165                         *
166                         * @return reference of this Builder
167                         */
168                         Builder &setAttributes(const RCSResourceAttributes &attributes);
169
170                         /**
171                         * API for setting attributes of the resource.
172                         *
173                         * @param attributes Resource Attributes to set
174                         *
175                         * @return reference of this Builder
176                         */
177                         Builder &setAttributes(RCSResourceAttributes &&attributes);
178
179                         /**
180                          * API for constructing a new RCSResourceObject.
181                          *
182                          * @return Pointer to RCSResourceObject instance created.
183                          *
184                          * @throw PlatformException
185                          *       It catches exception from registerResource API of OCPlatform and
186                          *       throws it to developer.
187                          *
188                          */
189                         RCSResourceObject::Ptr build();
190
191                     private:
192                         std::string m_uri;
193                         std::string m_type;
194                         std::string m_interface;
195                         uint8_t m_properties;
196                         RCSResourceAttributes m_resourceAttributes;
197                 };
198
199                 class LockGuard;
200
201                 typedef std::function < RCSGetResponse(const RCSRequest&,
202                                                        RCSResourceAttributes&) > GetRequestHandler;
203                 typedef std::function < RCSSetResponse(const RCSRequest&,
204                                                        RCSResourceAttributes&) > SetRequestHandler;
205
206                 typedef std::function < void(const RCSResourceAttributes::Value&,
207                                      const RCSResourceAttributes::Value &) > AttributeUpdatedListener;
208
209             public:
210                 RCSResourceObject(RCSResourceObject&&) = delete;
211                 RCSResourceObject(const RCSResourceObject&) = delete;
212
213                 RCSResourceObject& operator=(RCSResourceObject&&) = delete;
214                 RCSResourceObject& operator=(const RCSResourceObject&) = delete;
215
216                 virtual ~RCSResourceObject();
217
218                 /**
219                  * API for setting a particular attribute value.
220                  *
221                  * @param key name of attribute(used to map the attribute value).
222                  * @param value attribute value to be mapped against the key.
223                  *
224                  * @note It is guaranteed thread-safety about attributes.
225                  */
226                 void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
227
228                 /**
229                  * @overload
230                  */
231                 void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
232
233                 /**
234                  * @overload
235                  */
236                 void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
237
238                 /**
239                  * @overload
240                  */
241                 void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
242
243                 /**
244                  * API for getting attribute value corresponding to a key(name of that attribute).
245                  *
246                  * @param key name of the attribute value to look for.
247                  *
248                  * @return value of the resource attribute.
249                  *
250                  * @note It is guaranteed thread-safety about attributes.
251                  *
252                  * @throw InvalidKeyException
253                  *              Throw exception when empty string is provided as Attribute key.
254                  */
255                 RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
256
257                 /**
258                  * API for retrieving the attribute value associated with the supplied name.
259                  *
260                  * @param key Name of the attribute
261                  *
262                  * @return resource attributes value.
263                  *
264                  * It is guaranteed thread-safety about attributes.
265                  */
266                 template< typename T >
267                 T getAttribute(const std::string& key) const
268                 {
269                     WeakGuard lock(*this);
270                     return m_resourceAttributes.at(key).get< T >();
271                 }
272
273                 /**
274                  * API for removing a particular attribute of the resource.
275                  *
276                  * @param key Name of the attribute.
277                  *
278                  * @return If the key exist and matched attribute is deleted, return true.
279                  *
280                  * It is guaranteed thread-safety about attributes.
281                  */
282                 bool removeAttribute(const std::string& key);
283
284                 /**
285                  * API for checking whether a particular attribute is there for a resource or not.
286                  *
287                  * @param key Name of the attribute.
288                  *
289                  * @return If the key exist, return true.
290                  *
291                  * It is guaranteed thread-safety about attributes.
292                  */
293                 bool containsAttribute(const std::string& key) const;
294
295                 /**
296                  * API for getting all the attributes of the RCSResourceObject.
297                  * It invokes the expectOwnLock() API to check the owner of the lock using the
298                  * thread id.
299                  * If it is not the owner then it throws exception.
300                  *
301                  * @return reference of the attributes of this RCSResourceObject.
302                  *
303                  * @see expectOwnLock()
304                  *
305                  * @throw NoLockException
306                  *              If you don't do lock with LockGuard, throw exception.
307                  */
308                 RCSResourceAttributes& getAttributes();
309
310                 /**
311                  * @overload
312                  */
313                 const RCSResourceAttributes& getAttributes() const;
314
315                 /**
316                 * API for checking whether the particular resource is observable or not
317                 */
318                 virtual bool isObservable() const;
319
320                 /**
321                 * API for checking whether the particular resource is discoverable or not
322                 */
323                 virtual bool isDiscoverable() const;
324
325                 /**
326                  * API for setting the resource's get request handler by the developer/application.
327                  * If developer set this handler then all get request will come to the application &
328                  * developer can send the response to the client using APIs of RCSGetResponse class.
329                  *
330                  * @param handler Request handler for get requests
331                  *
332                  * @see RCSGetResponse
333                  *
334                  */
335                 virtual void setGetRequestHandler(GetRequestHandler handler);
336
337                 /**
338                  * API for setting the resource's set request handler by the developer/application.
339                  * If developer set this handler then all set request for the resource
340                  * will come to the application & developer can send the response to the client
341                  * using APIs of RCSSetResponse class.
342                  *
343                  * @param handler Request handler for set requests
344                  *
345                  * @see RCSSetResponse
346                  *
347                  */
348                 virtual void setSetRequestHandler(SetRequestHandler handler);
349
350                 /**
351                  * API for setting the Listener for a particular attribute update.
352                  *
353                  * @param key The interested attribute's key
354                  * @param listener Listener for updation of the interested attribute
355                  *
356                  */
357                 virtual void addAttributeUpdatedListener(const std::string& key,
358                         AttributeUpdatedListener listener);
359
360                 /**
361                  * API for setting the Listener for a particular attribute update.
362                  *
363                  * @param key The interested attribute's key
364                  * @param listener Listener for updation of the interested attribute
365                  *
366                  */
367                 virtual void addAttributeUpdatedListener(std::string&& key,
368                         AttributeUpdatedListener listener);
369
370                 /**
371                 * API for removing the handler for a particular attribute update.
372                 *
373                 * @param key The interested attribute's key
374                 *
375                 */
376                 virtual bool removeAttributeUpdatedListener(const std::string& key);
377
378                 /**
379                  * API for notifying all observers of the RCSResourceObject
380                  * with the updated attributes value
381                  */
382                 virtual void notify() const;
383
384                 /**
385                 * API for setting Auto notify policy
386                 *
387                 * @param policy policy to be set
388                 *
389                 * @see AutoNotifyPolicy
390                 *
391                 */
392                 void setAutoNotifyPolicy(AutoNotifyPolicy policy);
393
394                 /**
395                 * API for getting auto notify policy
396                 *
397                 * @returns AntoNotify policy
398                 *
399                 * @see AutoNotifyPolicy
400                 *
401                 */
402                 AutoNotifyPolicy getAutoNotifyPolicy() const;
403
404                 /**
405                 * API for setting the policy for a setRequestHandler.
406                 *
407                 * @param policy policy to be set
408                 *
409                 * @see SetRequestHandlerPolicy
410                 *
411                 */
412                 void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
413
414                 /**
415                 * API for getting the SetRequestHandler Policy.
416                 *
417                 * @returns Property of setRequesthandler
418                 *
419                 * @see SetRequestHandlerPolicy
420                 *
421                 */
422                 SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
423
424         private:
425             RCSResourceObject(uint8_t, RCSResourceAttributes&&);
426
427             OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest >);
428
429             OCEntityHandlerResult handleRequest(std::shared_ptr< OC::OCResourceRequest >);
430             OCEntityHandlerResult handleRequestGet(std::shared_ptr< OC::OCResourceRequest >);
431             OCEntityHandlerResult handleRequestSet(std::shared_ptr< OC::OCResourceRequest >);
432             OCEntityHandlerResult handleObserve(std::shared_ptr< OC::OCResourceRequest >);
433
434             void expectOwnLock() const;
435
436             void autoNotify(bool, AutoNotifyPolicy) const;
437             void autoNotify(bool) const;
438
439             bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
440
441             template< typename K, typename V >
442             void setAttributeInternal(K&&, V&&);
443
444         private:
445             const uint8_t m_properties;
446
447             OCResourceHandle m_resourceHandle;
448             RCSResourceAttributes m_resourceAttributes;
449
450             GetRequestHandler m_getRequestHandler;
451             SetRequestHandler m_setRequestHandler;
452             AutoNotifyPolicy m_autoNotifyPolicy;
453             SetRequestHandlerPolicy m_setRequestHandlerPolicy;
454
455             std::unordered_map< std::string, AttributeUpdatedListener >
456                     m_keyAttributesUpdatedListeners;
457
458             mutable boost::atomic< std::thread::id > m_lockOwner;
459             mutable std::mutex m_mutex;
460
461             std::mutex m_mutexKeyAttributeUpdate;
462
463         };
464
465         class RCSResourceObject::LockGuard
466         {
467         public:
468             LockGuard(const RCSResourceObject&);
469             LockGuard(const RCSResourceObject::Ptr);
470             LockGuard(const RCSResourceObject&, AutoNotifyPolicy);
471             LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
472             ~LockGuard();
473
474             LockGuard(const LockGuard&) = delete;
475             LockGuard(LockGuard&&) = delete;
476
477             LockGuard& operator=(const LockGuard&) = delete;
478             LockGuard& operator=(LockGuard&&) = delete;
479
480         private:
481             void init();
482
483         private:
484             const RCSResourceObject& m_resourceObject;
485
486             AutoNotifyPolicy m_autoNotifyPolicy;
487
488             bool m_isOwningLock;
489
490             std::function<void()> m_autoNotifyFunc;
491         };
492
493         class RCSResourceObject::WeakGuard
494         {
495         public:
496             WeakGuard(const RCSResourceObject&);
497             ~WeakGuard();
498
499             WeakGuard(const WeakGuard&) = delete;
500             WeakGuard(WeakGuard&&) = delete;
501
502             WeakGuard& operator=(const WeakGuard&) = delete;
503             WeakGuard& operator=(WeakGuard&&) = delete;
504
505             bool hasLocked() const;
506
507         private:
508             bool m_isOwningLock;
509             const RCSResourceObject& m_resourceObject;
510         };
511     }
512 }
513
514 #endif // SERVER_RCSRESOURCEOBJECT_H