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