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 <jhyo.kim@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1517
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Madan Lanka <lanka.madan@samsung.com>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
{
}
+ Value(const char* value);
+
Value& operator=(const Value&);
Value& operator=(Value&&);
#ifndef COMMON_INTERNAL_RESOURCEATTRIBUTESUTILS_H
#define COMMON_INTERNAL_RESOURCEATTRIBUTESUTILS_H
+#include <vector>
+#include <string>
+
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);
}
}
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&
{
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;
}
}
}
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;
ResourceAttributes newAttrs;
newAttrs[KEY] = NEW_VALUE;
- replaceAttributesRecursively(resourceAttributes, newAttrs);
+ replaceAttributes(resourceAttributes, newAttrs);
ASSERT_EQ(NEW_VALUE, resourceAttributes[KEY]);
}
class ResourceAttributes;
class RequestHandler;
+ class SetRequestHandler;
class PrimitiveGetResponse
{
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&);
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;
};
}
}
#define __REQUESTHANDLER_H
#include <ResourceObject.h>
+#include <PrimitiveResponse.h>
-#include <OCResourceResponse.h>
+#include <internal/ResourceAttributesUtils.h>
+
+namespace OC
+{
+ class OCResourceResponse;
+ class OCRepresentation;
+}
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 <typename T>
- 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;
};
+
}
}
{
PrimitiveGetResponse PrimitiveGetResponse::defaultAction()
{
- static PrimitiveGetResponse defaultRes { std::make_shared<SimpleRequestHandler>() };
+ static PrimitiveGetResponse defaultRes { std::make_shared< RequestHandler >() };
return defaultRes;
}
int errorCode)
{
return PrimitiveGetResponse {
- std::make_shared<SimpleRequestHandler>( result, errorCode) };
+ std::make_shared< RequestHandler >( result, errorCode) };
}
PrimitiveGetResponse PrimitiveGetResponse::create(const ResourceAttributes& attrs)
{
- return PrimitiveGetResponse { std::make_shared<CustomAttrRequestHandler>(attrs) };
+ return PrimitiveGetResponse { std::make_shared< RequestHandler >(attrs) };
}
PrimitiveGetResponse PrimitiveGetResponse::create(const ResourceAttributes& attrs,
const OCEntityHandlerResult& result, int errorCode)
{
return PrimitiveGetResponse {
- std::make_shared<CustomAttrRequestHandler>(attrs, result, errorCode) };
+ std::make_shared< RequestHandler >(attrs, result, errorCode) };
}
PrimitiveGetResponse PrimitiveGetResponse::create(ResourceAttributes&& result)
{
return PrimitiveGetResponse {
- std::make_shared<CustomAttrRequestHandler>(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<CustomAttrRequestHandler>(
+ return PrimitiveGetResponse { std::make_shared< RequestHandler >(
std::move(attrs), result, errorCode) };
}
PrimitiveSetResponse PrimitiveSetResponse::defaultAction()
{
- static PrimitiveSetResponse defaultRes {
- withProxy(std::make_shared<SimpleRequestHandler>()) };
+ 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<SimpleRequestHandler>(result, errorCode));
+ return std::make_shared< SetRequestHandler >(result, errorCode);
}
PrimitiveSetResponse PrimitiveSetResponse::create(const ResourceAttributes& attrs)
{
- return withProxy(std::make_shared<CustomAttrRequestHandler>(attrs));
+ return std::make_shared< SetRequestHandler >(attrs);
}
PrimitiveSetResponse PrimitiveSetResponse::create(const ResourceAttributes& attrs,
const OCEntityHandlerResult& result, int errorCode)
{
- return withProxy(std::make_shared<CustomAttrRequestHandler>(attrs, result, errorCode));
+ return std::make_shared< SetRequestHandler >(attrs, result, errorCode);
}
PrimitiveSetResponse PrimitiveSetResponse::create(ResourceAttributes&& result)
{
- return withProxy(std::make_shared<CustomAttrRequestHandler>(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<CustomAttrRequestHandler>(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<SetRequestProxyHandler>(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;
}
}
}
#include <internal/RequestHandler.h>
#include <internal/ResourceAttributesConverter.h>
-#include <internal/ResourceAttributesUtils.h>
-namespace OIC
+#include <OCResourceResponse.h>
+
+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<T>(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<AttrKeyValuePairs(ResourceObject&, const ResourceAttributes&)> 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);
}
}
constexpr const char LOG_TAG[]{ "PrimitiveServerResource" };
- namespace Detail
- {
- template <typename RESPONSE>
- 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)
{
return base & ~target;
}
- template< typename HANDLER, typename RESPONSE = typename std::decay<HANDLER>::type::result_type>
- OCEntityHandlerResult handleRequest(ResourceObject& resource,
- std::shared_ptr< OC::OCResourceRequest > ocRequest, HANDLER&& handler)
+ template <typename RESPONSE>
+ 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<HANDLER>::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
{
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{ }
{
}
}
+ 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)
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
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;
OCEntityHandlerResult ResourceObject::handleRequest(
std::shared_ptr< OC::OCResourceRequest > request)
{
+ assert(request != nullptr);
+
if (request->getRequestType() == "GET")
{
return handleRequestGet(request);
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;
{
public:
MockRepository mocks;
- ResourceObject::Ptr server;
public:
template< typename T >
ResourceObject::Ptr server =
ResourceObject::Builder("a/test", "", "").build();
- return response.getHandler()->buildResponse(*server, ResourceAttributes());
+ return response.getHandler()->buildResponse(*server);
}
protected:
.Return(OC_STACK_OK);
mocks.OnCallFunc(OCPlatform::unregisterResource).Return(OC_STACK_OK);
-
- server = ResourceObject::Builder("a/test", "", "").build();
}
};
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());
+}
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:
mocks.OnCallFuncOverload(static_cast<RegisterResource>(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<int>());
}
-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<int>());
}
-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<RegisterResource>(OC::OCPlatform::registerResource))
- .Return(OC_STACK_OK);
+ RequestHandlerTest::SetUp();
- setRequestProxyHandler = make_shared<SetRequestProxyHandler>(
- make_shared<SimpleRequestHandler>());
+ 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<int>(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<int>(EXISTING));
+}
- setRequestProxyHandler->buildResponse(*server, requestAttrs);
+TEST_F(SetRequestHandlerAcceptanceTest, ReturnedAttrPairsHaveOldValue)
+{
+ auto replaced = setRequestHandler->applyAcceptanceMethod(
+ PrimitiveSetResponse::AcceptanceMethod::ACCEPT, *server, requestAttrs);
- ASSERT_EQ(newValue, server->getAttribute<int>(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<int>(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());
}