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
34 #include "RCSResourceAttributes.h"
35 #include "RCSResponse.h"
39 class OCResourceRequest;
48 class RCSRepresentation;
49 class InterfaceHandler;
52 * @brief Thrown when lock has not been acquired.
54 * @see RCSResourceObject::LockGuard
55 * @see RCSResourceObject::getAttributes
57 class NoLockException: public RCSException
60 NoLockException(std::string &&what) : RCSException { std::move(what) } {}
64 template < typename T >
69 * RCSResourceObject represents a resource and handles any requests from clients
70 * automatically with attributes.
72 * It also provides an auto notification mechanism that notifies to the observers.
74 * Requests are handled automatically by defaultAction of RCSGetResponse and
75 * RCSSetResponse. You can override them and send your own response.
77 * For simple resources, they are simply required to notify whenever attributes are changed
78 * by a set request. In this case, add an AttributeUpdatedListener with a key interested
79 * in instead of overriding SetRequestHandler.
82 class RCSResourceObject : public std::enable_shared_from_this< RCSResourceObject >
87 typedef AtomicWrapper< std::thread::id > AtomicThreadId;
91 * Represents the policy of auto-notify function.
92 * In accord with this policy, observers are notified of attributes
93 * when the attributes are set.
95 * @note Attributes are set according to the execution of some functions which
96 * modify attributes or receipt of set requests.
98 * @see RCSResourceObject::setAttribute
99 * @see RCSResourceObject::removeAttribute
100 * @see RCSResourceObject::getAttributes
101 * @see RCSResourceObject::LockGuard
103 enum class AutoNotifyPolicy
106 ALWAYS, /**< Always*/
107 UPDATED /**< Only when attributes are changed*/
111 * Represents the policy of set-request handler.
112 * In accord with this, the RCSResourceObject decides whether a set-request is
115 enum class SetRequestHandlerPolicy
117 NEVER, /**< Requests will be ignored if attributes of the request contain
118 a new key or a value that has different type from the current
120 ACCEPTANCE /**< The attributes of the request will be applied unconditionally
121 even if there are new name or type conflicts. */
124 typedef std::shared_ptr< RCSResourceObject > Ptr;
125 typedef std::shared_ptr< const RCSResourceObject > ConstPtr;
128 * This is a builder to create resource with properties and attributes.
130 * The resource will be observable and discoverable by default, to make them disable
131 * set these properties explicitly with setDiscoverable and setObservable.
137 * Constructs a Builder.
139 * @param uri Resource uri
140 * @param type Resource type
141 * @param interface Resource interface
144 Builder(const std::string& uri, const std::string& type,
145 const std::string& interface);
147 Builder& addInterface(const std::string& interface);
148 Builder& addInterface(std::string&& interface);
150 Builder& addType(const std::string& type);
151 Builder& addType(std::string&& type);
154 * Sets the default interface
156 * @param interface default interface name
159 Builder& setDefaultInterface(std::string interface);
162 * Sets whether the resource is discoverable.
164 * @param discoverable whether to be discoverable.
167 Builder& setDiscoverable(bool discoverable);
170 * Sets the observable property of the resource.
172 * @param observable whether to be observable.
175 Builder& setObservable(bool observable);
178 * Sets whether the resource should be secure or not.
180 * @param secureFlag whether to be secure or not.
183 Builder& setSecureFlag(bool secureFlag);
186 * Sets attributes for the resource.
188 * @param attributes attributes to set
191 Builder& setAttributes(const RCSResourceAttributes &attributes);
196 Builder& setAttributes(RCSResourceAttributes &&attributes);
199 * Register a resource and returns a RCSResourceObject.
201 * @throw RCSPlatformException if resource registration is failed.
204 RCSResourceObject::Ptr build();
208 std::vector< std::string > m_types;
209 std::vector< std::string > m_interfaces;
210 std::string m_defaultInterface;
211 uint8_t m_properties;
212 RCSResourceAttributes m_resourceAttributes;
218 * Callback definition for a handler to be invoked when a get request is received.
220 * The handler will be called first when a get request is received, before the
221 * RCSResourceObject handles.
223 * @param request the request information
224 * @param attributes attributes of the request
226 * @return response to be sent and that indicates how the request to be handled by
227 * the RCSResourceObject.
229 * @see setGetRequestHandler
231 typedef std::function < RCSGetResponse(const RCSRequest& request,
232 RCSResourceAttributes& attributes) > GetRequestHandler;
235 * Callback definition for a handler to be invoked when a set request is received.
237 * The handler will be called first when a get request is received, before the
238 * RCSResourceObject handles. If the attributes are modified in the callback,
239 * the modified attributes will be set in the RCSResourceObject if the request is
242 * @param request the request information
243 * @param attributes attributes of the request
245 * @return response to be sent and that indicates how the request to be handled by
246 * the RCSResourceObject.
248 * @see setGetRequestHandler
250 typedef std::function < RCSSetResponse(const RCSRequest& request,
251 RCSResourceAttributes& attributes) > SetRequestHandler;
254 * Callback definition to be invoked when an attribute is updated.
256 * @param oldValue the value before being changed
257 * @param newValue changed value
259 typedef std::function < void(const RCSResourceAttributes::Value& oldValue,
260 const RCSResourceAttributes::Value& newValue) > AttributeUpdatedListener;
263 RCSResourceObject(RCSResourceObject&&) = delete;
264 RCSResourceObject(const RCSResourceObject&) = delete;
266 RCSResourceObject& operator=(RCSResourceObject&&) = delete;
267 RCSResourceObject& operator=(const RCSResourceObject&) = delete;
269 virtual ~RCSResourceObject();
272 * Sets a particular attribute value.
274 * @param key key of attribute
275 * @param value value to be mapped against the key
277 * @note Thread-safety is guaranteed for the attributes.
279 void setAttribute(const std::string& key, const RCSResourceAttributes::Value& value);
284 void setAttribute(const std::string& key, RCSResourceAttributes::Value&& value);
289 void setAttribute(std::string&& key, const RCSResourceAttributes::Value& value);
294 void setAttribute(std::string&& key, RCSResourceAttributes::Value&& value);
297 * Returns an attribute value corresponding to a key.
299 * @param key key of the attribute
301 * @throws RCSInvalidKeyException If key is invalid.
303 * @note Thread-safety is guaranteed for the attributes.
305 RCSResourceAttributes::Value getAttributeValue(const std::string& key) const;
308 * Returns the attribute value as T.
310 * @param key key of the attribute
312 * @throws RCSBadGetException If type of the underlying value is not T.
313 * @throws RCSInvalidKeyException If @a key doesn't match the key of any value.
315 * @note Thread-safety is guaranteed for the attributes.
317 template< typename T >
318 T getAttribute(const std::string& key) const
320 WeakGuard lock(*this);
321 return m_resourceAttributes.at(key).get< T >();
325 * Removes a particular attribute of the resource.
327 * @param key key of the attribute.
329 * @return True if the key exists and matched attribute is removed, otherwise false.
331 * @note Thread-safety is guaranteed for the attributes.
333 bool removeAttribute(const std::string& key);
336 * Checks whether a particular attribute exists or not.
338 * @param key key of the attribute
340 * @return True if the key exists, otherwise false.
342 * @note Thread-safety is guaranteed for the attributes.
344 bool containsAttribute(const std::string& key) const;
347 * Returns reference to the attributes of the RCSResourceObject.
349 * @pre The call must be guarded by LockGuard.
352 * @return Reference to the attributes
354 * @throws NoLockException If the call is not guarded by LockGuard.
356 * @note Here is the standard idiom for LockGuard:
359 RCSResourceObject::LockGuard lock(rcsResourceObject);
361 auto &attributes = server->getAttributes();
366 RCSResourceAttributes& getAttributes();
371 const RCSResourceAttributes& getAttributes() const;
374 * Checks whether the resource is observable or not.
376 virtual bool isObservable() const;
379 * Checks whether the resource is discoverable or not.
381 virtual bool isDiscoverable() const;
384 * Sets the get request handler.
385 * To remove handler, pass empty handler or nullptr.
387 * Default behavior is RCSGetResponse::defaultAction().
389 * @param handler a get request handler
391 * @see RCSGetResponse
394 virtual void setGetRequestHandler(GetRequestHandler handler);
397 * Sets the set request handler.
398 * To remove handler, pass empty handler or nullptr.
400 * Default behavior is RCSSetResponse::defaultAction().
402 * @param handler a set request handler
404 * @see RCSSetResponse
407 virtual void setSetRequestHandler(SetRequestHandler handler);
410 * Adds a listener for a particular attribute updated.
412 * @param key the interested attribute's key
413 * @param listener listener to be invoked
416 virtual void addAttributeUpdatedListener(const std::string& key,
417 AttributeUpdatedListener listener);
422 virtual void addAttributeUpdatedListener(std::string&& key,
423 AttributeUpdatedListener listener);
426 * Removes a listener for a particular attribute updated.
428 * @param key the key associated with the listener to be removed
430 * @return True if the listener added with same key exists and is removed.
433 virtual bool removeAttributeUpdatedListener(const std::string& key);
436 * Notifies all observers of the current attributes.
438 * @throws RCSPlatformException If the operation failed.
440 virtual void notify() const;
443 * Sets auto notify policy
445 * @param policy policy to be set
448 void setAutoNotifyPolicy(AutoNotifyPolicy policy);
451 * Returns the current policy
454 AutoNotifyPolicy getAutoNotifyPolicy() const;
457 * Sets the policy for handling a set request.
459 * @param policy policy to be set
462 void setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy);
465 * Returns the current policy.
468 SetRequestHandlerPolicy getSetRequestHandlerPolicy() const;
470 void bindResource(const RCSResourceObject::Ptr&);
472 void unbindResource(const RCSResourceObject::Ptr&);
474 std::vector< RCSResourceObject::Ptr > getBoundResources() const;
476 std::string getUri() const;
477 std::string getDefaultInterface() const;
479 std::vector< std::string > getInterfaces() const;
480 std::vector< std::string > getTypes() const;
482 RCSRepresentation toRepresentation() const;
485 RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&);
487 void init(OCResourceHandle, const std::vector< std::string >&,
488 const std::vector< std::string >&, const std::string&);
490 static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&,
491 const std::shared_ptr< OC::OCResourceRequest >&);
493 OCEntityHandlerResult handleRequest(const std::shared_ptr< OC::OCResourceRequest >&);
494 OCEntityHandlerResult handleRequestGet(const RCSRequest&);
495 OCEntityHandlerResult handleRequestSet(const RCSRequest&);
496 OCEntityHandlerResult handleObserve(const std::shared_ptr< OC::OCResourceRequest >&);
498 template <typename RESPONSE, typename RESPONSE_BUILDER>
499 OCEntityHandlerResult sendResponse(const RCSRequest&,
500 const RESPONSE&, const RESPONSE_BUILDER&);
502 void expectOwnLock() const;
504 std::thread::id getLockOwner() const noexcept;
506 void setLockOwner(std::thread::id&&) const noexcept;
508 void autoNotify(bool, AutoNotifyPolicy) const;
509 void autoNotify(bool) const;
511 bool testValueUpdated(const std::string&, const RCSResourceAttributes::Value&) const;
513 template< typename K, typename V >
514 void setAttributeInternal(K&&, V&&);
516 RCSResourceAttributes applyAcceptanceMethod(const RCSSetResponse&,
517 const RCSResourceAttributes&);
519 InterfaceHandler findInterfaceHandler(const std::string&) const;
522 const uint8_t m_properties;
524 const std::string m_uri;
525 std::vector< std::string > m_interfaces;
526 std::vector< std::string > m_types;
527 std::string m_defaultInterface;
529 OCResourceHandle m_resourceHandle;
531 RCSResourceAttributes m_resourceAttributes;
533 std::shared_ptr< GetRequestHandler > m_getRequestHandler;
534 std::shared_ptr< SetRequestHandler > m_setRequestHandler;
536 AutoNotifyPolicy m_autoNotifyPolicy;
537 SetRequestHandlerPolicy m_setRequestHandlerPolicy;
539 std::unordered_map< std::string, std::shared_ptr< AttributeUpdatedListener > >
540 m_attributeUpdatedListeners;
542 mutable std::unique_ptr< AtomicThreadId > m_lockOwner;
543 mutable std::mutex m_mutex;
545 std::mutex m_mutexAttributeUpdatedListeners;
547 mutable std::mutex m_mutexForBoundResources;
549 std::vector< RCSResourceObject::Ptr > m_boundResources;
551 std::map< std::string, InterfaceHandler > m_interfaceHandlers;
556 * The class provides a convenient RAII-style mechanism for the attributes of a
557 * RCSResourceObject. When a LockGuard is created, it attempts to lock the attributes of
558 * the RCSResourceObject it is given. When control leaves the scope in which the LockGuard
559 * object was created, the LockGuard is destructed and the attributes is unlocked.
561 * Additionally when it is destructed and only when destructed not by stack unwinding
562 * caused by an exception, it tries to notify depending on AutoNotifyPolicy.
564 * @note The destrcutor can throw an exception if auto notify failed.
566 class RCSResourceObject::LockGuard
569 LockGuard(const RCSResourceObject& rcsResourceObject);
571 LockGuard(const RCSResourceObject::Ptr);
574 * Constructs a LockGuard with auto notify policy.
576 * @param object an object to be locked
577 * @param autoNotifyPolicy the policy to indicate how auto notification is handled
578 * when the LockGuard is destructed.
581 LockGuard(const RCSResourceObject& object, AutoNotifyPolicy autoNotifyPolicy);
586 LockGuard(const RCSResourceObject::Ptr, AutoNotifyPolicy);
589 * @throws RCSPlatformException If auto notify operation failed.
591 * @note The exception will never be thrown while stack unwinding.
593 ~LockGuard() noexcept(false);
595 LockGuard(const LockGuard&) = delete;
596 LockGuard(LockGuard&&) = delete;
598 LockGuard& operator=(const LockGuard&) = delete;
599 LockGuard& operator=(LockGuard&&) = delete;
605 const RCSResourceObject& m_resourceObject;
607 AutoNotifyPolicy m_autoNotifyPolicy;
611 std::function<void()> m_autoNotifyFunc;
615 class RCSResourceObject::WeakGuard
618 WeakGuard(const RCSResourceObject&);
621 WeakGuard(const WeakGuard&) = delete;
622 WeakGuard(WeakGuard&&) = delete;
624 WeakGuard& operator=(const WeakGuard&) = delete;
625 WeakGuard& operator=(WeakGuard&&) = delete;
627 bool hasLocked() const;
631 const RCSResourceObject& m_resourceObject;
637 #endif // SERVER_RCSRESOURCEOBJECT_H