Refactor PrimitiveResponse and RequestHandler
authorcoderhyme <jhyo.kim@samsung.com>
Sat, 4 Jul 2015 03:48:25 +0000 (12:48 +0900)
committerUze Choi <uzchoi@samsung.com>
Mon, 6 Jul 2015 09:25:25 +0000 (09:25 +0000)
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>
service/resource-manipulation/modules/common/primitiveResource/include/ResourceAttributes.h
service/resource-manipulation/modules/common/primitiveResource/include/internal/ResourceAttributesUtils.h
service/resource-manipulation/modules/common/primitiveResource/src/ResourceAttributes.cpp
service/resource-manipulation/modules/common/primitiveResource/unittests/ResourceAttributesTest.cpp
service/resource-manipulation/modules/serverBuilder/include/PrimitiveResponse.h
service/resource-manipulation/modules/serverBuilder/include/internal/RequestHandler.h
service/resource-manipulation/modules/serverBuilder/src/PrimitiveResponse.cpp
service/resource-manipulation/modules/serverBuilder/src/RequestHandler.cpp
service/resource-manipulation/modules/serverBuilder/src/ResourceObject.cpp
service/resource-manipulation/modules/serverBuilder/unittests/PrimitiveResponseTest.cpp
service/resource-manipulation/modules/serverBuilder/unittests/RequestHandlerTest.cpp

index 77819d1..35219fb 100755 (executable)
@@ -118,6 +118,8 @@ namespace OIC
                 {
                 }
 
+                Value(const char* value);
+
                 Value& operator=(const Value&);
                 Value& operator=(Value&&);
 
index a61cd00..8672373 100644 (file)
 #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);
     }
 }
 
index c065101..95d1746 100755 (executable)
@@ -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;
         }
     }
 }
index 00fff7d..3066a5f 100644 (file)
@@ -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]);
 }
index 717a873..3ec2967 100644 (file)
@@ -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;
         };
     }
 }
index b7f97cc..d27723a 100644 (file)
 #define __REQUESTHANDLER_H
 
 #include <ResourceObject.h>
+#include <PrimitiveResponse.h>
 
-#include <OCResourceResponse.h>
+#include <internal/ResourceAttributesUtils.h>
+
+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 <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;
         };
+
     }
 }
 
index 5bcc5f9..94eb85f 100644 (file)
@@ -28,7 +28,7 @@ namespace OIC
     {
         PrimitiveGetResponse PrimitiveGetResponse::defaultAction()
         {
-            static PrimitiveGetResponse defaultRes { std::make_shared<SimpleRequestHandler>() };
+            static PrimitiveGetResponse defaultRes { std::make_shared< RequestHandler >() };
 
             return defaultRes;
         }
@@ -37,31 +37,31 @@ namespace OIC
                 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) };
         }
 
@@ -79,59 +79,86 @@ namespace OIC
 
         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;
         }
     }
 }
index 0bd8848..6d4e205 100644 (file)
 #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);
         }
 
     }
index 36309a9..342c751 100644 (file)
@@ -37,33 +37,6 @@ namespace
 
     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)
     {
@@ -80,20 +53,46 @@ namespace
         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
@@ -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;
index eb18e4f..7a6e433 100644 (file)
@@ -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());
+}
index dee1f94..f937049 100644 (file)
@@ -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<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());
 }