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"
38 class OCResourceRequest;
47 class RCSRepresentation;
50 * @brief Thrown when lock has not been acquired.
52 * @see RCSResourceObject::LockGuard
53 * @see RCSResourceObject::getAttributes
55 class NoLockException: public RCSException
58 NoLockException(std::string &&what) : RCSException { std::move(what) } {}
62 template < typename T >
67 * RCSResourceObject represents a resource and handles any requests from clients
68 * automatically with attributes.
70 * It also provides an auto notification mechanism that notifies to the observers.
72 * Requests are handled automatically by defaultAction of RCSGetResponse and
73 * RCSSetResponse. You can override them and send your own response.
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.
80 class RCSResourceObject : public std::enable_shared_from_this< RCSResourceObject >
85 typedef AtomicWrapper< std::thread::id > AtomicThreadId;
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.
93 * @note Attributes are set according to the execution of some functions which
94 * modify attributes or receipt of set requests.
96 * @see RCSResourceObject::setAttribute
97 * @see RCSResourceObject::removeAttribute
98 * @see RCSResourceObject::getAttributes
99 * @see RCSResourceObject::LockGuard
101 enum class AutoNotifyPolicy
104 ALWAYS, /**< Always*/
105 UPDATED /**< Only when attributes are changed*/
109 * Represents the policy of set-request handler.
110 * In accord with this, the RCSResourceObject decides whether a set-request is
113 enum class SetRequestHandlerPolicy
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
118 ACCEPTANCE /**< The attributes of the request will be applied unconditionally
119 even if there are new name or type conflicts. */
122 typedef std::shared_ptr< RCSResourceObject > Ptr;
123 typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
126 * This is a builder to create resource with properties and attributes.
128 * The resource will be observable and discoverable by default, to make them disable
129 * set these properties explicitly with setDiscoverable and setObservable.
135 * Constructs a Builder.
137 * @param uri Resource uri
138 * @param type Resource type
139 * @param interface Resource interface
142 Builder(const std::string& uri, const std::string& type,
143 const std::string& interface);
145 Builder& addInterface(const std::string& interface);
146 Builder& addInterface(std::string&& interface);
148 Builder& addType(const std::string& type);
149 Builder& addType(std::string&& type);
152 * Sets whether the resource is discoverable.
154 * @param discoverable whether to be discoverable.
157 Builder& setDiscoverable(bool discoverable);
160 * Sets the observable property of the resource.
162 * @param observable whether to be observable.
165 Builder& setObservable(bool observable);
168 * Sets whether the resource should be secure or not.
170 * @param secureFlag whether to be secure or not.
173 Builder& setSecureFlag(bool secureFlag);
176 * Sets attributes for the resource.
178 * @param attributes attributes to set
181 Builder& setAttributes(const RCSResourceAttributes &attributes);
186 Builder& setAttributes(RCSResourceAttributes &&attributes);
189 * Register a resource and returns a RCSResourceObject.
191 * @throw RCSPlatformException if resource registration is failed.
194 RCSResourceObject::Ptr build();
198 std::vector< std::string > m_types;
199 std::vector< std::string > m_interfaces;
200 uint8_t m_properties;
201 RCSResourceAttributes m_resourceAttributes;
207 * Callback definition for a handler to be invoked when a get request is received.
209 * The handler will be called first when a get request is received, before the
210 * RCSResourceObject handles.
212 * @param request the request information
213 * @param attributes attributes of the request
215 * @return response to be sent and that indicates how the request to be handled by
216 * the RCSResourceObject.
218 * @see setGetRequestHandler
220 typedef std::function < RCSGetResponse(const RCSRequest& request,
221 RCSResourceAttributes& attributes) > GetRequestHandler;
224 * Callback definition for a handler to be invoked when a set request is received.
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
231 * @param request the request information
232 * @param attributes attributes of the request
234 * @return response to be sent and that indicates how the request to be handled by
235 * the RCSResourceObject.
237 * @see setGetRequestHandler
239 typedef std::function < RCSSetResponse(const RCSRequest& request,
240 RCSResourceAttributes& attributes) > SetRequestHandler;
243 * Callback definition to be invoked when an attribute is updated.
245 * @param oldValue the value before being changed
246 * @param newValue changed value
248 typedef std::function < void(const RCSResourceAttributes::Value& oldValue,
249 const RCSResourceAttributes::Value& newValue) > AttributeUpdatedListener;
252 RCSResourceObject(RCSResourceObject&&) = delete;
253 RCSResourceObject(const RCSResourceObject&) = delete;
255 RCSResourceObject& operator=(RCSResourceObject&&) = delete;
256 RCSResourceObject& operator=(const RCSResourceObject&) = delete;
258 virtual ~RCSResourceObject();
261 * Sets a particular attribute value.
263 * @param key key of attribute
264 * @param value value to be mapped against the key
266 * @note Thread-safety is guaranteed for the attributes.
268 void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
273 void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
278 void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
283 void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
286 * Returns an attribute value corresponding to a key.
288 * @param key key of the attribute
290 * @throws RCSInvalidKeyException If key is invalid.
292 * @note Thread-safety is guaranteed for the attributes.
294 RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
297 * Returns the attribute value as T.
299 * @param key key of the attribute
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.
304 * @note Thread-safety is guaranteed for the attributes.
306 template< typename T >
307 T getAttribute(const std::string& key) const
309 WeakGuard lock(*this);
310 return m_resourceAttributes.at(key).get< T >();
314 * Removes a particular attribute of the resource.
316 * @param key key of the attribute.
318 * @return True if the key exists and matched attribute is removed, otherwise false.
320 * @note Thread-safety is guaranteed for the attributes.
322 bool removeAttribute(const std::string& key);
325 * Checks whether a particular attribute exists or not.
327 * @param key key of the attribute
329 * @return True if the key exists, otherwise false.
331 * @note Thread-safety is guaranteed for the attributes.
333 bool containsAttribute(const std::string& key) const;
336 * Returns reference to the attributes of the RCSResourceObject.
338 * @pre The call must be guarded by LockGuard.
341 * @return Reference to the attributes
343 * @throws NoLockException If the call is not guarded by LockGuard.
345 * @note Here is the standard idiom for LockGuard:
348 RCSResourceObject::LockGuard lock(rcsResourceObject);
350 auto &attributes = server->getAttributes();
355 RCSResourceAttributes& getAttributes();
360 const RCSResourceAttributes& getAttributes() const;
363 * Checks whether the resource is observable or not.
365 virtual bool isObservable() const;
368 * Checks whether the resource is discoverable or not.
370 virtual bool isDiscoverable() const;
373 * Sets the get request handler.
374 * To remove handler, pass empty handler or nullptr.
376 * Default behavior is RCSGetResponse::defaultAction().
378 * @param handler a get request handler
380 * @see RCSGetResponse
383 virtual void setGetRequestHandler(GetRequestHandler handler);
386 * Sets the set request handler.
387 * To remove handler, pass empty handler or nullptr.
389 * Default behavior is RCSSetResponse::defaultAction().
391 * @param handler a set request handler
393 * @see RCSSetResponse
396 virtual void setSetRequestHandler(SetRequestHandler handler);
399 * Adds a listener for a particular attribute updated.
401 * @param key the interested attribute's key
402 * @param listener listener to be invoked
405 virtual void addAttributeUpdatedListener(const std::string& key,
406 AttributeUpdatedListener listener);
411 virtual void addAttributeUpdatedListener(std::string&& key,
412 AttributeUpdatedListener listener);
415 * Removes a listener for a particular attribute updated.
417 * @param key the key associated with the listener to be removed
419 * @return True if the listener added with same key exists and is removed.
422 virtual bool removeAttributeUpdatedListener(const std::string& key);
425 * Notifies all observers of the current attributes.
427 * @throws RCSPlatformException If the operation failed.
429 virtual void notify() const;
432 * Sets auto notify policy
434 * @param policy policy to be set
437 void setAutoNotifyPolicy(AutoNotifyPolicy policy);
440 * Returns the current policy
443 AutoNotifyPolicy getAutoNotifyPolicy() const;
446 * Sets the policy for handling a set request.
448 * @param policy policy to be set
451 void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
454 * Returns the current policy.
457 SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
459 void bindResource(const RCSResourceObject::Ptr&);
461 void unbindResource(const RCSResourceObject::Ptr&);
463 std::vector< RCSResourceObject::Ptr > getBoundResources() const;
465 std::vector< std::string > getInterfaces() const;
466 std::vector< std::string > getTypes() const;
468 RCSRepresentation toRepresentation() const;
471 RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&);
473 static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&,
474 const std::shared_ptr< OC::OCResourceRequest >&);
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 >&);
481 void expectOwnLock() const;
483 std::thread::id getLockOwner() const noexcept;
485 void setLockOwner(std::thread::id&&) const noexcept;
487 void autoNotify(bool, AutoNotifyPolicy) const;
488 void autoNotify(bool) const;
490 bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
492 template< typename K, typename V >
493 void setAttributeInternal(K&&, V&&);
495 bool applyAcceptanceMethod(const RCSSetResponse&, const RCSResourceAttributes&);
498 const uint8_t m_properties;
500 const std::string m_uri;
501 std::vector< std::string > m_interfaces;
502 std::vector< std::string > m_types;
504 OCResourceHandle m_resourceHandle;
506 RCSResourceAttributes m_resourceAttributes;
508 std::shared_ptr< GetRequestHandler > m_getRequestHandler;
509 std::shared_ptr< SetRequestHandler > m_setRequestHandler;
511 AutoNotifyPolicy m_autoNotifyPolicy;
512 SetRequestHandlerPolicy m_setRequestHandlerPolicy;
514 std::unordered_map< std::string, std::shared_ptr< AttributeUpdatedListener > >
515 m_attributeUpdatedListeners;
517 mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
518 mutable std::mutex m_mutex;
520 std::mutex m_mutexAttributeUpdatedListeners;
522 mutable std::mutex m_mutexForBoundResources;
524 std::vector< RCSResourceObject::Ptr > m_boundResources;
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.
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.
537 * @note The destrcutor can throw an exception if auto notify failed.
539 class RCSResourceObject::LockGuard
542 LockGuard(const RCSResourceObject& rcsResourceObject);
544 LockGuard(const RCSResourceObject::Ptr);
547 * Constructs a LockGuard with auto notify policy.
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.
554 LockGuard(const RCSResourceObject& object, AutoNotifyPolicy autoNotifyPolicy);
559 LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
562 * @throws RCSPlatformException If auto notify operation failed.
564 * @note The exception will never be thrown while stack unwinding.
566 ~LockGuard() noexcept(false);
568 LockGuard(const LockGuard&) = delete;
569 LockGuard(LockGuard&&) = delete;
571 LockGuard& operator=(const LockGuard&) = delete;
572 LockGuard& operator=(LockGuard&&) = delete;
578 const RCSResourceObject& m_resourceObject;
580 AutoNotifyPolicy m_autoNotifyPolicy;
584 std::function<void()> m_autoNotifyFunc;
588 class RCSResourceObject::WeakGuard
591 WeakGuard(const RCSResourceObject&);
594 WeakGuard(const WeakGuard&) = delete;
595 WeakGuard(WeakGuard&&) = delete;
597 WeakGuard& operator=(const WeakGuard&) = delete;
598 WeakGuard& operator=(WeakGuard&&) = delete;
600 bool hasLocked() const;
604 const RCSResourceObject& m_resourceObject;
610 #endif // SERVER_RCSRESOURCEOBJECT_H