From 2c2004951d594a71a57978816a74d5dc2427d51a Mon Sep 17 00:00:00 2001 From: "jaesick.shin" Date: Thu, 25 Feb 2016 14:54:55 +0900 Subject: [PATCH] modified RCSResourceObject to generate responses according to the interface of requests. Generate response for each of interface. (supported interfaces - oic.if.baseline, oic.if.a, oic.if.s, oic.if.b) User can setting the default Interface. If user not setting the default interface -> RE setting The default interface "oic.if.baseline" Change-Id: If4faa93bb97850587bc44c7df5e6495796544c18 Signed-off-by: jaesick.shin Reviewed-on: https://gerrit.iotivity.org/gerrit/5195 Reviewed-by: JungHo Kim Tested-by: JungHo Kim --- .../examples/linux/SampleResourceClient.cpp | 116 +++++++++++- .../examples/linux/SampleResourceServer.cpp | 14 +- .../include/RCSResourceObject.h | 33 +++- .../src/serverBuilder/include/InterfaceHandler.h | 68 +++++++ .../src/serverBuilder/include/RequestHandler.h | 23 +-- .../src/serverBuilder/src/InterfaceHandler.cpp | 135 ++++++++++++++ .../src/serverBuilder/src/RCSResourceObject.cpp | 200 +++++++++++++-------- .../src/serverBuilder/src/RequestHandler.cpp | 64 +++---- .../serverBuilder/unittests/RCSResponseTest.cpp | 138 +------------- .../serverBuilder/unittests/RequestHandlerTest.cpp | 35 +--- 10 files changed, 523 insertions(+), 303 deletions(-) create mode 100644 service/resource-encapsulation/src/serverBuilder/include/InterfaceHandler.h create mode 100644 service/resource-encapsulation/src/serverBuilder/src/InterfaceHandler.cpp diff --git a/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp b/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp index 61287a0..f911d62 100755 --- a/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp +++ b/service/resource-encapsulation/examples/linux/SampleResourceClient.cpp @@ -21,6 +21,7 @@ #include #include "RCSDiscoveryManager.h" +#include "RCSRepresentation.h" #include "RCSRemoteResourceObject.h" #include "RCSResourceAttributes.h" #include "RCSAddress.h" @@ -138,6 +139,30 @@ void handleItems(const std::vector& items) selectItem(items); } +std::string inputInterface() +{ + std::string interfaceName; + + std::cout << "\tInput the Interface you want to set : "; + std::cin >> interfaceName; + + return interfaceName; +} + +RCSResourceAttributes inputKeyValue() +{ + std::string key; + + std::cout << "\tEnter the Key you want to set : "; + std::cin >> key; + + std::cout << "\tEnter the value(INT) you want to set :"; + RCSResourceAttributes attrs; + attrs[key] = processUserInput(); + + return attrs; +} + void printAttribute(const std::string& key, const RCSResourceAttributes::Value& value) { std::cout << "\tkey : " << key << std::endl @@ -157,6 +182,60 @@ void printAttributes(const RCSResourceAttributes& attributes) } } +void print(const std::string& name, const std::vector< std::string >& elements) +{ + if (elements.empty()) + { + std::cout << "\t" << name << " is empty" << std::endl; + return; + } + + std::cout << "\t" << name << " : " << std::endl; + for(const auto& item : elements) + { + std::cout << item << " "; + } + std::cout << std::endl; +} + +void printUri(const std::string& uri) +{ + if(uri.empty()) + { + std::cout << "\turi is empty" << std::endl; + } + else + { + std::cout << "\turi : " << uri << std::endl; + } +} + +void printRepresentation(const RCSRepresentation& rep) +{ + printUri(rep.getUri()); + print("interfaces", rep.getInterfaces()); + print("resourceTypes", rep.getResourceTypes()); + printAttributes(rep.getAttributes()); + + const auto& children = rep.getChildren(); + + if(children.empty()) + { + std::cout << "\tchildren is empty" << std::endl; + } + else + { + int cnt = 0; + for(const auto& child : children) + { + std::cout << "========================================================" << std::endl; + std::cout << ++cnt << " chlid" << std::endl; + printRepresentation(child); + std::cout << "========================================================" << std::endl; + } + } +} + void onResourceStateChanged(ResourceState resourceState) { std::cout << "onResourceStateChanged callback" << std::endl; @@ -199,6 +278,20 @@ void onRemoteAttributesReceived(const RCSResourceAttributes& attributes, int) printAttributes(attributes); } +void onRemoteGetReceived(const HeaderOpts&, const RCSRepresentation& rep, int) +{ + std::cout << "onRemoteGetReceived callback" << std::endl; + + printRepresentation(rep); +} + +void onRemoteSetReceived(const HeaderOpts&, const RCSRepresentation& rep, int) +{ + std::cout << "onRemoteSetReceived callback" << std::endl; + + printRepresentation(rep); +} + void startMonitoring() { if (g_selectedResource->isMonitoring()) @@ -230,16 +323,23 @@ void getRemoteAttributes() void setRemoteAttributes() { - std::string key; + g_selectedResource->setRemoteAttributes(inputKeyValue(), onRemoteAttributesReceived); +} - std::cout << "\tEnter the Key you want to set : "; - std::cin >> key; +void getWithInterface() +{ + RCSQueryParams queryParams; + queryParams.setResourceInterface(inputInterface()); - std::cout << "\tEnter the value(INT) you want to set :"; - RCSResourceAttributes attrs; - attrs[key] = processUserInput(); + g_selectedResource->get(queryParams, onRemoteGetReceived); +} + +void setWithInterface() +{ + RCSQueryParams queryParams; + queryParams.setResourceInterface(inputInterface()); - g_selectedResource->setRemoteAttributes(attrs, onRemoteAttributesReceived); + g_selectedResource->set(queryParams, inputKeyValue(), onRemoteSetReceived); } void startCaching(RCSRemoteResourceObject::CacheUpdatedCallback cb) @@ -381,6 +481,8 @@ void runResourceControl() DECLARE_MENU(stopMonitoring), DECLARE_MENU(getRemoteAttributes), DECLARE_MENU(setRemoteAttributes), + DECLARE_MENU(getWithInterface), + DECLARE_MENU(setWithInterface), DECLARE_MENU(startCachingWithoutCallback), DECLARE_MENU(startCachingWithCallback), DECLARE_MENU(getResourceCacheState), diff --git a/service/resource-encapsulation/examples/linux/SampleResourceServer.cpp b/service/resource-encapsulation/examples/linux/SampleResourceServer.cpp index 7c4532a..a8946d2 100755 --- a/service/resource-encapsulation/examples/linux/SampleResourceServer.cpp +++ b/service/resource-encapsulation/examples/linux/SampleResourceServer.cpp @@ -35,6 +35,11 @@ constexpr int CUSTOM_SERVER = 2; constexpr int INCREASE = 1; constexpr int DECREASE = 2; +const std::string BASELINE_INTERFACE = "oic.if.baseline"; +const std::string ACTUATOR_INTERFACE = "oic.if.a"; +const std::string SENSOR_INTERFACE = "oic.if.s"; +const std::string CUSTOM_INTERFACE = "test.custom"; + typedef void (*DisplayControlMenuFunc)(); typedef std::function Run; @@ -116,8 +121,13 @@ RCSSetResponse requestHandlerForSet(const RCSRequest&, RCSResourceAttributes& at void initServer(const std::string& resourceUri, const std::string& resourceType, const std::string& attrKey) { - g_resource = RCSResourceObject::Builder(resourceUri, resourceType, "oic.if."). - setDiscoverable(true).setObservable(true).build(); + g_resource = RCSResourceObject::Builder(resourceUri, resourceType, ACTUATOR_INTERFACE) + .addInterface(CUSTOM_INTERFACE) + .addInterface(SENSOR_INTERFACE) + .setDefaultInterface(SENSOR_INTERFACE) + .setDiscoverable(true) + .setObservable(true) + .build(); g_resource->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED); g_resource->setSetRequestHandlerPolicy(RCSResourceObject::SetRequestHandlerPolicy::NEVER); diff --git a/service/resource-encapsulation/include/RCSResourceObject.h b/service/resource-encapsulation/include/RCSResourceObject.h index 9eb4543..e913293 100644 --- a/service/resource-encapsulation/include/RCSResourceObject.h +++ b/service/resource-encapsulation/include/RCSResourceObject.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "RCSResourceAttributes.h" #include "RCSResponse.h" @@ -45,6 +46,7 @@ namespace OIC class RCSRequest; class RCSRepresentation; + class InterfaceHandler; /** * @brief Thrown when lock has not been acquired. @@ -149,6 +151,14 @@ namespace OIC Builder& addType(std::string&& type); /** + * Sets the default interface + * + * @param interface default interface name + * + */ + Builder& setDefaultInterface(std::string interface); + + /** * Sets whether the resource is discoverable. * * @param discoverable whether to be discoverable. @@ -197,6 +207,7 @@ namespace OIC std::string m_uri; std::vector< std::string > m_types; std::vector< std::string > m_interfaces; + std::string m_defaultInterface; uint8_t m_properties; RCSResourceAttributes m_resourceAttributes; }; @@ -462,6 +473,9 @@ namespace OIC std::vector< RCSResourceObject::Ptr > getBoundResources() const; + std::string getUri() const; + std::string getDefaultInterface() const; + std::vector< std::string > getInterfaces() const; std::vector< std::string > getTypes() const; @@ -470,14 +484,21 @@ namespace OIC private: RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&); + void init(OCResourceHandle, const std::vector< std::string >&, + const std::vector< std::string >&, const std::string&); + static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&, const std::shared_ptr< OC::OCResourceRequest >&); OCEntityHandlerResult handleRequest(const std::shared_ptr< OC::OCResourceRequest >&); - OCEntityHandlerResult handleRequestGet(const std::shared_ptr< OC::OCResourceRequest >&); - OCEntityHandlerResult handleRequestSet(const std::shared_ptr< OC::OCResourceRequest >&); + OCEntityHandlerResult handleRequestGet(const RCSRequest&); + OCEntityHandlerResult handleRequestSet(const RCSRequest&); OCEntityHandlerResult handleObserve(const std::shared_ptr< OC::OCResourceRequest >&); + template + OCEntityHandlerResult sendResponse(const RCSRequest&, + const RESPONSE&, const RESPONSE_BUILDER&); + void expectOwnLock() const; std::thread::id getLockOwner() const noexcept; @@ -492,7 +513,10 @@ namespace OIC template< typename K, typename V > void setAttributeInternal(K&&, V&&); - bool applyAcceptanceMethod(const RCSSetResponse&, const RCSResourceAttributes&); + RCSResourceAttributes applyAcceptanceMethod(const RCSSetResponse&, + const RCSResourceAttributes&); + + InterfaceHandler findInterfaceHandler(const std::string&) const; private: const uint8_t m_properties; @@ -500,6 +524,7 @@ namespace OIC const std::string m_uri; std::vector< std::string > m_interfaces; std::vector< std::string > m_types; + std::string m_defaultInterface; OCResourceHandle m_resourceHandle; @@ -523,6 +548,8 @@ namespace OIC std::vector< RCSResourceObject::Ptr > m_boundResources; + std::map< std::string, InterfaceHandler > m_interfaceHandlers; + }; /** diff --git a/service/resource-encapsulation/src/serverBuilder/include/InterfaceHandler.h b/service/resource-encapsulation/src/serverBuilder/include/InterfaceHandler.h new file mode 100644 index 0000000..2f8150f --- /dev/null +++ b/service/resource-encapsulation/src/serverBuilder/include/InterfaceHandler.h @@ -0,0 +1,68 @@ +//****************************************************************** +// +// Copyright 2015 Samsung Electronics All Rights Reserved. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +#ifndef RE_INTERFACEHANDLER_H_ +#define RE_INTERFACEHANDLER_H_ + +#include +#include + +namespace OIC +{ + namespace Service + { + class RCSRequest; + class RCSResourceObject; + class RCSRepresentation; + class RCSResourceAttributes; + + const std::string BASELINE_INTERFACE = "oic.if.baseline"; + const std::string ACTUATOR_INTERFACE = "oic.if.a"; + const std::string SENSOR_INTERFACE = "oic.if.s"; + const std::string BATCH_INTERFACE = "oic.if.b"; + + class InterfaceHandler + { + public: + typedef std::function< RCSRepresentation(RCSRequest, RCSResourceObject&) > + GetResponseBuilder; + + typedef std::function< RCSRepresentation(RCSRequest, RCSResourceObject&) > + SetResponseBuilder; + + public: + InterfaceHandler(GetResponseBuilder, SetResponseBuilder); + + bool isGetSupported() const; + bool isSetSupported() const; + + GetResponseBuilder getGetResponseBuilder() const; + SetResponseBuilder getSetResponseBuilder() const; + + private: + GetResponseBuilder m_getBuilder; + SetResponseBuilder m_setBuilder; + }; + + InterfaceHandler getDefaultInterfaceHandler(const std::string&, const std::string&); + } +} + +#endif /* RE_INTERFACEHANDLER_H_ */ diff --git a/service/resource-encapsulation/src/serverBuilder/include/RequestHandler.h b/service/resource-encapsulation/src/serverBuilder/include/RequestHandler.h index 8c6f345..41a7285 100644 --- a/service/resource-encapsulation/src/serverBuilder/include/RequestHandler.h +++ b/service/resource-encapsulation/src/serverBuilder/include/RequestHandler.h @@ -21,12 +21,11 @@ #ifndef SERVERBUILDER_REQUESTHANDLER_H #define SERVERBUILDER_REQUESTHANDLER_H -#include -#include +#include "RCSResponse.h" +#include "RCSResourceAttributes.h" namespace OC { - class OCResourceResponse; class OCRepresentation; } @@ -40,13 +39,9 @@ namespace OIC class RequestHandler { private: - typedef std::function< std::shared_ptr< OC::OCResourceResponse >(RCSResourceObject&) > - BuildResponseHolder; + typedef std::function< OC::OCRepresentation() > RepresentationBuilder; public: - typedef std::shared_ptr< RequestHandler > Pre; - - static constexpr int DEFAULT_ERROR_CODE = 200; RequestHandler(); @@ -61,10 +56,18 @@ namespace OIC virtual ~RequestHandler() { }; - std::shared_ptr< OC::OCResourceResponse > buildResponse(RCSResourceObject&); + int getErrorCode() const; + + bool hasCustomRepresentation() const; + + OC::OCRepresentation getRepresentation() const; + + public: + static constexpr int DEFAULT_ERROR_CODE = 200; private: - const BuildResponseHolder m_holder; + const int m_errorCode; + const RepresentationBuilder m_repBuilder; }; class SetRequestHandler: public RequestHandler diff --git a/service/resource-encapsulation/src/serverBuilder/src/InterfaceHandler.cpp b/service/resource-encapsulation/src/serverBuilder/src/InterfaceHandler.cpp new file mode 100644 index 0000000..21422ba --- /dev/null +++ b/service/resource-encapsulation/src/serverBuilder/src/InterfaceHandler.cpp @@ -0,0 +1,135 @@ +#include "InterfaceHandler.h" + +#include "OCApi.h" +#include "OCResourceRequest.h" + +#include "RCSRepresentation.h" +#include "RCSRequest.h" +#include "RCSResourceObject.h" +#include "RCSResourceAttributes.h" +#include "ResourceAttributesConverter.h" + +#include + +namespace +{ + using namespace OIC::Service; + + RCSRepresentation buildGetBaselineResponse(const RCSRequest&, RCSResourceObject& resource) + { + RCSResourceObject::LockGuard lock(resource); + + return RCSRepresentation{ resource.getUri(), resource.getInterfaces(), resource.getTypes(), + resource.getAttributes()}; + } + + RCSRepresentation buildSetBaselineResponse(const RCSRequest& rcsRequest, RCSResourceObject& resource) + { + return buildGetBaselineResponse(rcsRequest, resource); + } + + RCSRepresentation buildGetRequestResponse(const RCSRequest&, RCSResourceObject& resource) + { + RCSResourceObject::LockGuard lock(resource); + + return RCSRepresentation{resource.getAttributes()}; + } + + RCSRepresentation buildSetRequestResponse(const RCSRequest& rcsRequest, RCSResourceObject& resource) + { + auto requestAttr = ResourceAttributesConverter::fromOCRepresentation( + (rcsRequest.getOCRequest())->getResourceRepresentation()); + + RCSResourceObject::LockGuard lock(resource); + + const RCSResourceAttributes& updatedAttr = resource.getAttributes(); + + for (auto& kvPair : requestAttr) + { + if(updatedAttr.contains(kvPair.key())) + { + kvPair.value() = updatedAttr.at(kvPair.key()); + } + else + { + //FIXME erase item with iterator. + requestAttr.erase(kvPair.key()); + } + } + + return RCSRepresentation{ requestAttr }; + } + + RCSRepresentation buildGetBatchResponse(RCSRequest, RCSResourceObject& resource) + { + RCSRepresentation rcsRep; + + for (const auto& bound : resource.getBoundResources()) + { + rcsRep.addChild(bound->toRepresentation()); + } + + return rcsRep; + } + + const std::unordered_map< std::string, InterfaceHandler > g_defaultHandlers { + + { BASELINE_INTERFACE, + InterfaceHandler(buildGetBaselineResponse, buildSetBaselineResponse) }, + + { ACTUATOR_INTERFACE, + InterfaceHandler(buildGetRequestResponse, buildSetRequestResponse) }, + + { SENSOR_INTERFACE, + InterfaceHandler(buildGetRequestResponse, nullptr) }, + + { BATCH_INTERFACE, + InterfaceHandler(buildGetBatchResponse, buildSetBaselineResponse) } + }; +} + +namespace OIC +{ + namespace Service + { + + InterfaceHandler::InterfaceHandler(GetResponseBuilder getBuilder, + SetResponseBuilder setBuilder) : + m_getBuilder{ std::move(getBuilder) }, + m_setBuilder{ std::move(setBuilder) } + { + } + + bool InterfaceHandler::isGetSupported() const + { + return m_getBuilder != nullptr; + } + + bool InterfaceHandler::isSetSupported() const + { + return m_setBuilder != nullptr; + } + + InterfaceHandler::GetResponseBuilder InterfaceHandler::getGetResponseBuilder() const + { + return m_getBuilder; + } + + InterfaceHandler::SetResponseBuilder InterfaceHandler::getSetResponseBuilder() const + { + return m_setBuilder; + } + + InterfaceHandler getDefaultInterfaceHandler(const std::string& interfaceName, + const std::string& defaultInterfaceName) + { + auto it = g_defaultHandlers.find(interfaceName); + if (it != g_defaultHandlers.end()) return it->second; + + it = g_defaultHandlers.find(defaultInterfaceName); + if (it != g_defaultHandlers.end()) return it->second; + + return g_defaultHandlers.find(OIC::Service::BASELINE_INTERFACE)->second; + } + } +} diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp index b93780b..60715ea 100644 --- a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp +++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp @@ -20,7 +20,6 @@ #include "RCSResourceObject.h" -#include #include #include @@ -31,6 +30,7 @@ #include "ResourceAttributesUtils.h" #include "RCSRequest.h" #include "RCSRepresentation.h" +#include "InterfaceHandler.h" #include "logger.h" #include "OCPlatform.h" @@ -56,16 +56,6 @@ namespace return base & ~target; } - inline bool requestContainsInterface(const std::shared_ptr< OC::OCResourceRequest >& request, - const std::string& interface) - { - auto it = request->getQueryParameters().find(OC::Key::INTERFACESKEY); - - if (it == request->getQueryParameters().end()) return false; - - return it->second == interface; - } - OCEntityHandlerResult sendResponse(const std::shared_ptr< OC::OCResourceRequest >& ocRequest, const std::shared_ptr< OC::OCResourceResponse >& ocResponse) { @@ -87,14 +77,6 @@ namespace return OC_EH_ERROR; } - - template - OCEntityHandlerResult sendResponse(RCSResourceObject& resource, - const std::shared_ptr< OC::OCResourceRequest >& ocRequest, RESPONSE&& response) - { - return sendResponse(ocRequest, response.getHandler()->buildResponse(resource)); - } - RCSResourceAttributes getAttributesFromOCRequest( const std::shared_ptr< OC::OCResourceRequest >& request) { @@ -120,7 +102,8 @@ namespace (bool, RCSResourceObject::AutoNotifyPolicy) const; std::function createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc, - const RCSResourceObject& resourceObject, const RCSResourceAttributes& resourceAttributes, + const RCSResourceObject& resourceObject, + const RCSResourceAttributes& resourceAttributes, RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy) { if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED) @@ -140,27 +123,6 @@ namespace return {}; } - OCEntityHandlerResult handleBatchInterfaceGetRequest( - const std::shared_ptr< OC::OCResourceRequest >& request, - const RCSResourceObject* resourceObject) - { - RCSRepresentation rcsRep; - - for (const auto& bound : resourceObject->getBoundResources()) - { - rcsRep.addChild(bound->toRepresentation()); - } - - auto response = std::make_shared< OC::OCResourceResponse >(); - - response->setResponseResult(OC_EH_OK); - response->setErrorCode(200); - response->setResourceRepresentation( - RCSRepresentation::toOCRepresentation(std::move(rcsRep))); - - return sendResponse(request, response); - } - } // unnamed namespace namespace OIC @@ -173,6 +135,7 @@ namespace OIC m_uri{ uri }, m_types{ type }, m_interfaces{ interface }, + m_defaultInterface { BASELINE_INTERFACE }, m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE }, m_resourceAttributes{ } { @@ -202,6 +165,20 @@ namespace OIC return *this; } + RCSResourceObject::Builder& RCSResourceObject::Builder::setDefaultInterface( + std::string interface) + { + if (std::find(m_interfaces.begin(), m_interfaces.end(), interface) == + m_interfaces.end()) + { + throw RCSBadRequestException{"The interface should be added, first."}; + } + + m_defaultInterface = std::move(interface); + + return *this; + } + RCSResourceObject::Builder& RCSResourceObject::Builder::setDiscoverable( bool discoverable) { @@ -262,9 +239,7 @@ namespace OIC invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName); }); - server->m_resourceHandle = handle; - server->m_interfaces = m_interfaces; - server->m_types = m_types; + server->init(handle, m_interfaces, m_types, m_defaultInterface); return server; } @@ -276,6 +251,7 @@ namespace OIC m_uri{ uri }, m_interfaces{ }, m_types{ }, + m_defaultInterface{ }, m_resourceHandle{ }, m_resourceAttributes{ std::move(attrs) }, m_getRequestHandler{ }, @@ -290,6 +266,23 @@ namespace OIC m_lockOwner.reset(new AtomicThreadId); } + void RCSResourceObject::init(OCResourceHandle handle, + const std::vector< std::string >& interfaces, + const std::vector< std::string >& types, + const std::string& defaultInterface) + { + m_resourceHandle = handle; + m_interfaces = interfaces; + m_types = types; + m_defaultInterface = defaultInterface; + + for (const auto& itf : interfaces) + { + m_interfaceHandlers.insert({ itf, getDefaultInterfaceHandler(itf, + m_defaultInterface) }); + } + } + RCSResourceObject::~RCSResourceObject() { if (m_resourceHandle) @@ -527,6 +520,16 @@ namespace OIC return m_boundResources; } + std::string RCSResourceObject::getUri() const + { + return m_uri; + } + + std::string RCSResourceObject::getDefaultInterface() const + { + return m_defaultInterface; + } + std::vector< std::string > RCSResourceObject::getInterfaces() const { return m_interfaces; @@ -541,7 +544,7 @@ namespace OIC { WeakGuard lock{*this}; return RCSRepresentation{ m_uri, m_interfaces, m_types, m_resourceAttributes }; - } + } void RCSResourceObject::autoNotify(bool isAttributesChanged) const { @@ -603,47 +606,57 @@ namespace OIC { assert(request != nullptr); + RCSRequest rcsRequest{ shared_from_this(), request }; + + if (rcsRequest.getInterface() != "" && m_interfaceHandlers.find( + rcsRequest.getInterface()) == m_interfaceHandlers.end()) + { + return OC_EH_ERROR; + } + if (request->getRequestType() == "GET") { - return handleRequestGet(request); + return handleRequestGet(rcsRequest); } if (request->getRequestType() == "POST") { - return handleRequestSet(request); + return handleRequestSet(rcsRequest); } return OC_EH_ERROR; } OCEntityHandlerResult RCSResourceObject::handleRequestGet( - const std::shared_ptr< OC::OCResourceRequest >& request) + const RCSRequest& request) { - assert(request != nullptr); - - if (requestContainsInterface(request, OC::BATCH_INTERFACE)) + if (!findInterfaceHandler(request.getInterface()).isGetSupported()) { - return handleBatchInterfaceGetRequest(request, this); + return OC_EH_ERROR; } - auto attrs = getAttributesFromOCRequest(request); + auto attrs = getAttributesFromOCRequest(request.getOCRequest()); - auto response = invokeHandler(shared_from_this(), attrs, request, m_getRequestHandler); + auto response = invokeHandler(shared_from_this(), attrs, request.getOCRequest(), + m_getRequestHandler); if (response.isSeparate()) return OC_EH_SLOW; - return sendResponse(*this, request, response); + return sendResponse(request, response, + findInterfaceHandler(request.getInterface()).getGetResponseBuilder()); } - bool RCSResourceObject::applyAcceptanceMethod(const RCSSetResponse& response, - const RCSResourceAttributes& requstAttrs) + RCSResourceAttributes RCSResourceObject::applyAcceptanceMethod( + const RCSSetResponse& response, const RCSResourceAttributes& requestAttrs) { auto requestHandler = response.getHandler(); assert(requestHandler != nullptr); + RCSResourceAttributes result; + auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(), - *this, requstAttrs); + *this, requestAttrs); OIC_LOG_V(WARNING, LOG_TAG, "replaced num %zu", replaced.size()); for (const auto& attrKeyValPair : replaced) @@ -661,33 +674,36 @@ namespace OIC if (foundListener) { - (*foundListener)(attrKeyValPair.second, requstAttrs.at(attrKeyValPair.first)); + (*foundListener)(attrKeyValPair.second, requestAttrs.at(attrKeyValPair.first)); } + + result[attrKeyValPair.first] = attrKeyValPair.second; } - return !replaced.empty(); + return result; } OCEntityHandlerResult RCSResourceObject::handleRequestSet( - const std::shared_ptr< OC::OCResourceRequest >& request) + const RCSRequest& request) { - assert(request != nullptr); + if (!findInterfaceHandler(request.getInterface()).isSetSupported()) + { + return OC_EH_ERROR; + } + + auto attrs = getAttributesFromOCRequest(request.getOCRequest()); - auto attrs = getAttributesFromOCRequest(request); - auto response = invokeHandler(shared_from_this(), attrs, request, m_setRequestHandler); + auto response = invokeHandler(shared_from_this(), attrs, request.getOCRequest(), + m_setRequestHandler); if (response.isSeparate()) return OC_EH_SLOW; - auto attrsChanged = applyAcceptanceMethod(response, attrs); + auto replaced = applyAcceptanceMethod(response, attrs); - try - { - autoNotify(attrsChanged, m_autoNotifyPolicy); - return sendResponse(*this, request, response); - } catch (const RCSPlatformException& e) { - OIC_LOG_V(ERROR, LOG_TAG, "Error : %s ", e.what()); - return OC_EH_ERROR; - } + autoNotify(!replaced.empty(), m_autoNotifyPolicy); + + return sendResponse(request, response, + findInterfaceHandler(request.getInterface()).getSetResponseBuilder()); } OCEntityHandlerResult RCSResourceObject::handleObserve( @@ -701,6 +717,44 @@ namespace OIC return OC_EH_OK; } + InterfaceHandler RCSResourceObject::findInterfaceHandler( + const std::string& interfaceName) const + { + auto it = m_interfaceHandlers.find(interfaceName); + + if (it != m_interfaceHandlers.end()) return it->second; + + assert(m_interfaceHandlers.find(m_defaultInterface) != m_interfaceHandlers.end()); + + return m_interfaceHandlers.find(m_defaultInterface)->second; + } + + template + OCEntityHandlerResult RCSResourceObject::sendResponse( + const RCSRequest& request, const RESPONSE& response, + const RESPONSE_BUILDER& resBuilder) + { + auto reqHandler = response.getHandler(); + auto ocResponse = std::make_shared< OC::OCResourceResponse >(); + + ocResponse->setResponseResult(OC_EH_OK); + ocResponse->setErrorCode(reqHandler->getErrorCode()); + + if (reqHandler->hasCustomRepresentation()) + { + ocResponse->setResourceRepresentation(reqHandler->getRepresentation()); + } + else + { + ocResponse->setResourceRepresentation( + RCSRepresentation::toOCRepresentation( + resBuilder(request, *this))); + } + + return ::sendResponse(request.getOCRequest(), ocResponse); + } + + RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) : m_resourceObject(*ptr), m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() }, diff --git a/service/resource-encapsulation/src/serverBuilder/src/RequestHandler.cpp b/service/resource-encapsulation/src/serverBuilder/src/RequestHandler.cpp index f1facbc..e7e41a2 100644 --- a/service/resource-encapsulation/src/serverBuilder/src/RequestHandler.cpp +++ b/service/resource-encapsulation/src/serverBuilder/src/RequestHandler.cpp @@ -31,37 +31,6 @@ namespace { using namespace OIC::Service; - typedef std::function< OC::OCRepresentation(RCSResourceObject&) > OCRepresentationGetter; - - OC::OCRepresentation getOCRepresentationFromResource(RCSResourceObject& resource) - { - RCSResourceObject::LockGuard lock{ resource, RCSResourceObject::AutoNotifyPolicy::NEVER }; - return ResourceAttributesConverter::toOCRepresentation(resource.getAttributes()); - } - - OC::OCRepresentation getOCRepresentation(const RCSResourceAttributes& attrs) - { - return ResourceAttributesConverter::toOCRepresentation(attrs); - } - - template< typename T > - OCRepresentationGetter wrapGetOCRepresentation(T&& attrs) - { - return std::bind(getOCRepresentation, std::forward(attrs)); - } - - std::shared_ptr< OC::OCResourceResponse > doBuildResponse(RCSResourceObject& resource, - int errorCode, OCRepresentationGetter ocRepGetter) - { - auto response = std::make_shared< OC::OCResourceResponse >(); - - response->setResponseResult(OC_EH_OK); - response->setErrorCode(errorCode); - response->setResourceRepresentation(ocRepGetter(resource)); - - return response; - } - AttrKeyValuePairs applyAcceptMethod(RCSResourceObject& resource, const RCSResourceAttributes& requestAttrs) { @@ -117,35 +86,46 @@ namespace OIC constexpr int RequestHandler::DEFAULT_ERROR_CODE; RequestHandler::RequestHandler() : - m_holder{ std::bind(doBuildResponse, std::placeholders::_1, DEFAULT_ERROR_CODE, - getOCRepresentationFromResource) } + m_errorCode{ DEFAULT_ERROR_CODE }, + m_repBuilder{ } { } RequestHandler::RequestHandler(int errorCode) : - m_holder{ std::bind(doBuildResponse, std::placeholders::_1, errorCode, - getOCRepresentationFromResource) } + m_errorCode{ errorCode }, + m_repBuilder{ } + { } RequestHandler::RequestHandler(const RCSResourceAttributes& attrs, int errorCode) : - m_holder{ std::bind(doBuildResponse, std::placeholders::_1, errorCode, - wrapGetOCRepresentation(attrs)) } + m_errorCode{ errorCode }, + m_repBuilder{ std::bind(ResourceAttributesConverter::toOCRepresentation, attrs) } { } RequestHandler::RequestHandler(RCSResourceAttributes&& attrs, int errorCode) : - m_holder{ std::bind(doBuildResponse, std::placeholders::_1, errorCode, - wrapGetOCRepresentation(std::move(attrs))) } + m_errorCode{ errorCode }, + m_repBuilder{ std::bind(ResourceAttributesConverter::toOCRepresentation, + std::move(attrs)) } { } - std::shared_ptr< OC::OCResourceResponse > RequestHandler::buildResponse( - RCSResourceObject& resource) + int RequestHandler::getErrorCode() const { - return m_holder(resource); + return m_errorCode; } + bool RequestHandler::hasCustomRepresentation() const + { + return m_repBuilder != nullptr; + } + + OC::OCRepresentation RequestHandler::getRepresentation() const + { + assert(m_repBuilder); + return m_repBuilder(); + } SetRequestHandler::SetRequestHandler() : RequestHandler{ } diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp index d76184e..4f55d4a 100644 --- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp +++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp @@ -35,151 +35,25 @@ using namespace std; using namespace OIC::Service; using namespace OC; -typedef OCStackResult (*registerResourceSig)(OCResourceHandle&, - string&, - const string&, - const string&, - EntityHandler, - uint8_t ); - -static constexpr char KEY[] = "key"; - - -void EXPECT_RESPONSE(shared_ptr< OCResourceResponse > ocResponse, int errorCode, - const RCSResourceAttributes& attrs) -{ - EXPECT_EQ(ocResponse->getErrorCode(), errorCode); - EXPECT_EQ(ResourceAttributesConverter::fromOCRepresentation( - ocResponse->getResourceRepresentation()), attrs); -} - - -class RCSResponseTest: public TestWithMock -{ -public: - template< typename T > - shared_ptr< OCResourceResponse > buildResponse(const T& response) - { - RCSResourceObject::Ptr server = - RCSResourceObject::Builder("a/test", "", "").build(); - - return response.getHandler()->buildResponse(*server); - } - -protected: - void SetUp() - { - TestWithMock::SetUp(); - - mocks.OnCallFuncOverload(static_cast< registerResourceSig >(OCPlatform::registerResource)) - .Return(OC_STACK_OK); - - mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK); - } -}; - -TEST_F(RCSResponseTest, GetDefaultActionHasEmptyAttrs) -{ - EXPECT_RESPONSE(buildResponse(RCSGetResponse::defaultAction()), - RequestHandler::DEFAULT_ERROR_CODE, RCSResourceAttributes()); -} - -TEST_F(RCSResponseTest, GetResponseHasResultsPassedCodes) -{ - constexpr int errorCode{ -10 }; - - EXPECT_RESPONSE(buildResponse(RCSGetResponse::create(errorCode)), - errorCode, RCSResourceAttributes()); -} - -TEST_F(RCSResponseTest, GetResponseHasAttrsAndResultsPassedCodes) -{ - constexpr int errorCode{ -10 }; - - RCSResourceAttributes attrs; - attrs[KEY] = 100; - - EXPECT_RESPONSE(buildResponse(RCSGetResponse::create(attrs, errorCode)), errorCode, attrs); -} - -TEST_F(RCSResponseTest, GetResponseCanMoveAttrs) -{ - constexpr int errorCode{ -10 }; - - RCSResourceAttributes attrs; - attrs[KEY] = 100; - - RCSResourceAttributes attrsClone; - attrsClone[KEY] = 100; - - EXPECT_RESPONSE( - buildResponse(RCSGetResponse::create(std::move(attrs), errorCode)), - errorCode, attrsClone); - - EXPECT_TRUE(attrs.empty()); -} - -TEST_F(RCSResponseTest, SetDefaultActionHasEmptyAttrs) -{ - EXPECT_RESPONSE(buildResponse(RCSSetResponse::defaultAction()), - RequestHandler::DEFAULT_ERROR_CODE, RCSResourceAttributes()); -} - -TEST_F(RCSResponseTest, SetResponseHasResultsPassedCodes) -{ - constexpr int errorCode{ -10 }; - - EXPECT_RESPONSE(buildResponse(RCSSetResponse::create(errorCode)), - errorCode, RCSResourceAttributes()); -} - -TEST_F(RCSResponseTest, SetResponseHasAttrsAndResultsPassedCodes) -{ - constexpr int errorCode{ -10 }; - - RCSResourceAttributes attrs; - attrs[KEY] = 100; - - EXPECT_RESPONSE(buildResponse(RCSSetResponse::create(attrs, errorCode)), - errorCode, attrs); -} - -TEST_F(RCSResponseTest, SetResponseCanMoveAttrs) -{ - constexpr int errorCode{ -10 }; - - RCSResourceAttributes attrs; - attrs[KEY] = 100; - - RCSResourceAttributes attrsClone; - attrsClone[KEY] = 100; - - EXPECT_RESPONSE(buildResponse(RCSSetResponse::create(std::move(attrs), errorCode)), - errorCode, attrsClone); - - EXPECT_TRUE(attrs.empty()); -} - - -TEST_F(RCSResponseTest, DefaultSetResponseHasDefaultMethod) +TEST(RCSResponseTest, DefaultSetResponseHasDefaultMethod) { EXPECT_EQ(RCSSetResponse::AcceptanceMethod::DEFAULT, RCSSetResponse::defaultAction().getAcceptanceMethod()); } -TEST_F(RCSResponseTest, AcceptSetResponseHasAcceptMethod) +TEST(RCSResponseTest, AcceptSetResponseHasAcceptMethod) { EXPECT_EQ(RCSSetResponse::AcceptanceMethod::ACCEPT, RCSSetResponse::accept().getAcceptanceMethod()); } -TEST_F(RCSResponseTest, IgnoreSetResponseHasIgnoreMethod) +TEST(RCSResponseTest, IgnoreSetResponseHasIgnoreMethod) { EXPECT_EQ(RCSSetResponse::AcceptanceMethod::IGNORE, RCSSetResponse::ignore().getAcceptanceMethod()); } -TEST_F(RCSResponseTest, SetResponseHasMethodSetBySetter) +TEST(RCSResponseTest, SetResponseHasMethodSetBySetter) { RCSSetResponse::AcceptanceMethod method = RCSSetResponse::AcceptanceMethod::ACCEPT; RCSSetResponse response = @@ -188,13 +62,13 @@ TEST_F(RCSResponseTest, SetResponseHasMethodSetBySetter) EXPECT_EQ(method, response.getAcceptanceMethod()); } -TEST_F(RCSResponseTest, SeparateResponseHasNoHandler) +TEST(RCSResponseTest, SeparateResponseHasNoHandler) { RCSGetResponse response = RCSGetResponse::separate(); EXPECT_EQ(nullptr, response.getHandler()); } -TEST_F(RCSResponseTest, ThrowIfRequestIsInvalidWhenConstructingSeparateResponse) +TEST(RCSResponseTest, ThrowIfRequestIsInvalidWhenConstructingSeparateResponse) { RCSRequest aRequest; diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RequestHandlerTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RequestHandlerTest.cpp index 7eba605..d675634 100644 --- a/service/resource-encapsulation/src/serverBuilder/unittests/RequestHandlerTest.cpp +++ b/service/resource-encapsulation/src/serverBuilder/unittests/RequestHandlerTest.cpp @@ -37,6 +37,7 @@ constexpr int NEW_VALUE{ 1 }; typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&, const std::string&, const std::string&, OC::EntityHandler, uint8_t); + class RequestHandlerTest: public TestWithMock { public: @@ -59,40 +60,6 @@ protected: } }; -TEST_F(RequestHandlerTest, ResponseHasSameValuesPassedToHandlerConstructor) -{ - RequestHandler handler{ -1000 }; - - auto response = handler.buildResponse(*server); - - ASSERT_EQ(-1000, response->getErrorCode()); -} - -TEST_F(RequestHandlerTest, ResponseHasSameAttrsWithServerAttrs) -{ - RequestHandler handler{}; - - auto response = handler.buildResponse(*server); - - ASSERT_EQ(ORIGIN_VALUE, response->getResourceRepresentation()[EXISTING].getValue()); -} - -TEST_F(RequestHandlerTest, ResponseHasAttrsSetByCustomAttrRequestHandler) -{ - constexpr char key[] { "key" }; - constexpr int newValue{ 100 }; - - RCSResourceAttributes attrs; - attrs[key] = newValue; - RequestHandler handler{ attrs }; - - auto response = handler.buildResponse(*server); - - ASSERT_EQ(ORIGIN_VALUE, response->getResourceRepresentation()[key].getValue()); -} - - - class SetRequestHandlerAcceptanceTest: public RequestHandlerTest { public: -- 2.7.4