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