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