Merge branch 'group-manager'
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / src / RCSResourceObject.cpp
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 #include "RCSResourceObject.h"
22
23 #include <functional>
24 #include <vector>
25
26 #include "RequestHandler.h"
27 #include "AssertUtils.h"
28 #include "AtomicHelper.h"
29 #include "ResourceAttributesConverter.h"
30 #include "ResourceAttributesUtils.h"
31 #include "RCSRequest.h"
32 #include "RCSRepresentation.h"
33 #include "InterfaceHandler.h"
34
35 #include "logger.h"
36 #include "OCPlatform.h"
37
38 #define LOG_TAG "RCSResourceObject"
39
40 namespace
41 {
42     using namespace OIC::Service;
43
44     inline bool hasProperty(uint8_t base, uint8_t target)
45     {
46         return (base & target) == target;
47     }
48
49     inline uint8_t makePropertyFlags(uint8_t base, uint8_t target, bool add)
50     {
51         if (add)
52         {
53             return base | target;
54         }
55
56         return base & ~target;
57     }
58
59     OCEntityHandlerResult sendResponse(const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
60             const std::shared_ptr< OC::OCResourceResponse >& ocResponse)
61     {
62         ocResponse->setRequestHandle(ocRequest->getRequestHandle());
63         ocResponse->setResourceHandle(ocRequest->getResourceHandle());
64
65         try
66         {
67             if (OC::OCPlatform::sendResponse(ocResponse) == OC_STACK_OK)
68             {
69                 return OC_EH_OK;
70             }
71         }
72         catch (const OC::OCException& e)
73         {
74             OIC_LOG_V(WARNING, LOG_TAG, "Error (%s)", e.what());
75         }
76
77         return OC_EH_ERROR;
78     }
79
80     RCSResourceAttributes getAttributesFromOCRequest(
81             const std::shared_ptr< OC::OCResourceRequest >& request)
82     {
83         return ResourceAttributesConverter::fromOCRepresentation(
84                 request->getResourceRepresentation());
85     }
86
87     template< typename HANDLER, typename RESPONSE =
88             typename std::decay<HANDLER>::type::result_type >
89     RESPONSE invokeHandler(const RCSResourceObject::Ptr& resObj, RCSResourceAttributes& attrs,
90             const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
91             std::shared_ptr< HANDLER > handler)
92     {
93         if (handler)
94         {
95             return (*handler)(RCSRequest{ resObj, ocRequest }, attrs);
96         }
97
98         return RESPONSE::defaultAction();
99     }
100
101     typedef void (RCSResourceObject::* AutoNotifyFunc)
102             (bool, RCSResourceObject::AutoNotifyPolicy) const;
103
104     std::function<void()> createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc,
105             const RCSResourceObject& resourceObject,
106             const RCSResourceAttributes& resourceAttributes,
107             RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy)
108     {
109         if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED)
110         {
111             auto&& compareAttributesFunc =
112                     std::bind(std::not_equal_to<RCSResourceAttributes>(),
113                                 resourceAttributes,
114                                 std::cref(resourceAttributes));
115             return std::bind(autoNotifyFunc,
116                     &resourceObject, std::move(compareAttributesFunc), autoNotifyPolicy);
117         }
118         else if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::ALWAYS)
119         {
120             return std::bind(autoNotifyFunc,
121                     &resourceObject, true, autoNotifyPolicy);
122         }
123         return {};
124     }
125
126 } // unnamed namespace
127
128 namespace OIC
129 {
130     namespace Service
131     {
132
133         RCSResourceObject::Builder::Builder(std::string uri, std::string type,
134                 std::string interface) :
135                 m_uri{ std::move(uri) },
136                 m_types{ std::move(type) },
137                 m_interfaces{ std::move(interface) },
138                 m_defaultInterface { BASELINE_INTERFACE },
139                 m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE },
140                 m_resourceAttributes{ }
141         {
142         }
143
144         RCSResourceObject::Builder& RCSResourceObject::Builder::addInterface(std::string interface)
145         {
146             m_interfaces.push_back(std::move(interface));
147             return *this;
148         }
149
150         RCSResourceObject::Builder& RCSResourceObject::Builder::addType(std::string type)
151         {
152             m_types.push_back(std::move(type));
153             return *this;
154         }
155
156         RCSResourceObject::Builder& RCSResourceObject::Builder::setDefaultInterface(
157                 std::string interface)
158         {
159             if (std::find(m_interfaces.begin(), m_interfaces.end(), interface) ==
160                     m_interfaces.end())
161             {
162                 throw RCSBadRequestException{"The interface should be added, first."};
163             }
164
165             m_defaultInterface = std::move(interface);
166
167             return *this;
168         }
169
170         RCSResourceObject::Builder& RCSResourceObject::Builder::setDiscoverable(
171                 bool discoverable)
172         {
173             m_properties = ::makePropertyFlags(m_properties, OC_DISCOVERABLE, discoverable);
174             return *this;
175         }
176
177         RCSResourceObject::Builder& RCSResourceObject::Builder::setObservable(
178                 bool observable)
179         {
180             m_properties = ::makePropertyFlags(m_properties, OC_OBSERVABLE, observable);
181             return *this;
182         }
183
184         RCSResourceObject::Builder& RCSResourceObject::Builder::setSecureFlag(
185             bool secureFlag)
186         {
187             m_properties = ::makePropertyFlags(m_properties, OC_SECURE, secureFlag);
188             return *this;
189         }
190         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
191                 const RCSResourceAttributes& attrs)
192         {
193             m_resourceAttributes = attrs;
194             return *this;
195         }
196
197         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
198                 RCSResourceAttributes&& attrs)
199         {
200             m_resourceAttributes = std::move(attrs);
201             return *this;
202         }
203
204         RCSResourceObject::Ptr RCSResourceObject::Builder::build()
205         {
206             OCResourceHandle handle{ nullptr };
207
208             RCSResourceObject::Ptr server {
209                 new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } };
210
211             OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
212                     std::weak_ptr< RCSResourceObject >{ server }, std::placeholders::_1) };
213
214             typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
215                     const std::string&, const std::string&, OC::EntityHandler, uint8_t);
216
217             invokeOCFunc(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
218                     handle, m_uri, m_types[0], m_interfaces[0], entityHandler, m_properties);
219
220             std::for_each(m_interfaces.begin() + 1, m_interfaces.end(),
221                     [&handle](const std::string& interfaceName){
222                 invokeOCFunc(OC::OCPlatform::bindInterfaceToResource, handle, interfaceName);
223             });
224
225             std::for_each(m_types.begin() + 1, m_types.end(),
226                     [&handle](const std::string& typeName){
227                 invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName);
228             });
229
230             server->init(handle, m_interfaces, m_types, m_defaultInterface);
231
232             return server;
233         }
234
235
236         RCSResourceObject::RCSResourceObject(const std::string& uri,
237                 uint8_t properties, RCSResourceAttributes&& attrs) :
238                 m_properties{ properties },
239                 m_uri{ uri },
240                 m_interfaces{ },
241                 m_types{ },
242                 m_defaultInterface{ },
243                 m_resourceHandle{ },
244                 m_resourceAttributes{ std::move(attrs) },
245                 m_getRequestHandler{ },
246                 m_setRequestHandler{ },
247                 m_autoNotifyPolicy{ AutoNotifyPolicy::UPDATED },
248                 m_setRequestHandlerPolicy{ SetRequestHandlerPolicy::NEVER },
249                 m_attributeUpdatedListeners{ },
250                 m_lockOwner{ },
251                 m_mutex{ },
252                 m_mutexAttributeUpdatedListeners{ }
253         {
254             m_lockOwner.reset(new AtomicThreadId);
255         }
256
257         void RCSResourceObject::init(OCResourceHandle handle,
258                 const std::vector< std::string >& interfaces,
259                 const std::vector< std::string >& types,
260                 const std::string& defaultInterface)
261         {
262             m_resourceHandle = handle;
263             m_interfaces = interfaces;
264             m_types = types;
265             m_defaultInterface = defaultInterface;
266
267             for (const auto& itf : interfaces)
268             {
269                 m_interfaceHandlers.insert({ itf, getDefaultInterfaceHandler(itf,
270                         m_defaultInterface) });
271             }
272         }
273
274         RCSResourceObject::~RCSResourceObject()
275         {
276             if (m_resourceHandle)
277             {
278                 try
279                 {
280                     invokeOCFunc(OC::OCPlatform::unregisterResource, m_resourceHandle);
281                 }
282                 catch (...)
283                 {
284                     OIC_LOG(WARNING, LOG_TAG, "Failed to unregister resource.");
285                 }
286             }
287         }
288
289         template< typename K, typename V >
290         void RCSResourceObject::setAttributeInternal(K&& key, V&& value)
291         {
292             bool needToNotify = false;
293             bool valueUpdated = false;
294
295             {
296                 WeakGuard lock(*this);
297
298                 if (lock.hasLocked())
299                 {
300                     needToNotify = true;
301                     valueUpdated = testValueUpdated(key, value);
302                 }
303
304                 m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
305             }
306
307             if (needToNotify) autoNotify(valueUpdated);
308         }
309         void RCSResourceObject::setAttribute(const std::string& key,
310                 const RCSResourceAttributes::Value& value)
311         {
312             setAttributeInternal(key, value);
313         }
314
315         void RCSResourceObject::setAttribute(const std::string& key,
316                 RCSResourceAttributes::Value&& value)
317         {
318             setAttributeInternal(key, std::move(value));
319         }
320
321         void RCSResourceObject::setAttribute(std::string&& key,
322                 const RCSResourceAttributes::Value& value)
323         {
324             setAttributeInternal(std::move(key), value);
325         }
326
327         void RCSResourceObject::setAttribute(std::string&& key,
328                 RCSResourceAttributes::Value&& value)
329         {
330             setAttributeInternal(std::move(key), std::move(value));
331         }
332
333         RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
334                 const std::string& key) const
335         {
336             WeakGuard lock(*this);
337             return m_resourceAttributes.at(key);
338         }
339
340         bool RCSResourceObject::removeAttribute(const std::string& key)
341         {
342             bool needToNotify = false;
343             bool erased = false;
344             {
345                 WeakGuard lock(*this);
346
347                 if (m_resourceAttributes.erase(key))
348                 {
349                     erased = true;
350                     needToNotify = lock.hasLocked();
351                 }
352             }
353
354             if (needToNotify) autoNotify(true);
355
356             return erased;
357         }
358
359         bool RCSResourceObject::containsAttribute(const std::string& key) const
360         {
361             WeakGuard lock(*this);
362             return m_resourceAttributes.contains(key);
363         }
364
365         RCSResourceAttributes& RCSResourceObject::getAttributes()
366         {
367             expectOwnLock();
368             return m_resourceAttributes;
369         }
370
371         const RCSResourceAttributes& RCSResourceObject::getAttributes() const
372         {
373             expectOwnLock();
374             return m_resourceAttributes;
375         }
376
377         void RCSResourceObject::expectOwnLock() const
378         {
379             if (getLockOwner() != std::this_thread::get_id())
380             {
381                 throw NoLockException{ "Must acquire the lock first using LockGuard." };
382             }
383         }
384
385         std::thread::id RCSResourceObject::getLockOwner() const noexcept
386         {
387             return *m_lockOwner;
388         }
389
390         void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
391         {
392             m_lockOwner->store(std::move(id));
393         }
394
395         bool RCSResourceObject::isObservable() const
396         {
397             return ::hasProperty(m_properties, OC_OBSERVABLE);
398         }
399
400         bool RCSResourceObject::isDiscoverable() const
401         {
402             return ::hasProperty(m_properties, OC_DISCOVERABLE);
403         }
404
405         void RCSResourceObject::setGetRequestHandler(GetRequestHandler h)
406         {
407             m_getRequestHandler = std::make_shared< GetRequestHandler >(std::move(h));
408         }
409
410         void RCSResourceObject::setSetRequestHandler(SetRequestHandler h)
411         {
412             m_setRequestHandler = std::make_shared< SetRequestHandler >(std::move(h));
413         }
414
415         void RCSResourceObject::notify() const
416         {
417             typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
418
419             invokeOCFuncWithResultExpect({ OC_STACK_OK, OC_STACK_NO_OBSERVERS },
420                     static_cast< NotifyAllObservers >(OC::OCPlatform::notifyAllObservers),
421                     m_resourceHandle);
422         }
423
424         void RCSResourceObject::addAttributeUpdatedListener(const std::string& key,
425                 AttributeUpdatedListener h)
426         {
427             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
428
429             m_attributeUpdatedListeners[key] =
430                     std::make_shared< AttributeUpdatedListener >(std::move(h));
431         }
432
433         void RCSResourceObject::addAttributeUpdatedListener(std::string&& key,
434                 AttributeUpdatedListener h)
435         {
436             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
437
438             m_attributeUpdatedListeners[std::move(key)] =
439                     std::make_shared< AttributeUpdatedListener >(std::move(h));
440         }
441
442         bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key)
443         {
444             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
445
446             return m_attributeUpdatedListeners.erase(key) != 0;
447         }
448
449         bool RCSResourceObject::testValueUpdated(const std::string& key,
450                 const RCSResourceAttributes::Value& value) const
451         {
452             return m_resourceAttributes.contains(key) == false
453                     || m_resourceAttributes.at(key) != value;
454         }
455
456         void RCSResourceObject::setAutoNotifyPolicy(AutoNotifyPolicy policy)
457         {
458             m_autoNotifyPolicy = policy;
459         }
460
461         RCSResourceObject::AutoNotifyPolicy RCSResourceObject::getAutoNotifyPolicy() const
462         {
463             return m_autoNotifyPolicy;
464         }
465
466         void RCSResourceObject::setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
467         {
468             m_setRequestHandlerPolicy = policy;
469         }
470
471         auto RCSResourceObject::getSetRequestHandlerPolicy() const -> SetRequestHandlerPolicy
472         {
473             return m_setRequestHandlerPolicy;
474         }
475
476         void RCSResourceObject::bindResource(const RCSResourceObject::Ptr& resource)
477         {
478             if (!resource || resource.get() == this)
479             {
480                 throw RCSInvalidParameterException("The resource is invalid!");
481             }
482
483             invokeOCFunc(OC::OCPlatform::bindResource,
484                     m_resourceHandle, resource->m_resourceHandle);
485
486             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
487             m_boundResources.push_back(resource);
488         }
489
490         void RCSResourceObject::unbindResource(const RCSResourceObject::Ptr& resource)
491         {
492             if (!resource || resource.get() == this)
493             {
494                 throw RCSInvalidParameterException("The resource is invalid!");
495             }
496
497             invokeOCFunc(OC::OCPlatform::unbindResource,
498                     m_resourceHandle, resource->m_resourceHandle);
499
500             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
501             m_boundResources.erase(std::find(m_boundResources.begin(), m_boundResources.end(),
502                     resource));
503         }
504
505         std::vector< RCSResourceObject::Ptr > RCSResourceObject::getBoundResources() const
506         {
507             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
508             return m_boundResources;
509         }
510
511         std::string RCSResourceObject::getUri() const
512         {
513             return m_uri;
514         }
515
516         std::string RCSResourceObject::getDefaultInterface() const
517         {
518             return m_defaultInterface;
519         }
520
521         std::vector< std::string > RCSResourceObject::getInterfaces() const
522         {
523             return m_interfaces;
524         }
525
526         std::vector< std::string > RCSResourceObject::getTypes() const
527         {
528             return m_types;
529         }
530
531         RCSRepresentation RCSResourceObject::getRepresentation(const RCSRequest& request) const
532         {
533             if (request.getOCRequest()->getRequestType() == "GET")
534             {
535                 return findInterfaceHandler(
536                         request.getInterface()).getGetResponseBuilder()(request, *this);
537             }
538
539             if (request.getOCRequest()->getRequestType() == "POST")
540             {
541                 return findInterfaceHandler(
542                         request.getInterface()).getSetResponseBuilder()(request, *this);
543             }
544
545             throw RCSBadRequestException{ "Unsupported request type!" };
546         }
547
548         void RCSResourceObject::autoNotify(bool isAttributesChanged) const
549         {
550             autoNotify(isAttributesChanged, m_autoNotifyPolicy);
551         }
552
553         void RCSResourceObject::autoNotify(
554                         bool isAttributesChanged, AutoNotifyPolicy autoNotifyPolicy) const
555         {
556             if(autoNotifyPolicy == AutoNotifyPolicy::NEVER) return;
557             if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED &&
558                     isAttributesChanged == false) return;
559
560             notify();
561         }
562
563         OCEntityHandlerResult RCSResourceObject::entityHandler(
564                 const std::weak_ptr< RCSResourceObject >& weakRes,
565                 const std::shared_ptr< OC::OCResourceRequest >& request)
566         {
567             auto resource = weakRes.lock();
568
569             if (!resource) return OC_EH_ERROR;
570
571             OIC_LOG(WARNING, LOG_TAG, "entityHandler");
572             if (!request)
573             {
574                 return OC_EH_ERROR;
575             }
576
577             try
578             {
579                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
580                 {
581                     return resource->handleRequest(request);
582                 }
583
584                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
585                 {
586                     return resource->handleObserve(request);
587                 }
588             }
589             catch (const std::exception& e)
590             {
591                 OIC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what());
592                 throw;
593             }
594             catch (...)
595             {
596                 OIC_LOG(WARNING, LOG_TAG, "Failed to handle request.");
597                 throw;
598             }
599
600             return OC_EH_ERROR;
601         }
602
603         OCEntityHandlerResult RCSResourceObject::handleRequest(
604                 const std::shared_ptr< OC::OCResourceRequest >& request)
605         {
606             assert(request != nullptr);
607
608             RCSRequest rcsRequest{ shared_from_this(), request };
609
610             if (rcsRequest.getInterface() != "" && m_interfaceHandlers.find(
611                     rcsRequest.getInterface()) == m_interfaceHandlers.end())
612             {
613                 return OC_EH_ERROR;
614             }
615
616             if (request->getRequestType() == "GET")
617             {
618                 return handleRequestGet(rcsRequest);
619             }
620
621             if (request->getRequestType() == "POST")
622             {
623                 return handleRequestSet(rcsRequest);
624             }
625
626             return OC_EH_ERROR;
627         }
628
629         OCEntityHandlerResult RCSResourceObject::handleRequestGet(
630                 const RCSRequest& request)
631         {
632             if (!findInterfaceHandler(request.getInterface()).isGetSupported())
633             {
634                 return OC_EH_ERROR;
635             }
636
637             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
638             auto response = invokeHandler(shared_from_this(), attrs, request.getOCRequest(),
639                     m_getRequestHandler);
640
641             if (response.isSeparate()) return OC_EH_SLOW;
642
643             return sendResponse(request, response,
644                          findInterfaceHandler(request.getInterface()).getGetResponseBuilder());
645         }
646
647         bool RCSResourceObject::applyAcceptanceMethod(
648                 const RCSSetResponse& response, const RCSResourceAttributes& requestAttrs)
649         {
650             auto requestHandler = response.getHandler();
651
652             assert(requestHandler != nullptr);
653
654             RCSResourceAttributes result;
655
656             auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(),
657                     *this, requestAttrs);
658
659             OIC_LOG_V(WARNING, LOG_TAG, "replaced num %zu", replaced.size());
660             for (const auto& attrKeyValPair : replaced)
661             {
662                 std::shared_ptr< AttributeUpdatedListener > foundListener;
663                 {
664                     std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
665
666                     auto it = m_attributeUpdatedListeners.find(attrKeyValPair.first);
667                     if (it != m_attributeUpdatedListeners.end())
668                     {
669                         foundListener = it->second;
670                     }
671                 }
672
673                 if (foundListener)
674                 {
675                     (*foundListener)(attrKeyValPair.second, requestAttrs.at(attrKeyValPair.first));
676                 }
677             }
678
679             return !replaced.empty();
680         }
681
682         OCEntityHandlerResult RCSResourceObject::handleRequestSet(
683                 const RCSRequest& request)
684         {
685             if (!findInterfaceHandler(request.getInterface()).isSetSupported())
686             {
687                 return OC_EH_ERROR;
688             }
689
690             auto attrs = getAttributesFromOCRequest(request.getOCRequest());
691
692             auto response = invokeHandler(shared_from_this(), attrs, request.getOCRequest(),
693                     m_setRequestHandler);
694
695             if (response.isSeparate()) return OC_EH_SLOW;
696
697             autoNotify(applyAcceptanceMethod(response, attrs), m_autoNotifyPolicy);
698
699             return sendResponse(request, response,
700                     findInterfaceHandler(request.getInterface()).getSetResponseBuilder());
701         }
702
703         OCEntityHandlerResult RCSResourceObject::handleObserve(
704                 const std::shared_ptr< OC::OCResourceRequest >&)
705         {
706             if (!isObservable())
707             {
708                 return OC_EH_ERROR;
709             }
710
711             return OC_EH_OK;
712         }
713
714         InterfaceHandler RCSResourceObject::findInterfaceHandler(
715                 const std::string& interfaceName) const
716         {
717             auto it = m_interfaceHandlers.find(interfaceName);
718
719             if (it != m_interfaceHandlers.end()) return it->second;
720
721             assert(m_interfaceHandlers.find(m_defaultInterface) != m_interfaceHandlers.end());
722
723             return m_interfaceHandlers.find(m_defaultInterface)->second;
724         }
725
726         template <typename RESPONSE, typename RESPONSE_BUILDER>
727         OCEntityHandlerResult RCSResourceObject::sendResponse(
728                 const RCSRequest& request, const RESPONSE& response,
729                 const RESPONSE_BUILDER& resBuilder)
730         {
731             auto reqHandler = response.getHandler();
732             auto ocResponse = std::make_shared< OC::OCResourceResponse >();
733
734             ocResponse->setResponseResult(OC_EH_OK);
735             ocResponse->setErrorCode(reqHandler->getErrorCode());
736
737             if (reqHandler->hasCustomRepresentation())
738             {
739                 ocResponse->setResourceRepresentation(reqHandler->getRepresentation());
740             }
741             else
742             {
743                 ocResponse->setResourceRepresentation(
744                         RCSRepresentation::toOCRepresentation(resBuilder(request, *this)));
745             }
746
747             return ::sendResponse(request.getOCRequest(), ocResponse);
748         }
749
750
751         RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) :
752                 m_resourceObject(*ptr),
753                 m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() },
754                 m_isOwningLock{ false }
755         {
756             init();
757         }
758
759         RCSResourceObject::LockGuard::LockGuard(
760                 const RCSResourceObject& serverResource) :
761                 m_resourceObject(serverResource),
762                 m_autoNotifyPolicy{ serverResource.getAutoNotifyPolicy() },
763                 m_isOwningLock{ false }
764         {
765             init();
766         }
767
768         RCSResourceObject::LockGuard::LockGuard(
769                 const RCSResourceObject::Ptr ptr, AutoNotifyPolicy autoNotifyPolicy) :
770                 m_resourceObject(*ptr),
771                 m_autoNotifyPolicy { autoNotifyPolicy },
772                 m_isOwningLock{ false }
773         {
774             init();
775         }
776
777         RCSResourceObject::LockGuard::LockGuard(
778                 const RCSResourceObject& resourceObject, AutoNotifyPolicy autoNotifyPolicy) :
779                 m_resourceObject(resourceObject),
780                 m_autoNotifyPolicy { autoNotifyPolicy },
781                 m_isOwningLock{ false }
782         {
783             init();
784         }
785
786         RCSResourceObject::LockGuard::~LockGuard() noexcept(false)
787         {
788             if (!std::uncaught_exception() && m_autoNotifyFunc) m_autoNotifyFunc();
789
790             if (m_isOwningLock)
791             {
792                 m_resourceObject.setLockOwner(std::thread::id{ });
793                 m_resourceObject.m_mutex.unlock();
794             }
795         }
796
797         void RCSResourceObject::LockGuard::init()
798         {
799             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
800             {
801                 m_resourceObject.m_mutex.lock();
802                 m_resourceObject.setLockOwner(std::this_thread::get_id());
803                 m_isOwningLock = true;
804             }
805             m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
806                     m_resourceObject, m_resourceObject.m_resourceAttributes, m_autoNotifyPolicy);
807         }
808
809         RCSResourceObject::WeakGuard::WeakGuard(
810                 const RCSResourceObject& resourceObject) :
811                 m_isOwningLock{ false },
812                 m_resourceObject(resourceObject)
813         {
814             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
815             {
816                 m_resourceObject.m_mutex.lock();
817                 m_resourceObject.setLockOwner(std::this_thread::get_id());
818                 m_isOwningLock = true;
819             }
820         }
821
822         RCSResourceObject::WeakGuard::~WeakGuard()
823         {
824             if (m_isOwningLock)
825             {
826                 m_resourceObject.setLockOwner(std::thread::id{ });
827                 m_resourceObject.m_mutex.unlock();
828             }
829         }
830
831         bool RCSResourceObject::WeakGuard::hasLocked() const
832         {
833             return m_isOwningLock;
834         }
835
836     }
837 }