From: coderhyme Date: Sat, 4 Jul 2015 03:48:25 +0000 (+0900) Subject: Refactor PrimitiveResponse and RequestHandler X-Git-Tag: 1.2.0+RC1~1430^2~76 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=541193b562712c961ddeadedd9ffe54138bc132a;p=platform%2Fupstream%2Fiotivity.git Refactor PrimitiveResponse and RequestHandler Now PrimitiveSetResponse has AcceptanceMethod that indicates how to handle ResourceAttributes from request. Belows are AcceptanceMehtod of PrimitiveSetResponse Default : Follow handling policy of ResourceObject which will be implemented soon. Ignore : Always ignore request attributes. Accept : Always accept request attribuets, even if there is unknown value or different type with ResourceObject's attribute. Change-Id: Ie67b9f8eeb6c56deace57a16e1535b9926fe3a5c Signed-off-by: coderhyme Reviewed-on: https://gerrit.iotivity.org/gerrit/1517 Tested-by: jenkins-iotivity Reviewed-by: Madan Lanka Reviewed-by: Uze Choi --- diff --git a/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h b/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h index 77819d1..35219fb 100755 --- a/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h +++ b/service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h @@ -118,6 +118,8 @@ namespace OIC { } + Value(const char* value); + Value& operator=(const Value&); Value& operator=(Value&&); diff --git a/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h b/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h index a61cd00..8672373 100644 --- a/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h +++ b/service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h @@ -21,19 +21,22 @@ #ifndef COMMON_INTERNAL_RESOURCEATTRIBUTESUTILS_H #define COMMON_INTERNAL_RESOURCEATTRIBUTESUTILS_H +#include +#include + namespace OIC { namespace Service { + using AttrKeyValuePair = std::pair< std::string, ResourceAttributes::Value >; + using AttrKeyValuePairs = std::vector< AttrKeyValuePair >; + bool acceptableAttributes(const ResourceAttributes& dest, const ResourceAttributes& attr); bool acceptableAttributeValue(const ResourceAttributes::Value& dest, const ResourceAttributes::Value& value); - void replaceAttributesRecursively(ResourceAttributes& dest, const ResourceAttributes& attr); - - void replaceAttributeValueRecursively(ResourceAttributes::Value& dest, - const ResourceAttributes::Value& value); + AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest, const ResourceAttributes& attrs); } } diff --git a/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp b/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp index c065101..95d1746 100755 --- a/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp +++ b/service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp @@ -120,6 +120,10 @@ namespace OIC m_data->swap(*from.m_data); } + ResourceAttributes::Value::Value(const char* value) : + m_data{ new ValueVariant{ std::string{ value } } } + { + } auto ResourceAttributes::Value::operator=(const Value& rhs) -> Value& { @@ -438,29 +442,24 @@ namespace OIC return true; } - void replaceAttributeValueRecursively(ResourceAttributes::Value& dest, - const ResourceAttributes::Value& value) + AttrKeyValuePairs replaceAttributes(ResourceAttributes& dest, + const ResourceAttributes& newAttrs) { - static_assert(ResourceAttributes::is_supported_type< ResourceAttributes >::value, - "ResourceAttributes doesn't have ResourceAttributes recursively."); + AttrKeyValuePairs replacedList; - if (dest.isTypeOf< ResourceAttributes >()) - { - replaceAttributesRecursively(dest.get< ResourceAttributes >(), - value.get< ResourceAttributes >()); - } - else + for (const auto& kv : newAttrs) { - dest = value; - } - } + if (dest[kv.key()] != kv.value()) + { + ResourceAttributes::Value replacedValue; + replacedValue.swap(dest[kv.key()]); + dest[kv.key()] = kv.value(); - void replaceAttributesRecursively(ResourceAttributes& dest, const ResourceAttributes& attr) - { - for (const auto& kv : attr) - { - replaceAttributeValueRecursively(dest[kv.key()], kv.value()); + replacedList.push_back(AttrKeyValuePair{ kv.key(), std::move(replacedValue) }); + } } + + return replacedList; } } } diff --git a/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp b/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp index 00fff7d..3066a5f 100644 --- a/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp +++ b/service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp @@ -258,6 +258,20 @@ TEST(ResourceAttributesValueTest, DifferentValuesAreNotEqual) ASSERT_NE(one, another); } +TEST(ResourceAttributesValueTest, ValuesCanBeSwapped) +{ + constexpr int i { 1 }; + constexpr char str[]{ "abc" }; + + ResourceAttributes::Value intValue { i }; + ResourceAttributes::Value strValue { str }; + + intValue.swap(strValue); + + ASSERT_EQ(str, intValue); + ASSERT_EQ(i, strValue); +} + TEST(ResourceAttributesConverterTest, OCRepresentationCanBeConvertedIntoResourceAttributes) { constexpr double value = 9876; @@ -393,7 +407,7 @@ TEST_F(ResourceAttributesUtilTest, ReplaceWillOverwriteOriginal) ResourceAttributes newAttrs; newAttrs[KEY] = NEW_VALUE; - replaceAttributesRecursively(resourceAttributes, newAttrs); + replaceAttributes(resourceAttributes, newAttrs); ASSERT_EQ(NEW_VALUE, resourceAttributes[KEY]); } diff --git a/service/resource-manipulation/modules/serverBuilder/include/PrimitiveResponse.h b/service/resource-manipulation/modules/serverBuilder/include/PrimitiveResponse.h index 717a873..3ec2967 100644 --- a/service/resource-manipulation/modules/serverBuilder/include/PrimitiveResponse.h +++ b/service/resource-manipulation/modules/serverBuilder/include/PrimitiveResponse.h @@ -33,6 +33,7 @@ namespace OIC class ResourceAttributes; class RequestHandler; + class SetRequestHandler; class PrimitiveGetResponse { @@ -61,8 +62,21 @@ namespace OIC class PrimitiveSetResponse { public: + enum class AcceptanceMethod + { + DEFAULT, + ACCEPT, + IGNORE + }; + static PrimitiveSetResponse defaultAction(); + static PrimitiveSetResponse accept(); + static PrimitiveSetResponse accept(const OCEntityHandlerResult&, int errorCode); + + static PrimitiveSetResponse ignore(); + static PrimitiveSetResponse ignore(const OCEntityHandlerResult&, int errorCode); + static PrimitiveSetResponse create(const OCEntityHandlerResult&, int errorCode); static PrimitiveSetResponse create(const ResourceAttributes&); @@ -73,15 +87,19 @@ namespace OIC static PrimitiveSetResponse create(ResourceAttributes&&, const OCEntityHandlerResult&, int errorCode); - RequestHandler* getHandler() const; + SetRequestHandler* getHandler() const; - private: - PrimitiveSetResponse(std::shared_ptr< RequestHandler >&&); + AcceptanceMethod getAcceptanceMethod() const; - static PrimitiveSetResponse withProxy(std::shared_ptr< RequestHandler >&&); + PrimitiveSetResponse& setAcceptanceMethod(AcceptanceMethod); private: - std::shared_ptr< RequestHandler > m_handler; + PrimitiveSetResponse(std::shared_ptr< SetRequestHandler >&&); + PrimitiveSetResponse(std::shared_ptr< SetRequestHandler >&&, AcceptanceMethod); + + private: + AcceptanceMethod m_acceptanceMethod; + std::shared_ptr< SetRequestHandler > m_handler; }; } } diff --git a/service/resource-manipulation/modules/serverBuilder/include/internal/RequestHandler.h b/service/resource-manipulation/modules/serverBuilder/include/internal/RequestHandler.h index b7f97cc..d27723a 100644 --- a/service/resource-manipulation/modules/serverBuilder/include/internal/RequestHandler.h +++ b/service/resource-manipulation/modules/serverBuilder/include/internal/RequestHandler.h @@ -22,8 +22,15 @@ #define __REQUESTHANDLER_H #include +#include -#include +#include + +namespace OC +{ + class OCResourceResponse; + class OCRepresentation; +} namespace OIC { @@ -31,70 +38,64 @@ namespace OIC { class RequestHandler { + private: + using BuildResponseHolder = std::function< std::shared_ptr< OC::OCResourceResponse >( + ResourceObject&) >; + public: using Ptr = std::shared_ptr< RequestHandler >; static constexpr int DEFAULT_ERROR_CODE = 200; static constexpr OCEntityHandlerResult DEFAULT_RESULT = OC_EH_OK; - virtual ~RequestHandler() - { - } + RequestHandler(); - virtual std::shared_ptr< OC::OCResourceResponse > buildResponse( - ResourceObject&, const ResourceAttributes& requestAttrs) = 0; - }; + RequestHandler(const RequestHandler&) = delete; + RequestHandler(RequestHandler&&) = default; - class SimpleRequestHandler: public RequestHandler - { - public: - SimpleRequestHandler(const OCEntityHandlerResult& result = DEFAULT_RESULT, + RequestHandler(const OCEntityHandlerResult& result, int errorCode); + + RequestHandler(const ResourceAttributes&, + const OCEntityHandlerResult& result = DEFAULT_RESULT, int errorCode = DEFAULT_ERROR_CODE); - std::shared_ptr< OC::OCResourceResponse > buildResponse( - ResourceObject&, const ResourceAttributes&) override; + RequestHandler(ResourceAttributes&&, + const OCEntityHandlerResult& result = DEFAULT_RESULT, + int errorCode = DEFAULT_ERROR_CODE); + + + virtual ~RequestHandler() = default; - protected: - virtual int getErrorCode(ResourceObject&); - virtual OCEntityHandlerResult getResponseResult(ResourceObject&); - virtual OC::OCRepresentation getOCRepresentation(ResourceObject& resource); + std::shared_ptr< OC::OCResourceResponse > buildResponse(ResourceObject&); private: - OCEntityHandlerResult m_result; - int m_errorCode; + const BuildResponseHolder m_holder; }; - - class CustomAttrRequestHandler: public SimpleRequestHandler + class SetRequestHandler: public RequestHandler { public: - template - CustomAttrRequestHandler(T&& attrs, - const OCEntityHandlerResult& result = DEFAULT_RESULT, - int errorCode = DEFAULT_ERROR_CODE) : - SimpleRequestHandler{ result, errorCode }, m_attrs{ std::forward< T >(attrs) } - { - } + using Ptr = std::shared_ptr< SetRequestHandler >; - protected: - OC::OCRepresentation getOCRepresentation(ResourceObject& resource) override; + SetRequestHandler(const SetRequestHandler&) = delete; + SetRequestHandler(SetRequestHandler&&) = default; - private: - ResourceAttributes m_attrs; - }; + SetRequestHandler(); - class SetRequestProxyHandler: public RequestHandler - { - public: - SetRequestProxyHandler(RequestHandler::Ptr requestHandler); + SetRequestHandler(const OCEntityHandlerResult& result, int errorCode); - std::shared_ptr< OC::OCResourceResponse > buildResponse( - ResourceObject& resource, - const ResourceAttributes& requestAttrs) override; + SetRequestHandler(const ResourceAttributes&, + const OCEntityHandlerResult& result = DEFAULT_RESULT, + int errorCode = DEFAULT_ERROR_CODE); - private: - RequestHandler::Ptr m_requestHandler; + SetRequestHandler(ResourceAttributes&&, + const OCEntityHandlerResult& result = DEFAULT_RESULT, + int errorCode = DEFAULT_ERROR_CODE); + + AttrKeyValuePairs applyAcceptanceMethod(PrimitiveSetResponse::AcceptanceMethod, + ResourceObject&, const ResourceAttributes&) const; }; + } } diff --git a/service/resource-manipulation/modules/serverBuilder/src/PrimitiveResponse.cpp b/service/resource-manipulation/modules/serverBuilder/src/PrimitiveResponse.cpp index 5bcc5f9..94eb85f 100644 --- a/service/resource-manipulation/modules/serverBuilder/src/PrimitiveResponse.cpp +++ b/service/resource-manipulation/modules/serverBuilder/src/PrimitiveResponse.cpp @@ -28,7 +28,7 @@ namespace OIC { PrimitiveGetResponse PrimitiveGetResponse::defaultAction() { - static PrimitiveGetResponse defaultRes { std::make_shared() }; + static PrimitiveGetResponse defaultRes { std::make_shared< RequestHandler >() }; return defaultRes; } @@ -37,31 +37,31 @@ namespace OIC int errorCode) { return PrimitiveGetResponse { - std::make_shared( result, errorCode) }; + std::make_shared< RequestHandler >( result, errorCode) }; } PrimitiveGetResponse PrimitiveGetResponse::create(const ResourceAttributes& attrs) { - return PrimitiveGetResponse { std::make_shared(attrs) }; + return PrimitiveGetResponse { std::make_shared< RequestHandler >(attrs) }; } PrimitiveGetResponse PrimitiveGetResponse::create(const ResourceAttributes& attrs, const OCEntityHandlerResult& result, int errorCode) { return PrimitiveGetResponse { - std::make_shared(attrs, result, errorCode) }; + std::make_shared< RequestHandler >(attrs, result, errorCode) }; } PrimitiveGetResponse PrimitiveGetResponse::create(ResourceAttributes&& result) { return PrimitiveGetResponse { - std::make_shared(std::move(result)) }; + std::make_shared< RequestHandler >(std::move(result)) }; } PrimitiveGetResponse PrimitiveGetResponse::create(ResourceAttributes&& attrs, const OCEntityHandlerResult& result, int errorCode) { - return PrimitiveGetResponse { std::make_shared( + return PrimitiveGetResponse { std::make_shared< RequestHandler >( std::move(attrs), result, errorCode) }; } @@ -79,59 +79,86 @@ namespace OIC PrimitiveSetResponse PrimitiveSetResponse::defaultAction() { - static PrimitiveSetResponse defaultRes { - withProxy(std::make_shared()) }; + return std::make_shared< SetRequestHandler >(); + } - return defaultRes; + PrimitiveSetResponse PrimitiveSetResponse::accept() + { + return defaultAction().setAcceptanceMethod(AcceptanceMethod::ACCEPT); + } + + PrimitiveSetResponse PrimitiveSetResponse::accept(const OCEntityHandlerResult& result, + int errorCode) + { + return create(result, errorCode).setAcceptanceMethod(AcceptanceMethod::ACCEPT); + } + + PrimitiveSetResponse PrimitiveSetResponse::ignore() + { + return defaultAction().setAcceptanceMethod(AcceptanceMethod::IGNORE); + } + + PrimitiveSetResponse PrimitiveSetResponse::ignore(const OCEntityHandlerResult& result, + int errorCode) + { + return create(result, errorCode).setAcceptanceMethod(AcceptanceMethod::IGNORE); } PrimitiveSetResponse PrimitiveSetResponse::create(const OCEntityHandlerResult& result, int errorCode) { - return withProxy(std::make_shared(result, errorCode)); + return std::make_shared< SetRequestHandler >(result, errorCode); } PrimitiveSetResponse PrimitiveSetResponse::create(const ResourceAttributes& attrs) { - return withProxy(std::make_shared(attrs)); + return std::make_shared< SetRequestHandler >(attrs); } PrimitiveSetResponse PrimitiveSetResponse::create(const ResourceAttributes& attrs, const OCEntityHandlerResult& result, int errorCode) { - return withProxy(std::make_shared(attrs, result, errorCode)); + return std::make_shared< SetRequestHandler >(attrs, result, errorCode); } PrimitiveSetResponse PrimitiveSetResponse::create(ResourceAttributes&& result) { - return withProxy(std::make_shared(std::move(result))); + return std::make_shared< SetRequestHandler >(std::move(result)); } PrimitiveSetResponse PrimitiveSetResponse::create(ResourceAttributes&& attrs, const OCEntityHandlerResult& result, int errorCode) { - return withProxy( - std::make_shared(std::move(attrs), result, errorCode)); + return std::make_shared< SetRequestHandler >(std::move(attrs), result, errorCode); } - PrimitiveSetResponse::PrimitiveSetResponse(std::shared_ptr< RequestHandler >&& handler) : - m_handler{ handler } + PrimitiveSetResponse::PrimitiveSetResponse(std::shared_ptr< SetRequestHandler >&& handler) : + PrimitiveSetResponse{ std::move(handler), AcceptanceMethod::DEFAULT } + { + } + + PrimitiveSetResponse::PrimitiveSetResponse(std::shared_ptr< SetRequestHandler >&& handler, + AcceptanceMethod method) : + m_acceptanceMethod{ method }, + m_handler{ std::move(handler) } { assert(m_handler); } - PrimitiveSetResponse PrimitiveSetResponse::withProxy( - std::shared_ptr< RequestHandler >&& handler) + SetRequestHandler* PrimitiveSetResponse::getHandler() const { - assert(handler); + return m_handler.get(); + } - return PrimitiveSetResponse{ - std::make_shared(std::move(handler)) }; + auto PrimitiveSetResponse::getAcceptanceMethod() const -> AcceptanceMethod + { + return m_acceptanceMethod; } - RequestHandler* PrimitiveSetResponse::getHandler() const + PrimitiveSetResponse& PrimitiveSetResponse::setAcceptanceMethod(AcceptanceMethod method) { - return m_handler.get(); + m_acceptanceMethod = method; + return *this; } } } diff --git a/service/resource-manipulation/modules/serverBuilder/src/RequestHandler.cpp b/service/resource-manipulation/modules/serverBuilder/src/RequestHandler.cpp index 0bd8848..6d4e205 100644 --- a/service/resource-manipulation/modules/serverBuilder/src/RequestHandler.cpp +++ b/service/resource-manipulation/modules/serverBuilder/src/RequestHandler.cpp @@ -21,78 +21,155 @@ #include #include -#include -namespace OIC +#include + +namespace { - namespace Service + using namespace OIC::Service; + + using OCRepresentationGetter = std::function< OC::OCRepresentation(ResourceObject&) >; + + OC::OCRepresentation getOCRepresentationFromResource(ResourceObject& resource) { + ResourceObject::LockGuard lock{ resource }; + return ResourceAttributesConverter::toOCRepresentation(resource.getAttributes()); + } - constexpr OCEntityHandlerResult RequestHandler::DEFAULT_RESULT; + OC::OCRepresentation getOCRepresentation(const ResourceAttributes& attrs) + { + return ResourceAttributesConverter::toOCRepresentation(attrs); + } + + template< typename T > + OCRepresentationGetter wrapGetOCRepresentation(T&& attrs) + { + return std::bind(getOCRepresentation, std::forward(attrs)); + } - SimpleRequestHandler::SimpleRequestHandler(const OCEntityHandlerResult& result, - int errorCode) : - m_result{ result }, m_errorCode{ errorCode } + std::shared_ptr< OC::OCResourceResponse > doBuildResponse(ResourceObject& resource, + const OCEntityHandlerResult result, int errorCode, OCRepresentationGetter ocRepGetter) + { + auto response = std::make_shared< OC::OCResourceResponse >(); + + response->setResponseResult(result); + response->setErrorCode(errorCode); + response->setResourceRepresentation(ocRepGetter(resource)); + + return response; + } + + AttrKeyValuePairs applyAcceptMethod(ResourceObject& resource, const ResourceAttributes& requestAttrs) + { + ResourceObject::LockGuard lock(resource); + + return replaceAttributes(resource.getAttributes(), requestAttrs); + } + + AttrKeyValuePairs applyDefaultMethod(ResourceObject& resource, const ResourceAttributes& requestAttrs) + { + ResourceObject::LockGuard lock(resource); + + if (!acceptableAttributes(resource.getAttributes(), requestAttrs)) { + return AttrKeyValuePairs{ }; } - std::shared_ptr< OC::OCResourceResponse > SimpleRequestHandler::buildResponse( - ResourceObject& resource, const ResourceAttributes&) + return replaceAttributes(resource.getAttributes(), requestAttrs); + } + + AttrKeyValuePairs applyIgnoreMethod(ResourceObject&, const ResourceAttributes&) + { + return AttrKeyValuePairs(); + } + + std::function getApplyAcceptanceFunc( + PrimitiveSetResponse::AcceptanceMethod method) + { + switch (method) { - auto response = std::make_shared< OC::OCResourceResponse >(); + case PrimitiveSetResponse::AcceptanceMethod::DEFAULT: + return applyDefaultMethod; - response->setErrorCode(getErrorCode(resource)); - response->setResponseResult(getResponseResult(resource)); - response->setResourceRepresentation(getOCRepresentation(resource)); + case PrimitiveSetResponse::AcceptanceMethod::ACCEPT: + return applyAcceptMethod; - return response; + case PrimitiveSetResponse::AcceptanceMethod::IGNORE: + return applyIgnoreMethod; } - int SimpleRequestHandler::getErrorCode(ResourceObject&) + return applyIgnoreMethod; + } + +} // unnamed namespace + +namespace OIC +{ + namespace Service + { + constexpr int RequestHandler::DEFAULT_ERROR_CODE; + constexpr OCEntityHandlerResult RequestHandler::DEFAULT_RESULT; + + RequestHandler::RequestHandler() : + RequestHandler { DEFAULT_RESULT, DEFAULT_ERROR_CODE } { - return m_errorCode; } - OCEntityHandlerResult SimpleRequestHandler::getResponseResult(ResourceObject&) + RequestHandler::RequestHandler(const OCEntityHandlerResult& result, int errorCode) : + m_holder{ std::bind(doBuildResponse, std::placeholders::_1, result, errorCode, + getOCRepresentationFromResource) } { - return m_result; } - OC::OCRepresentation SimpleRequestHandler::getOCRepresentation( - ResourceObject& resource) + RequestHandler::RequestHandler(const ResourceAttributes& attrs, + const OCEntityHandlerResult& result, int errorCode) : + m_holder{ std::bind(doBuildResponse, std::placeholders::_1, result, errorCode, + wrapGetOCRepresentation(attrs)) } { - ResourceObject::LockGuard lock{ resource }; - return ResourceAttributesConverter::toOCRepresentation(resource.getAttributes()); } + RequestHandler::RequestHandler(ResourceAttributes&& attrs, + const OCEntityHandlerResult& result, int errorCode) : + m_holder{ std::bind(doBuildResponse, std::placeholders::_1, result, errorCode, + wrapGetOCRepresentation(std::move(attrs))) } + { + } - OC::OCRepresentation CustomAttrRequestHandler::getOCRepresentation( + std::shared_ptr< OC::OCResourceResponse > RequestHandler::buildResponse( ResourceObject& resource) { - return ResourceAttributesConverter::toOCRepresentation(m_attrs); + return m_holder(resource); } - SetRequestProxyHandler::SetRequestProxyHandler(RequestHandler::Ptr requestHandler) : - m_requestHandler{ requestHandler } + SetRequestHandler::SetRequestHandler() : + RequestHandler{ } + { + } + + SetRequestHandler::SetRequestHandler(const OCEntityHandlerResult& result, int errorCode) : + RequestHandler{ result, errorCode } { - assert(m_requestHandler); } - std::shared_ptr< OC::OCResourceResponse > SetRequestProxyHandler::buildResponse( - ResourceObject& resource, const ResourceAttributes& requestAttrs) + + SetRequestHandler::SetRequestHandler(const ResourceAttributes& attrs, + const OCEntityHandlerResult& result, int errorCode) : + RequestHandler{ attrs, result, errorCode } { - { - ResourceObject::LockGuard lock(resource); + } - if (!acceptableAttributes(resource.getAttributes(), requestAttrs)) - { - throw PrimitiveException("Resource can't accept request Attributes!"); - } + SetRequestHandler::SetRequestHandler(ResourceAttributes&& attrs, + const OCEntityHandlerResult& result, int errorCode) : + RequestHandler{ std::move(attrs), result, errorCode } + { + } - replaceAttributesRecursively(resource.getAttributes(), requestAttrs); - } - return m_requestHandler->buildResponse(resource, requestAttrs); + AttrKeyValuePairs SetRequestHandler::applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod method, ResourceObject& resource, + const ResourceAttributes& requestAttrs) const + { + return getApplyAcceptanceFunc(method)(resource, requestAttrs); } } diff --git a/service/resource-manipulation/modules/serverBuilder/src/ResourceObject.cpp b/service/resource-manipulation/modules/serverBuilder/src/ResourceObject.cpp index 36309a9..342c751 100644 --- a/service/resource-manipulation/modules/serverBuilder/src/ResourceObject.cpp +++ b/service/resource-manipulation/modules/serverBuilder/src/ResourceObject.cpp @@ -37,33 +37,6 @@ namespace constexpr const char LOG_TAG[]{ "PrimitiveServerResource" }; - namespace Detail - { - template - OCEntityHandlerResult sendResponse(ResourceObject& resource, - std::shared_ptr< OC::OCResourceRequest > ocRequest, - const ResourceAttributes& requestAttrs, RESPONSE&& response) - { - auto ocResponse = response.getHandler()->buildResponse(resource, requestAttrs); - - ocResponse->setRequestHandle(ocRequest->getRequestHandle()); - ocResponse->setResourceHandle(ocRequest->getResourceHandle()); - - try - { - if (OC::OCPlatform::sendResponse(ocResponse) == OC_STACK_OK) - { - return OC_EH_OK; - } - } - catch (const OC::OCException& e) - { - OC_LOG(WARNING, LOG_TAG, e.what()); - } - - return OC_EH_ERROR; - } - } inline bool hasProperty(uint8_t base, uint8_t target) { @@ -80,20 +53,46 @@ namespace return base & ~target; } - template< typename HANDLER, typename RESPONSE = typename std::decay::type::result_type> - OCEntityHandlerResult handleRequest(ResourceObject& resource, - std::shared_ptr< OC::OCResourceRequest > ocRequest, HANDLER&& handler) + template + OCEntityHandlerResult sendResponse(ResourceObject& resource, + std::shared_ptr< OC::OCResourceRequest > ocRequest, RESPONSE&& response) + { + auto ocResponse = response.getHandler()->buildResponse(resource); + + ocResponse->setRequestHandle(ocRequest->getRequestHandle()); + ocResponse->setResourceHandle(ocRequest->getResourceHandle()); + + try + { + if (OC::OCPlatform::sendResponse(ocResponse) == OC_STACK_OK) + { + return OC_EH_OK; + } + } + catch (const OC::OCException& e) + { + OC_LOG(WARNING, LOG_TAG, e.what()); + } + + return OC_EH_ERROR; + } + + ResourceAttributes getAttributesFromOCRequest(std::shared_ptr< OC::OCResourceRequest > request) { - ResourceAttributes attrs{ ResourceAttributesConverter::fromOCRepresentation( - ocRequest->getResourceRepresentation()) }; + return ResourceAttributesConverter::fromOCRepresentation( + request->getResourceRepresentation()); + } + template< typename HANDLER, typename RESPONSE = typename std::decay::type::result_type > + RESPONSE invokeHandler(ResourceAttributes& attrs, + std::shared_ptr< OC::OCResourceRequest > ocRequest, HANDLER&& handler) + { if (handler) { - return Detail::sendResponse(resource, ocRequest, attrs, handler( - PrimitiveRequest{ ocRequest->getResourceUri() }, attrs)); + return handler(PrimitiveRequest{ ocRequest->getResourceUri() }, attrs); } - return Detail::sendResponse(resource, ocRequest, attrs, RESPONSE::defaultAction()); + return RESPONSE::defaultAction(); } } // unnamed namespace @@ -103,18 +102,14 @@ namespace OIC { namespace Service { - ResourceObject::ResourceObject(uint8_t properties, - ResourceAttributes&& attrs) : - m_properties { properties }, m_resourceHandle{}, - m_resourceAttributes{ std::move(attrs) }, m_getRequestHandler{ }, - m_setRequestHandler{ }, m_mutex { } - { - } ResourceObject::Builder::Builder(const std::string& uri, const std::string& type, const std::string& interface) : - m_uri{ uri }, m_type{ type }, m_interface{ interface }, - m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE } + m_uri{ uri }, + m_type{ type }, + m_interface{ interface }, + m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE }, + m_resourceAttributes{ } { } @@ -175,6 +170,17 @@ namespace OIC } + ResourceObject::ResourceObject(uint8_t properties, ResourceAttributes&& attrs) : + m_properties { properties }, + m_resourceHandle{ }, + m_resourceAttributes{ std::move(attrs) }, + m_getRequestHandler{ }, + m_setRequestHandler{ }, + m_lockOwner{ }, + m_mutex{ } + { + } + ResourceObject::~ResourceObject() { if (m_resourceHandle) @@ -234,12 +240,12 @@ namespace OIC void ResourceObject::setGetRequestHandler(GetRequestHandler h) { - m_getRequestHandler = h; + m_getRequestHandler = std::move(h); } void ResourceObject::setSetRequestHandler(SetRequestHandler h) { - m_setRequestHandler = h; + m_setRequestHandler = std::move(h); } void ResourceObject::notify() const @@ -273,11 +279,12 @@ namespace OIC catch (const std::exception& e) { OC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what()); + throw; } catch (...) { OC_LOG(WARNING, LOG_TAG, "Failed to handle request."); - // TODO : how to notify the error? + throw; } return OC_EH_ERROR; @@ -286,6 +293,8 @@ namespace OIC OCEntityHandlerResult ResourceObject::handleRequest( std::shared_ptr< OC::OCResourceRequest > request) { + assert(request != nullptr); + if (request->getRequestType() == "GET") { return handleRequestGet(request); @@ -302,18 +311,35 @@ namespace OIC OCEntityHandlerResult ResourceObject::handleRequestGet( std::shared_ptr< OC::OCResourceRequest > request) { - return ::handleRequest(*this, request, m_getRequestHandler); + assert(request != nullptr); + + auto attrs = getAttributesFromOCRequest(request); + + return sendResponse(*this, request, invokeHandler(attrs, request, m_getRequestHandler)); } OCEntityHandlerResult ResourceObject::handleRequestSet( std::shared_ptr< OC::OCResourceRequest > request) { - return ::handleRequest(*this, request, m_setRequestHandler); + assert(request != nullptr); + + auto attrs = getAttributesFromOCRequest(request); + auto response = invokeHandler(attrs, request, m_setRequestHandler); + auto requestHandler = response.getHandler(); + + assert(requestHandler != nullptr); + + AttrKeyValuePairs replaced = requestHandler->applyAcceptanceMethod( + response.getAcceptanceMethod(), *this, attrs); + + return sendResponse(*this, request, response); } OCEntityHandlerResult ResourceObject::handleObserve( std::shared_ptr< OC::OCResourceRequest > request) { + assert(request != nullptr); + if (!isObservable()) { return OC_EH_ERROR; diff --git a/service/resource-manipulation/modules/serverBuilder/unittests/PrimitiveResponseTest.cpp b/service/resource-manipulation/modules/serverBuilder/unittests/PrimitiveResponseTest.cpp index eb18e4f..7a6e433 100644 --- a/service/resource-manipulation/modules/serverBuilder/unittests/PrimitiveResponseTest.cpp +++ b/service/resource-manipulation/modules/serverBuilder/unittests/PrimitiveResponseTest.cpp @@ -60,7 +60,6 @@ class PrimitiveResponseTest: public Test { public: MockRepository mocks; - ResourceObject::Ptr server; public: template< typename T > @@ -69,7 +68,7 @@ public: ResourceObject::Ptr server = ResourceObject::Builder("a/test", "", "").build(); - return response.getHandler()->buildResponse(*server, ResourceAttributes()); + return response.getHandler()->buildResponse(*server); } protected: @@ -79,8 +78,6 @@ protected: .Return(OC_STACK_OK); mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK); - - server = ResourceObject::Builder("a/test", "", "").build(); } }; @@ -175,3 +172,31 @@ TEST_F(PrimitiveResponseTest, SetResponseCanMoveAttrs) EXPECT_TRUE(attrs.empty()); } + + +TEST_F(PrimitiveResponseTest, DefaultSetResponseHasDefaultMethod) +{ + EXPECT_EQ(PrimitiveSetResponse::AcceptanceMethod::DEFAULT, + PrimitiveSetResponse::defaultAction().getAcceptanceMethod()); +} + +TEST_F(PrimitiveResponseTest, AcceptSetResponseHasAcceptMethod) +{ + EXPECT_EQ(PrimitiveSetResponse::AcceptanceMethod::ACCEPT, + PrimitiveSetResponse::accept().getAcceptanceMethod()); +} + +TEST_F(PrimitiveResponseTest, IgnoreSetResponseHasIgnoreMethod) +{ + EXPECT_EQ(PrimitiveSetResponse::AcceptanceMethod::IGNORE, + PrimitiveSetResponse::ignore().getAcceptanceMethod()); +} + +TEST_F(PrimitiveResponseTest, SetResponseHasMethodSetBySetter) +{ + PrimitiveSetResponse::AcceptanceMethod method = PrimitiveSetResponse::AcceptanceMethod::ACCEPT; + PrimitiveSetResponse response = + PrimitiveSetResponse::defaultAction().setAcceptanceMethod(method); + + EXPECT_EQ(method, response.getAcceptanceMethod()); +} diff --git a/service/resource-manipulation/modules/serverBuilder/unittests/RequestHandlerTest.cpp b/service/resource-manipulation/modules/serverBuilder/unittests/RequestHandlerTest.cpp index dee1f94..f937049 100644 --- a/service/resource-manipulation/modules/serverBuilder/unittests/RequestHandlerTest.cpp +++ b/service/resource-manipulation/modules/serverBuilder/unittests/RequestHandlerTest.cpp @@ -33,16 +33,16 @@ using namespace OIC::Service; constexpr char EXISTING[]{ "ext" }; constexpr int ORIGIN_VALUE{ 100 }; +constexpr int NEW_VALUE{ 1 }; + using RegisterResource = OCStackResult (*)(OCResourceHandle&, std::string&, const std::string&, const std::string&, OC::EntityHandler, uint8_t); -class SimpleRequestHandlerTest: public Test +class RequestHandlerTest: public Test { public: ResourceObject::Ptr server; - ResourceAttributes requestAttrs; - MockRepository mocks; protected: @@ -51,104 +51,121 @@ protected: mocks.OnCallFuncOverload(static_cast(OC::OCPlatform::registerResource)) .Return(OC_STACK_OK); + mocks.OnCallFunc(OC::OCPlatform::unregisterResource).Return(OC_STACK_OK); + server = ResourceObject::Builder("a/test", "resourceType", "").build(); server->setAttribute(EXISTING, ORIGIN_VALUE); } }; -TEST_F(SimpleRequestHandlerTest, ResponseHasSameValuesPassedToHandlerConstructor) +TEST_F(RequestHandlerTest, ResponseHasSameValuesPassedToHandlerConstructor) { - SimpleRequestHandler handler{ OC_EH_ERROR, -1000 }; + RequestHandler handler{ OC_EH_ERROR, -1000 }; - auto response = handler.buildResponse(*server, requestAttrs); + auto response = handler.buildResponse(*server); ASSERT_EQ(OC_EH_ERROR, response->getResponseResult()); ASSERT_EQ(-1000, response->getErrorCode()); } -TEST_F(SimpleRequestHandlerTest, ResponseHasSameAttrsWithServerAttrs) +TEST_F(RequestHandlerTest, ResponseHasSameAttrsWithServerAttrs) { - SimpleRequestHandler handler{}; + RequestHandler handler{}; - auto response = handler.buildResponse(*server, requestAttrs); + auto response = handler.buildResponse(*server); ASSERT_EQ(ORIGIN_VALUE, response->getResourceRepresentation()[EXISTING].getValue()); } -TEST_F(SimpleRequestHandlerTest, ResponseHasAttrsSetByCustomAttrRequestHandler) +TEST_F(RequestHandlerTest, ResponseHasAttrsSetByCustomAttrRequestHandler) { constexpr char key[] { "key" }; constexpr int newValue{ 100 }; ResourceAttributes attrs; attrs[key] = newValue; - CustomAttrRequestHandler handler{ attrs }; + RequestHandler handler{ attrs }; - auto response = handler.buildResponse(*server, requestAttrs); + auto response = handler.buildResponse(*server); ASSERT_EQ(ORIGIN_VALUE, response->getResourceRepresentation()[key].getValue()); } -class SetRequestProxyHandlerTest: public Test +class SetRequestHandlerAcceptanceTest: public RequestHandlerTest { public: - ResourceObject::Ptr server; - ResourceAttributes requestAttrs; - RequestHandler::Ptr setRequestProxyHandler; + SetRequestHandler::Ptr setRequestHandler; - MockRepository mocks; + ResourceAttributes requestAttrs; protected: void SetUp() override { - mocks.OnCallFuncOverload(static_cast(OC::OCPlatform::registerResource)) - .Return(OC_STACK_OK); + RequestHandlerTest::SetUp(); - setRequestProxyHandler = make_shared( - make_shared()); + setRequestHandler = make_shared< SetRequestHandler >(); - server = ResourceObject::Builder("a/test", "resourceType", "").build(); - - server->setAttribute(EXISTING, ORIGIN_VALUE); + requestAttrs[EXISTING] = NEW_VALUE; } }; -TEST_F(SetRequestProxyHandlerTest, NothingHappenedWithEmptyAttrs) +TEST_F(SetRequestHandlerAcceptanceTest, NothingReplacedWithIgnoreMethod) { + auto replaced = setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::IGNORE, *server, requestAttrs); - setRequestProxyHandler->buildResponse(*server, requestAttrs); - - ASSERT_EQ(ORIGIN_VALUE, server->getAttribute(EXISTING)); + ASSERT_TRUE(replaced.empty()); } -TEST_F(SetRequestProxyHandlerTest, ServerAttributesChangedIfOnlySameKeyExists) +TEST_F(SetRequestHandlerAcceptanceTest, NewValueApplyedWithAcceptMethod) { - constexpr int newValue{ 100 }; + setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, requestAttrs); - requestAttrs[EXISTING] = newValue; + ASSERT_EQ(NEW_VALUE, server->getAttribute(EXISTING)); +} - setRequestProxyHandler->buildResponse(*server, requestAttrs); +TEST_F(SetRequestHandlerAcceptanceTest, ReturnedAttrPairsHaveOldValue) +{ + auto replaced = setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, requestAttrs); - ASSERT_EQ(newValue, server->getAttribute(EXISTING)); + ASSERT_EQ(ORIGIN_VALUE, replaced[0].second); } -TEST_F(SetRequestProxyHandlerTest, ThrowIfTypeMismatch) +TEST_F(SetRequestHandlerAcceptanceTest, NothingHappenedWithEmptyAttrs) +{ + setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, ResourceAttributes{ }); + + ASSERT_EQ(ORIGIN_VALUE, server->getAttribute(EXISTING)); +} + + +TEST_F(SetRequestHandlerAcceptanceTest, NothingReplacedIfTypeMismatch) { requestAttrs[EXISTING] = ""; - ASSERT_THROW(setRequestProxyHandler->buildResponse(*server, requestAttrs), PrimitiveException); + auto replaced = setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, requestAttrs); + + ASSERT_TRUE(replaced.empty()); } -TEST_F(SetRequestProxyHandlerTest, ThrowIfRequestAttrsHasUnknownKey) +TEST_F(SetRequestHandlerAcceptanceTest, NothingReplacedIfRequestAttrsHasUnknownKey) { constexpr char unknownKey[]{ "???" }; requestAttrs[EXISTING] = ORIGIN_VALUE; requestAttrs[unknownKey] = ORIGIN_VALUE; - ASSERT_THROW(setRequestProxyHandler->buildResponse(*server, requestAttrs), PrimitiveException); + + auto replaced = setRequestHandler->applyAcceptanceMethod( + PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, requestAttrs); + + ASSERT_TRUE(replaced.empty()); }