modified RCSResourceObject to generate responses according to the interface of requests.
authorjaesick.shin <jaesick.shin@samsung.com>
Thu, 25 Feb 2016 05:54:55 +0000 (14:54 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 26 Feb 2016 04:57:58 +0000 (04:57 +0000)
Generate response for each of interface. (supported interfaces - oic.if.baseline, oic.if.a, oic.if.s, oic.if.b)
User can setting the default Interface.
If user not setting the default interface -> RE setting The default interface "oic.if.baseline"

Change-Id: If4faa93bb97850587bc44c7df5e6495796544c18
Signed-off-by: jaesick.shin <jaesick.shin@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5195
Reviewed-by: JungHo Kim <jhyo.kim@samsung.com>
Tested-by: JungHo Kim <jhyo.kim@samsung.com>
service/resource-encapsulation/examples/linux/SampleResourceClient.cpp
service/resource-encapsulation/examples/linux/SampleResourceServer.cpp
service/resource-encapsulation/include/RCSResourceObject.h
service/resource-encapsulation/src/serverBuilder/include/InterfaceHandler.h [new file with mode: 0644]
service/resource-encapsulation/src/serverBuilder/include/RequestHandler.h
service/resource-encapsulation/src/serverBuilder/src/InterfaceHandler.cpp [new file with mode: 0644]
service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
service/resource-encapsulation/src/serverBuilder/src/RequestHandler.cpp
service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
service/resource-encapsulation/src/serverBuilder/unittests/RequestHandlerTest.cpp

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