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