1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 * This file contains the declaration of classes and its members related to RCSResourceObject
26 #ifndef SERVER_RCSRESOURCEOBJECT_H
27 #define SERVER_RCSRESOURCEOBJECT_H
33 #include <RCSResourceAttributes.h>
34 #include <RCSResponse.h>
35 #include <RCSRequest.h>
39 class OCResourceRequest;
48 * @brief Thrown when lock has not been acquired.
50 * @see RCSResourceObject::LockGuard
51 * @see RCSResourceObject::getAttributes
53 class NoLockException: public RCSException
56 NoLockException(std::string &&what) : RCSException { std::move(what) } {}
60 template < typename T >
65 * RCSResourceObject represents a resource and handles any requests from clients
66 * automatically with attributes.
68 * It also provides an auto notification mechanism that notifies to the observers.
70 * Requests are handled automatically by defaultAction of RCSGetResponse and
71 * RCSSetResponse. You can override them and send your own response.
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.
78 class RCSResourceObject
83 typedef AtomicWrapper< std::thread::id > AtomicThreadId;
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.
91 * @note Attributes are set according to the execution of some functions which
92 * modify attributes or receipt of set requests.
94 * @see RCSResourceObject::setAttribute
95 * @see RCSResourceObject::removeAttribute
96 * @see RCSResourceObject::getAttributes
97 * @see RCSResourceObject::LockGuard
99 enum class AutoNotifyPolicy
102 ALWAYS, /**< Always*/
103 UPDATED /**< Only when attributes are changed*/
107 * Represents the policy of set-request handler.
108 * In accord with this, the RCSResourceObject decides whether a set-request is
111 enum class SetRequestHandlerPolicy
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
116 ACCEPTANCE /**< The whole attributes of the request will be applied
117 even if there are new name or type conflicts. */
120 typedef std::shared_ptr< RCSResourceObject > Ptr;
121 typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
124 * This is a builder to create resource with properties and attributes.
126 * The resource will be observable and discoverable by default, to make them disable
127 * set these properties explicitly with setDiscoverable and setObservable.
133 * Constructs a Builder.
135 * @param uri Resource uri
136 * @param type Resource type
137 * @param interface Resource interface
140 Builder(const std::string& uri, const std::string& type,
141 const std::string& interface);
144 * Sets whether the resource is discoverable.
146 * @param discoverable whether to be discovered.
149 Builder& setDiscoverable(bool discoverable);
152 * Sets the observable property of the resource.
154 * @param observable whether to be observed.
157 Builder& setObservable(bool observable);
160 * Sets attribute of the resource.
162 * @param attributes attributes to set
165 Builder& setAttributes(const RCSResourceAttributes &attributes);
170 Builder& setAttributes(RCSResourceAttributes &&attributes);
173 * Register a resource and returns a RCSResourceObject.
175 * @throw RCSPlatformException if resource registration is failed.
178 RCSResourceObject::Ptr build();
183 std::string m_interface;
184 uint8_t m_properties;
185 RCSResourceAttributes m_resourceAttributes;
191 * Callback definition for a handler to be invoked when a get request is received.
193 * The handler will be called first when a get request is received, before the
194 * RCSResourceObject handles.
196 * @param request the request information
197 * @param attributes attributes of the request
199 * @return response to be sent and that indicates how the request to be handled by
200 * the RCSResourceObject.
202 * @see setGetRequestHandler
204 typedef std::function < RCSGetResponse(const RCSRequest& request,
205 RCSResourceAttributes& attributes) > GetRequestHandler;
208 * Callback definition for a handler to be invoked when a set request is received.
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
215 * @param request the request information
216 * @param attributes attributes of the request
218 * @return response to be sent and that indicates how the request to be handled by
219 * the RCSResourceObject.
221 * @see setGetRequestHandler
223 typedef std::function < RCSSetResponse(const RCSRequest& request,
224 RCSResourceAttributes& attributes) > SetRequestHandler;
227 * Callback definition to be invoked when an attribute is updated.
229 * @param oldValue the value before being changed
230 * @param newValue changed value
232 typedef std::function < void(const RCSResourceAttributes::Value& oldValue,
233 const RCSResourceAttributes::Value& newValue) > AttributeUpdatedListener;
236 RCSResourceObject(RCSResourceObject&&) = delete;
237 RCSResourceObject(const RCSResourceObject&) = delete;
239 RCSResourceObject& operator=(RCSResourceObject&&) = delete;
240 RCSResourceObject& operator=(const RCSResourceObject&) = delete;
242 virtual ~RCSResourceObject();
245 * Sets a particular attribute value.
247 * @param key key of attribute
248 * @param value value to be mapped against the key
250 * @note Thread-safety is guaranteed for the attributes.
252 void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
257 void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
262 void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
267 void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
270 * Returns an attribute value corresponding to a key.
272 * @param key key of the attribute
274 * @throws RCSInvalidKeyException If key is invalid.
276 * @note Thread-safety is guaranteed for the attributes.
278 RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
281 * Returns the attribute value as T.
283 * @param key key of the attribute
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.
288 * @note Thread-safety is guaranteed for the attributes.
290 template< typename T >
291 T getAttribute(const std::string& key) const
293 WeakGuard lock(*this);
294 return m_resourceAttributes.at(key).get< T >();
298 * Removes a particular attribute of the resource.
300 * @param key key of the attribute.
302 * @return True if the key exists and matched attribute is removed, otherwise false.
304 * @note Thread-safety is guaranteed for the attributes.
306 bool removeAttribute(const std::string& key);
309 * Checks whether a particular attribute exists or not.
311 * @param key key of the attribute
313 * @return True if the key exists, otherwise false.
315 * @note Thread-safety is guaranteed for the attributes.
317 bool containsAttribute(const std::string& key) const;
320 * Returns reference to the attributes of the RCSResourceObject.
322 * @pre The call must be guarded by LockGuard.
325 * @return Reference to the attributes
327 * @throws NoLockException If the call is not guarded by LockGuard.
329 * @note Here is the standard idiom for LockGuard:
332 RCSResourceObject::LockGuard lock(rcsResourceObject);
334 auto &attributes = server->getAttributes();
339 RCSResourceAttributes& getAttributes();
344 const RCSResourceAttributes& getAttributes() const;
347 * Checks whether the particular resource is observable or not.
349 virtual bool isObservable() const;
352 * Checks whether the particular resource is discoverable or not.
354 virtual bool isDiscoverable() const;
357 * Sets the get request handler.
358 * To remove handler, pass empty handler or nullptr.
360 * Default behavior is RCSGetResponse::defaultAction()
362 * @param handler a get request handler
364 * @see RCSGetResponse
367 virtual void setGetRequestHandler(GetRequestHandler handler);
370 * Sets the set request handler.
371 * To remove handler, pass empty handler or nullptr.
373 * Default behavior is RCSGetResponse::defaultAction()
375 * @param handler a set request handler
377 * @see RCSSetResponse
380 virtual void setSetRequestHandler(SetRequestHandler handler);
383 * Adds a listener for a particular attribute update.
385 * @param key the interested attribute's key
386 * @param listener listener to be invoked
389 virtual void addAttributeUpdatedListener(const std::string& key,
390 AttributeUpdatedListener listener);
395 virtual void addAttributeUpdatedListener(std::string&& key,
396 AttributeUpdatedListener listener);
399 * Removes a listener for a particular attribute update.
401 * @param key the key to be removed
404 virtual bool removeAttributeUpdatedListener(const std::string& key);
407 * Notifies all observers of the current attributes.
409 * @throws RCSPlatformException If the operation failed.
411 virtual void notify() const;
414 * Sets auto notify policy
416 * @param policy policy to be set
419 void setAutoNotifyPolicy(AutoNotifyPolicy policy);
422 * Returns the current policy
425 AutoNotifyPolicy getAutoNotifyPolicy() const;
428 * Sets the policy for handling a set request.
430 * @param policy policy to be set
433 void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
436 * Returns the current policy.
439 SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
442 RCSResourceObject(uint8_t, RCSResourceAttributes&&);
444 OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest >);
446 OCEntityHandlerResult handleRequest(std::shared_ptr< OC::OCResourceRequest >);
447 OCEntityHandlerResult handleRequestGet(std::shared_ptr< OC::OCResourceRequest >);
448 OCEntityHandlerResult handleRequestSet(std::shared_ptr< OC::OCResourceRequest >);
449 OCEntityHandlerResult handleObserve(std::shared_ptr< OC::OCResourceRequest >);
451 void expectOwnLock() const;
453 std::thread::id getLockOwner() const noexcept;
455 void setLockOwner(std::thread::id&&) const noexcept;
457 void autoNotify(bool, AutoNotifyPolicy) const;
458 void autoNotify(bool) const;
460 bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
462 template< typename K, typename V >
463 void setAttributeInternal(K&&, V&&);
465 bool applyAcceptanceMethod(const RCSSetResponse&, const RCSResourceAttributes&);
468 const uint8_t m_properties;
470 OCResourceHandle m_resourceHandle;
472 RCSResourceAttributes m_resourceAttributes;
474 GetRequestHandler m_getRequestHandler;
475 SetRequestHandler m_setRequestHandler;
477 AutoNotifyPolicy m_autoNotifyPolicy;
478 SetRequestHandlerPolicy m_setRequestHandlerPolicy;
480 std::unordered_map< std::string, std::shared_ptr< AttributeUpdatedListener > >
481 m_attributeUpdatedListeners;
483 mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
484 mutable std::mutex m_mutex;
486 std::mutex m_mutexAttributeUpdatedListeners;
491 * The class provides a convinent RAII-style mechanism for the attributes of a
492 * RCSResourceObject. When a LockGuard is created, it attempts to lock the attributes of
493 * the RCSResourceObject it is given. When control leaves the scope in which the LockGuard
494 * object was created, the LockGuard is destructed and the attributes is unlocked.
496 * Additionally when this is destructed, it tries to notify depending on AutoNotifyPolicy
497 * of the RCSResourceObject.
499 class RCSResourceObject::LockGuard
502 LockGuard(const RCSResourceObject& rcsResourceObject);
504 LockGuard(const RCSResourceObject::Ptr);
507 * Constructs a LockGuard with auto notify policy.
509 * @param object an object to be locked
510 * @param autoNotifyPolicy the policy to indicate how auto notification is handled
511 * when the LockGuard is destructed.
514 LockGuard(const RCSResourceObject& object, AutoNotifyPolicy autoNotifyPolicy);
519 LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
522 LockGuard(const LockGuard&) = delete;
523 LockGuard(LockGuard&&) = delete;
525 LockGuard& operator=(const LockGuard&) = delete;
526 LockGuard& operator=(LockGuard&&) = delete;
532 const RCSResourceObject& m_resourceObject;
534 AutoNotifyPolicy m_autoNotifyPolicy;
538 std::function<void()> m_autoNotifyFunc;
542 class RCSResourceObject::WeakGuard
545 WeakGuard(const RCSResourceObject&);
548 WeakGuard(const WeakGuard&) = delete;
549 WeakGuard(WeakGuard&&) = delete;
551 WeakGuard& operator=(const WeakGuard&) = delete;
552 WeakGuard& operator=(WeakGuard&&) = delete;
554 bool hasLocked() const;
558 const RCSResourceObject& m_resourceObject;
564 #endif // SERVER_RCSRESOURCEOBJECT_H