Implementation of Things Manager feature.
authorHyunJun Kim <hyunjun2.kim@samsung.com>
Tue, 16 Dec 2014 07:50:07 +0000 (16:50 +0900)
committerHyunJun Kim <hyunjun2.kim@samsung.com>
Tue, 16 Dec 2014 07:50:07 +0000 (16:50 +0900)
Add feature for Things Manager

 - Subscribe Collection Presence
 - CRUD function for ActionSet
 - Finding group
 - Creating group
 - Join the specific group
 - Let the other devices to join the specific group
 - Leave from the specific group
 - Delete the group
 - Get all group information
 - send configuration information to multiple things
 - send diagnostics information(i.e. factory reset, reboot)
 - Get the configuration parameter list
 - Get the diagnostics functionalities list

Fix Segmentation fault.
 - Bug fix : "Implementation of Things Manager feature."
             https://oic-review.01.org/gerrit/495
             OCPlatform_impl.cpp, InProcServerWrapper.cpp

Change-Id: I5b44fbdb034c924df4787a30a4d9c86ce4704aff
Signed-off-by: HyunJun Kim <hyunjun2.kim@samsung.com>
17 files changed:
resource/src/InProcServerWrapper.cpp [changed mode: 0644->0755]
resource/src/OCPlatform_impl.cpp [changed mode: 0644->0755]
service/things-manager/build/linux/Makefile [changed mode: 0644->0755]
service/things-manager/sampleapp/SConscript [deleted file]
service/things-manager/sdk/build/linux/Makefile [changed mode: 0644->0755]
service/things-manager/sdk/inc/TGMClient.h [deleted file]
service/things-manager/sdk/inc/ThingsManager.h [new file with mode: 0755]
service/things-manager/sdk/src/GroupManager.cpp [new file with mode: 0755]
service/things-manager/sdk/src/GroupManager.h [new file with mode: 0755]
service/things-manager/sdk/src/GroupSynchronization.cpp [new file with mode: 0755]
service/things-manager/sdk/src/GroupSynchronization.h [new file with mode: 0755]
service/things-manager/sdk/src/TGMClient.cpp [deleted file]
service/things-manager/sdk/src/ThingsConfiguration.cpp [new file with mode: 0755]
service/things-manager/sdk/src/ThingsConfiguration.h [new file with mode: 0755]
service/things-manager/sdk/src/ThingsDiagnostics.cpp [new file with mode: 0755]
service/things-manager/sdk/src/ThingsDiagnostics.h [new file with mode: 0755]
service/things-manager/sdk/src/ThingsManager.cpp [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index c92a036..9dbaa27
@@ -351,7 +351,7 @@ namespace OC
                         resourceTypeName.c_str(), // const char * resourceTypeName
                         resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
                         resourceHOST.c_str(), // const char * host
-                        resourceURI.c_str(), // const char * uri
+                        (resourceHOST + resourceURI).c_str(), // const char * uri
                         EntityHandlerWrapper, // OCEntityHandler entityHandler
                         resourceProperties // uint8_t resourceProperties
                         );
@@ -362,7 +362,7 @@ namespace OC
                         resourceTypeName.c_str(), // const char * resourceTypeName
                         resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
                         resourceHOST.c_str(), // const char * host
-                        resourceURI.c_str(), // const char * uri
+                        (resourceHOST + resourceURI).c_str(), // const char * uri
                         nullptr, // OCEntityHandler entityHandler
                         resourceProperties // uint8_t resourceProperties
                         );
old mode 100644 (file)
new mode 100755 (executable)
index e99cea7..e680943
@@ -190,9 +190,10 @@ namespace OC
                                             const std::shared_ptr< OCResource > resource)
     {
         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+        std::vector<std::string> resourceTypes = resource->getResourceTypes();
 
         return checked_guard(m_server, &IServerWrapper::registerResourceWithHost,
-                ref(resourceHandle), resource->host(), resource->uri(), "core.remote", "oc.mi.def",
+                ref(resourceHandle), resource->host(), resource->uri(), resourceTypes[0]/*"core.remote"*/, "oc.mi.def",
                 (EntityHandler) nullptr, resourceProperty);
 
     }
old mode 100644 (file)
new mode 100755 (executable)
index 58009ec..dc9647f
@@ -1,5 +1,4 @@
 .PHONY : pre resource sdk sampleapp
-
 #.PHONY : lib tgm sdk sampleapp 
 all: .PHONY
 
@@ -16,8 +15,8 @@ sdk:
 
 
 sampleapp:
-       cd ../../sampleapp/linux/tgmclient && $(MAKE)
-       cp -Rdp ../../sampleapp/linux/tgmclient/tgmclient release/
+#      cd ../../sampleapp/linux/tgmclient && $(MAKE)
+#      cp -Rdp ../../sampleapp/linux/tgmclient/tgmclient release/
 
 clean:
        cd ../../sdk/build/linux && $(MAKE) clean
diff --git a/service/things-manager/sampleapp/SConscript b/service/things-manager/sampleapp/SConscript
deleted file mode 100644 (file)
index bd1b631..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-##
-# sampleapp build script
-##
-
-Import('env')
-
-if env.get('TARGET_OS') == 'linux':
-       # Build linux sample app
-       SConscript('linux/tgmclient/SConscript')
old mode 100644 (file)
new mode 100755 (executable)
index 1cadc89..0e5ec03
@@ -15,13 +15,14 @@ CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -ldl
 
 
-CXX_INC        := -I../../ -I../../inc/ 
+CXX_INC        := -I../../ -I../../inc/ -I../../src/
 CXX_INC        += -I${IOT_BASE}/include/ 
 CXX_INC += -I${IOT_BASE}/oc_logger/include
 CXX_INC        += -I${IOT_BASE}/csdk/stack/include 
 CXX_INC        += -I${IOT_BASE}/csdk/ocsocket/include 
 CXX_INC        += -I${IOT_BASE}/csdk/ocrandom/include 
 CXX_INC        += -I${IOT_BASE}/csdk/logger/include 
+CXX_INC        += -I${IOT_BASE}/dependencies/cereal/include
 
 CXX_LIB=-L""
 
diff --git a/service/things-manager/sdk/inc/TGMClient.h b/service/things-manager/sdk/inc/TGMClient.h
deleted file mode 100644 (file)
index a087ee6..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file   TGMClient.h
-
-/// @brief  This file contains the declaration of classes and its members related to TGMClient.
-
-#ifndef __OC_TGMCLIENT__
-#define __OC_TGMCLIENT__
-
-#include <string>
-#include <vector>
-#include <map>
-#include <cstdlib>
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-using namespace OC;
-
-typedef std::function< void(std::vector< std::shared_ptr< OCResource > >) > CandidateCallback;
-typedef std::function< void(std::vector< std::shared_ptr< OCResource > >) > CollectionPresenceCallback;
-
-class TGMClient
-{
-public:
-    /**
-     * Constructor for TGMClient. Constructs a new TGMClient
-     */
-    TGMClient(void);
-
-    /**
-     * Virtual destructor
-     */
-    ~TGMClient(void);
-
-    /**
-     * API for candidate resources discovery.
-     * Callback only call when all resource types found.
-     *
-     * @param resourceTypes - required resource types(called "candidate")
-     * @param candidateCallback - callback. OCResource vector.
-     *
-     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-     *
-     * NOTE: OCStackResult is defined in ocstack.h.
-     */
-    OCStackResult findCandidateResources(std::vector< std::string > resourceTypes,
-            CandidateCallback callback, int waitsec = -1);
-
-    /**
-     * API for Collection member's state subscribe.
-     *
-     * NOTE: NOT IMPLEMENT YET
-     */
-    OCStackResult subscribeCollectionPresence(OCResourceHandle&, CollectionPresenceCallback)
-    {
-        return OC_STACK_NOTIMPL;
-    }
-
-private:
-
-    void onFoundResource(std::shared_ptr< OCResource > resource, int waitsec);
-    void findPreparedRequest(std::map< std::vector< std::string >, CandidateCallback > &request);
-    void lazyCallback(int second);
-
-};
-
-#endif  /* __OC_TGMCLIENT__*/
diff --git a/service/things-manager/sdk/inc/ThingsManager.h b/service/things-manager/sdk/inc/ThingsManager.h
new file mode 100755 (executable)
index 0000000..31ee597
--- /dev/null
@@ -0,0 +1,111 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file   ThingsManager.h
+
+/// @brief  This file contains the declaration of classes and its members related to TGMClient.
+
+#ifndef __OC_THINGSMANAGER__
+#define __OC_THINGSMANAGER__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "GroupManager.h"
+
+using namespace OC;
+
+
+class ThingsManager
+{
+public:
+    /**
+     * Constructor for TGMClient. Constructs a new TGMClient
+     */
+    ThingsManager(void);
+
+    /**
+     * Virtual destructor
+     */
+    ~ThingsManager(void);
+
+    /**
+     * API for candidate resources discovery.
+     * Callback only call when all resource types found.
+     *
+     * @param resourceTypes - required resource types(called "candidate")
+     * @param candidateCallback - callback. OCResource vector.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult findCandidateResources(std::vector< std::string > resourceTypes,
+            std::function< void(std::vector< std::shared_ptr< OCResource > >) >  callback, int waitsec = -1);
+
+    /**
+     * API for Collection member's state subscribe.
+     *
+     *
+     */
+    OCStackResult subscribeCollectionPresence(std::shared_ptr< OCResource >, std::function< void(std::string, OCStackResult) > );
+
+       // Group Synchronization
+       OCStackResult findGroup (std::vector <std::string> collectionResourceTypes, FindCallback resourceHandler);
+       OCStackResult createGroup (std::string collectionResourceType);
+       OCStackResult joinGroup (std::string collectionResourceType, OCResourceHandle resourceHandle);
+       OCStackResult joinGroup (const std::shared_ptr<OCResource> resource, OCResourceHandle resourceHandle);
+       OCStackResult leaveGroup (std::string collectionResourceType, OCResourceHandle resourceHandle);
+       void deleteGroup (std::string collectionResourceType);
+       std::map<std::string, OCResourceHandle> getGroupList ();
+
+    // Things Configuration
+    OCStackResult updateConfigurations(std::shared_ptr< OCResource > resource, std::map<std::string, std::string> configurations,
+                std::function< void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > callback);
+    OCStackResult getConfigurations(std::shared_ptr< OCResource > resource, std::vector<std::string> configurations,
+                std::function< void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > callback);
+    std::string getListOfSupportedConfigurationUnits();
+    OCStackResult doBootstrap(
+                std::function< void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > callback);
+
+    // Things Diagnostics
+    OCStackResult reboot(std::shared_ptr< OCResource > resource,
+                std::function< void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > callback);
+    OCStackResult factoryReset(std::shared_ptr< OCResource > resource,
+                std::function< void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > callback);
+
+
+
+
+    // Group Action.
+    std::string getStringFromActionSet(const ActionSet *newActionSet);
+    ActionSet* getActionSetfromString(std::string desc);
+
+    OCStackResult addActionSet(std::shared_ptr< OCResource > resource, const ActionSet* newActionSet, PutCallback cb);
+    OCStackResult executeActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb);
+    OCStackResult getActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, GetCallback cb);
+    OCStackResult deleteActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback);
+
+};
+
+#endif  /* __OC_THINGSMANAGER__*/
diff --git a/service/things-manager/sdk/src/GroupManager.cpp b/service/things-manager/sdk/src/GroupManager.cpp
new file mode 100755 (executable)
index 0000000..b5bb22e
--- /dev/null
@@ -0,0 +1,603 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file    GroupManager.cpp
+///  @brief
+
+
+#include "GroupManager.h"
+#include <algorithm>
+#include <thread>
+#include <unistd.h>
+
+#include <string.h>
+
+#define DESC_DELIMITER "\""
+#define ACTION_DELIMITER "*"
+#define ATTR_DELIMITER "|"
+
+using namespace OC;
+
+std::map< std::vector< std::string >, CandidateCallback > candidateRequest;
+std::map< std::vector< std::string >, CandidateCallback > candidateRequestForTimer;
+std::map< std::string, std::map< std::string, std::shared_ptr< OCResource > > > rtForResourceList;
+std::vector< std::string > allFoundResourceTypes;
+
+template< typename T >
+bool IsSubset(std::vector< T > full, std::vector< T > sub)
+{
+    std::sort(full.begin(), full.end());
+    std::sort(sub.begin(), sub.end());
+    return std::includes(full.begin(), full.end(), sub.begin(), sub.end());
+}
+std::vector< std::string > &str_split(const std::string &s, char delim,
+        std::vector< std::string > &elems)
+{
+    std::stringstream ss(s);
+    std::string item;
+    while (std::getline(ss, item, delim))
+    {
+        elems.push_back(item);
+    }
+    return elems;
+}
+
+std::vector< std::string > str_split(const std::string &s, char delim)
+{
+    std::vector< std::string > elems;
+    str_split(s, delim, elems);
+    return elems;
+}
+
+void GroupManager::onFoundResource(std::shared_ptr< OCResource > resource, int waitsec)
+{
+
+    std::string resourceURI;
+    std::string hostAddress;
+    try
+    {
+        // Do some operations with resource object.
+        if (resource)
+        {
+
+            std::cout << "DISCOVERED Resource:" << std::endl;
+            // Get the resource URI
+            resourceURI = resource->uri();
+            std::cout << "\tURI of the resource: " << resourceURI << std::endl;
+
+            // Get the resource host address
+            hostAddress = resource->host();
+            std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
+
+            // Get the resource types
+            std::cout << "\tList of resource types: " << std::endl;
+
+            hostAddress.append(resourceURI);
+
+            for (auto &resourceTypes : resource->getResourceTypes())
+            {
+                std::cout << "\t\t" << resourceTypes << std::endl;
+
+                if (std::find(allFoundResourceTypes.begin(), allFoundResourceTypes.end(),
+                        resourceTypes) == allFoundResourceTypes.end())
+                {
+                    allFoundResourceTypes.push_back(resourceTypes);
+                }
+
+                rtForResourceList[resourceTypes][hostAddress] = resource;
+            }
+
+            // Get the resource interfaces
+            std::cout << "\tList of resource interfaces: " << std::endl;
+            for (auto &resourceInterfaces : resource->getResourceInterfaces())
+            {
+                std::cout << "\t\t" << resourceInterfaces << std::endl;
+            }
+
+            if (waitsec == -1)
+            {
+                findPreparedRequest(candidateRequest);
+            }
+        }
+        else
+        {
+            // Resource is invalid
+            std::cout << "Resource is invalid" << std::endl;
+        }
+
+    }
+    catch (std::exception& e)
+    {
+        //log(e.what());
+    }
+}
+
+GroupManager::GroupManager(void)
+{
+    ;
+}
+
+/**
+ * Virtual destructor
+ */
+GroupManager::~GroupManager(void)
+{
+    candidateRequest.clear();
+    candidateRequestForTimer.clear();
+    rtForResourceList.clear();
+    allFoundResourceTypes.clear();
+}
+
+void GroupManager::findPreparedRequest(
+        std::map< std::vector< std::string >, CandidateCallback > &request)
+{
+    std::vector < std::shared_ptr < OCResource >> resources;
+
+    for (auto it = request.begin(); it != request.end();)
+    {
+
+        if (IsSubset(allFoundResourceTypes, it->first))
+        {
+            //std::cout << "IS SUBSET !!! \n";
+
+            for (unsigned int i = 0; i < it->first.size(); ++i)
+            {
+
+                for (auto secondIt = rtForResourceList[it->first.at(i)].begin();
+                        secondIt != rtForResourceList[it->first.at(i)].end(); ++secondIt)
+                {
+                    resources.push_back(secondIt->second);
+                }
+            }
+
+            it->second(resources);
+
+            //TODO : decide policy - callback only once
+            request.erase(it++);
+        }
+        else
+        {
+            ++it;
+        }
+
+    }
+
+}
+
+void GroupManager::lazyCallback(int second)
+{
+    sleep(second);
+    findPreparedRequest(candidateRequestForTimer);
+
+}
+
+OCStackResult GroupManager::findCandidateResources(std::vector< std::string > resourceTypes,
+        CandidateCallback callback, int waitsec)
+{
+    if (resourceTypes.size() < 1)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    std::sort(resourceTypes.begin(), resourceTypes.end());
+    resourceTypes.erase(std::unique(resourceTypes.begin(), resourceTypes.end()),
+            resourceTypes.end());
+
+    if (waitsec != -1)
+    {
+        candidateRequestForTimer.insert(std::make_pair(resourceTypes, callback));
+    }
+    else
+    {
+        candidateRequest.insert(std::make_pair(resourceTypes, callback));
+    }
+
+    for (unsigned int i = 0; i < resourceTypes.size(); ++i)
+    {
+        std::cout << "resourceTypes : " << resourceTypes.at(i) << std::endl;
+        std::string query = "coap://224.0.1.187/oc/core?rt=";
+        query.append(resourceTypes.at(i));
+        OCPlatform::findResource("", query.c_str(),
+                std::function < void(std::shared_ptr < OCResource > resource)
+                        > (std::bind(&GroupManager::onFoundResource, this, std::placeholders::_1,
+                                waitsec)));
+    }
+
+    if (waitsec != -1)
+    {
+        std::thread exec(
+                std::function< void(int second) >(
+                        std::bind(&GroupManager::lazyCallback, this, std::placeholders::_1)), waitsec);
+        exec.detach();
+    }
+
+    return OC_STACK_OK;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+    Presence Check
+*/
+
+
+
+std::map<std::string, CollectionPresenceCallback> presenceCallbacks;
+
+// Callback to presence
+void GroupManager::collectionPresenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress, std::string host, std::string uri)
+{
+    std::cout << "uri : " << uri << std::endl;
+    std::cout << "host : " << host << std::endl;
+    std::cout << "result : " << result << std::endl;
+    switch(result)
+    {
+        case OC_STACK_OK:
+            std::cout << "Nonce# " << nonce << std::endl;
+            break;
+        case OC_STACK_PRESENCE_STOPPED:
+            std::cout << "Presence Stopped\n";
+            break;
+        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
+            std::cout << "Presence do not handle\n";
+            break;
+        case OC_STACK_PRESENCE_TIMEOUT:
+            std::cout << "Presence TIMEOUT\n";
+            break;
+        default:
+            std::cout << "Error\n";
+            break;
+    }
+
+    if(presenceCallbacks.find(uri) != presenceCallbacks.end())
+    {
+        (presenceCallbacks.find(uri)->second)(uri,result);
+    }
+}
+
+void GroupManager::checkCollectionRepresentation(const OCRepresentation& rep, CollectionPresenceCallback callback)
+{
+    std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+
+/* //bug not found
+    if(rep.hasAttribute("name"))
+    {
+        std::cout << "\tRoom name: " << rep.getValue<std::string>("name") << std::endl;
+    }
+*/
+    std::vector<OCRepresentation> children = rep.getChildren();
+
+    for(auto oit = children.begin(); oit != children.end(); ++oit)
+    {
+        std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
+        std::vector<std::string> hostAddressVector = str_split(oit->getUri(), '/');
+        std::string hostAddress = "";
+        for(unsigned int i = 0 ; i  < hostAddressVector.size() ; ++i)
+        {
+            if(i < 3)
+            {
+                hostAddress.append(hostAddressVector.at(i));
+                if(i!=2)
+                {
+                    hostAddress.append("/");
+                }
+            }
+        }
+
+
+        std::vector<std::string> resourceTypes = oit->getResourceTypes();
+        for(unsigned int i = 0 ; i < resourceTypes.size() ; ++i)
+        {
+             std::cout << "\t\t\tresourcetype :" <<  resourceTypes.at(i) << std::endl;
+        }
+
+        std::string resourceType = "core.";
+        resourceType.append(str_split(oit->getUri(), '/').at(4));
+        std::cout << "\t\tconvertRT : " << resourceType << std::endl;
+        std::cout << "\t\thost : " << hostAddress << std::endl;
+        OCPlatform::OCPresenceHandle presenceHandle;
+        OCStackResult result = OCPlatform::subscribePresence(presenceHandle, hostAddress, resourceType ,
+            std::function< void(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)>
+                        (std::bind(&GroupManager::collectionPresenceHandler, this, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,hostAddress,oit->getUri())));
+
+        if(result == OC_STACK_OK)
+        {
+            std::cout << "\t\tOK!" << std::endl;
+            presenceCallbacks.insert(std::make_pair(oit->getUri(),callback));
+        }
+        else
+        {
+            callback("",OC_STACK_ERROR);
+        }
+
+    }
+}
+
+void GroupManager::onGetForPresence(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode, CollectionPresenceCallback callback)
+{
+    if (eCode == OC_STACK_OK)
+    {
+        std::cout << "GET request was successful" << std::endl;
+        std::cout << "Resource URI: " << rep.getUri() << std::endl;
+
+        checkCollectionRepresentation(rep,callback);
+
+    }
+    else
+    {
+        std::cout << "onGET Response error: " << eCode << std::endl;
+        callback("",OC_STACK_ERROR);
+        std::exit(-1);
+    }
+}
+
+OCStackResult GroupManager::subscribeCollectionPresence(std::shared_ptr< OCResource > collectionResource, CollectionPresenceCallback callback)
+{
+    OCStackResult result = OC_STACK_OK;
+    //callback("core.room",OC_STACK_OK);
+
+    QueryParamsMap queryParam;
+
+    //parameter 1 = resourceType
+    collectionResource->get("",DEFAULT_INTERFACE,queryParam,
+        std::function< void(const HeaderOptions& headerOptions,const OCRepresentation& rep,const int eCode)>
+                        (std::bind(&GroupManager::onGetForPresence, this, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3, callback)));
+
+    return result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+    Group Action
+*/
+
+std::string GroupManager::getStringFromActionSet(const ActionSet *newActionSet)
+{
+    std::string message = "";
+
+    message = newActionSet->actionsetName;
+    message.append("*");
+    for(auto iterAction= newActionSet->listOfAction.begin(); iterAction != newActionSet->listOfAction.end();
+        iterAction++)
+    {
+        message.append("uri=");
+        message.append((*iterAction)->target);
+        message.append("|");
+
+        for( auto iterCapa = (*iterAction)->listOfCapability.begin(); iterCapa != (*iterAction)->listOfCapability.end();
+            iterCapa++)
+        {
+            message.append((*iterCapa)->capability);
+            message.append("=");
+            message.append((*iterCapa)->status);
+
+            if( iterCapa + 1 != (*iterAction)->listOfCapability.end() )
+                message.append( "|");
+        }
+
+        if( iterAction + 1 !=  newActionSet->listOfAction.end())
+        {
+             message.append("*");
+        }
+    }
+
+    return message;
+}
+
+ActionSet* GroupManager::getActionSetfromString(std::string desc)
+{
+    char *acitonRequest;
+    char *iterTokenPtr = NULL;
+    char *iterToken = NULL;
+    char *description = NULL;
+    char *iterDescPtr = NULL;
+
+    char *attributes = NULL;
+    char *iterAttrbutesPtr = NULL;
+
+    char *attr = NULL;
+    char *iterAttrPtr = NULL;
+
+    std::string actionsetName;
+
+    ActionSet* actionset = NULL;
+    Action* action = NULL;
+
+    actionset = new ActionSet();
+
+    acitonRequest = new char[strlen((char *)desc.c_str() + 1)];
+    strncpy(acitonRequest, (char *)desc.c_str(), strlen((char *)desc.c_str()) + 1);
+
+    //printf("\t%s\n", acitonRequest);
+    if(acitonRequest != NULL)
+    {
+        iterToken = (char *)strtok_r(acitonRequest, DESC_DELIMITER, &iterTokenPtr);
+
+        while(iterToken != NULL)
+        {
+            if( strcmp(iterToken, "ActionSet") == 0)
+            {// if iterToken is ActionSet, will be created and added a new action set.
+                iterToken = (char *)strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);           // it is mean ':'.
+                iterToken = (char *)strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);           // it is body of action description.
+
+                description = new char[(strlen(iterToken) + 1)];
+                strncpy(description, iterToken, strlen(iterToken) + 1);
+
+                // Find the action name from description.
+                iterDescPtr = NULL;
+                iterToken = (char *)strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
+                //while(iterToken != NULL)
+                if(iterToken != NULL)
+                {
+                    //  Actionset name.
+                    actionsetName = std::string(iterToken);
+                    // printf("ACTION SET NAME :: %s\n", *actionsetName);
+                    iterToken = (char *)strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
+                } else {
+                    return NULL;
+
+                }// end Action Set Name.
+
+                // New ActionSet Add to OCResource's ActionSet list.
+                // 1. Allocate a new pointer for actionset.
+                actionset  = new ActionSet;
+                // 2. Initiate actionset.
+                actionset->actionsetName = std::string(actionsetName);
+                // printf("ACTION SET NAME :: %s\n", actionset->actionsetName);
+
+                while(iterToken != NULL)
+                {
+                    action = new Action;
+
+                    // printf("ATTR Copied :: %s\n", iterToken);
+                    attributes = new char[strlen(iterToken) + 1];
+                    strncpy(attributes, iterToken, strlen(iterToken) + 1);
+                    // printf("ATTR Copied :: %s\n", attributes);
+
+                    iterToken = (char *)strtok_r(attributes, ATTR_DELIMITER, &iterAttrbutesPtr);
+                    while(iterToken != NULL)
+                    {
+                        attr = new char[(strlen(iterToken) + 1)];
+                        strncpy(attr, iterToken, strlen(iterToken) + 1);
+
+                        iterToken = (char *)strtok_r(attr, "=",&iterAttrPtr);
+                        while(iterToken != NULL)
+                        {
+                            // Find the URI from description.
+                            if(strcmp(iterToken, "uri") == 0)
+                            {
+                                iterToken = (char *)strtok_r(NULL, "=", &iterAttrPtr);
+                                // printf("uri :: %s\n", iterToken);
+
+                                action->target =std::string(iterToken);
+                            } else {
+                                Capability* capa = new Capability();
+                                // printf("%s :: ", iterToken);
+                                capa->capability = std::string(iterToken);
+                                iterToken = (char *)strtok_r(NULL, "=", &iterAttrPtr);
+                                // printf("%s\n", iterToken);
+                                capa->status = std::string(iterToken);
+
+                                action->listOfCapability.push_back(capa);
+                            }
+
+                            iterToken = (char *)strtok_r(NULL, "=", &iterAttrPtr);
+                        }
+
+                        iterToken = (char *)strtok_r(NULL, ATTR_DELIMITER, &iterAttrbutesPtr);
+                    }// End of Action
+
+                    actionset->listOfAction.push_back(action);
+
+                    iterToken = (char *)strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
+                }
+
+                return actionset;
+            }
+            iterToken = (char *)strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);
+        }
+    }
+
+    return NULL;
+}
+
+OCStackResult GroupManager::addActionSet(std::shared_ptr< OCResource > resource, const ActionSet* newActionSet, PutCallback cb)
+{
+    // BUILD message of ActionSet which it is included delimiter.
+    std::string message = getStringFromActionSet(newActionSet);
+    OCRepresentation rep;
+
+    rep.setValue("ActionSet", message);
+
+    return resource->put(resource->getResourceTypes().front(),
+                        GROUP_INTERFACE, rep, QueryParamsMap(),
+                        cb );
+}
+
+
+OCStackResult GroupManager::executeActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb)
+{
+    OCRepresentation rep;
+
+    rep.setValue("DoAction", actionsetName);
+    return resource->post(resource->getResourceTypes().front(),
+                        GROUP_INTERFACE, rep, QueryParamsMap(),
+                        cb );
+}
+
+OCStackResult GroupManager::getActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, GetCallback cb)
+{
+    OCRepresentation rep;
+
+    rep.setValue("GetActionSet", actionsetName);
+
+    return resource->put(resource->getResourceTypes().front(),
+                        GROUP_INTERFACE, rep, QueryParamsMap(),
+                        cb );
+}
+
+
+OCStackResult GroupManager::deleteActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb)
+{
+    OCRepresentation rep;
+
+    rep.setValue("DelActionSet", actionsetName);
+
+    return resource->put(resource->getResourceTypes().front(),
+                        GROUP_INTERFACE, rep, QueryParamsMap(),
+                        cb );
+}
diff --git a/service/things-manager/sdk/src/GroupManager.h b/service/things-manager/sdk/src/GroupManager.h
new file mode 100755 (executable)
index 0000000..1fd399d
--- /dev/null
@@ -0,0 +1,149 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file   GroupManager.h
+
+/// @brief  This file contains the declaration of classes and its members related to TGMClient.
+
+#ifndef __OC_GROUPMANAGER__
+#define __OC_GROUPMANAGER__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+
+typedef std::function< void(std::vector< std::shared_ptr< OCResource > >) > CandidateCallback;
+typedef std::function< void(std::string, OCStackResult) > CollectionPresenceCallback;
+
+typedef std::function<void(const HeaderOptions&, const OCRepresentation&, const int)> GetCallback;
+typedef std::function<void(const HeaderOptions&, const OCRepresentation&, const int)> PostCallback;
+typedef std::function<void(const HeaderOptions&, const OCRepresentation&, const int)> PutCallback;
+
+
+class Capability
+{
+public:
+    std::string capability;
+    std::string status;
+};
+
+class Action
+{
+public:
+    Action() : target("")
+    {
+    }
+    ~Action()
+    {
+        listOfCapability.clear();
+    }
+    std::string target;
+
+    std::vector<Capability*> listOfCapability;
+};
+
+class ActionSet
+{
+public:
+    ActionSet() : actionsetName("")
+    {
+    }
+    ~ActionSet()
+    {
+        listOfAction.clear();
+    }
+    std::string actionsetName;
+
+    std::vector<Action*> listOfAction;
+};
+
+
+class GroupManager
+{
+public:
+    /**
+     * Constructor for TGMClient. Constructs a new TGMClient
+     */
+    GroupManager(void);
+
+    /**
+     * Virtual destructor
+     */
+    ~GroupManager(void);
+
+    /**
+     * API for candidate resources discovery.
+     * Callback only call when all resource types found.
+     *
+     * @param resourceTypes - required resource types(called "candidate")
+     * @param candidateCallback - callback. OCResource vector.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult findCandidateResources(std::vector< std::string > resourceTypes,
+            CandidateCallback callback, int waitsec = -1);
+
+    /**
+     * API for Collection member's state subscribe.
+     *
+     * NOTE: NOT IMPLEMENT YET
+     */
+    OCStackResult subscribeCollectionPresence(std::shared_ptr< OCResource > resource, CollectionPresenceCallback);
+
+private:
+
+    void onFoundResource(std::shared_ptr< OCResource > resource, int waitsec);
+    void findPreparedRequest(std::map< std::vector< std::string >, CandidateCallback > &request);
+    void lazyCallback(int second);
+
+    void onGetForPresence(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode,CollectionPresenceCallback callback);
+    void checkCollectionRepresentation(const OCRepresentation& rep, CollectionPresenceCallback callback);
+    void collectionPresenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress, std::string host, std::string uri);
+
+
+
+
+
+    /**
+    *   API for Collection(Group) action.
+    */
+
+public:
+    std::string getStringFromActionSet(const ActionSet *newActionSet);
+    ActionSet* getActionSetfromString(std::string desc);
+
+    OCStackResult addActionSet(std::shared_ptr< OCResource > resource, const ActionSet* newActionSet, PutCallback cb);
+    OCStackResult executeActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb);
+    OCStackResult getActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, GetCallback cb);
+    OCStackResult deleteActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback);
+};
+
+
+
+
+
+#endif  /* __OC_GROUPMANAGER__*/
diff --git a/service/things-manager/sdk/src/GroupSynchronization.cpp b/service/things-manager/sdk/src/GroupSynchronization.cpp
new file mode 100755 (executable)
index 0000000..fe74d18
--- /dev/null
@@ -0,0 +1,1229 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//a
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file    GroupSynchronizatin.cpp
+/// @brief
+
+#include "GroupSynchronization.h"
+
+using namespace OC;
+
+
+GroupSynchronization* GroupSynchronization::groupSyncnstance = NULL;
+
+
+GroupSynchronization* GroupSynchronization::getInstance ()
+{
+    if (groupSyncnstance == NULL)
+    {
+        groupSyncnstance = new GroupSynchronization();
+    }
+    return groupSyncnstance;
+}
+
+
+void GroupSynchronization::deleteInstance()
+{
+    if (groupSyncnstance)
+    {
+        delete groupSyncnstance;
+        groupSyncnstance = NULL;
+    }
+}
+
+
+
+OCStackResult GroupSynchronization::findGroup (std::vector<std::string> collectionResourceTypes, FindCallback resourceHandler)
+{
+    cout << "GroupSynchronization::findGroup" << endl;
+
+    foundGroupResourceList.clear();
+
+    findCallback = resourceHandler;
+
+    for (unsigned int i = 0; i < collectionResourceTypes.size(); ++i)
+    {
+        std::string query = "coap://224.0.1.187/oc/core?rt=";
+        query.append(collectionResourceTypes.at(i));
+        cout << "GroupSynchronization::findGroup - " << query << endl;
+
+        OCPlatform::findResource("", query,std::bind(&GroupSynchronization::onFindGroup, this, std::placeholders::_1));
+    }
+
+    // thread to check if GroupSynchronization::onFoundGroup is called or not.
+    std::thread t(std::bind(&GroupSynchronization::checkFindGroup, this));
+    t.detach();
+
+    return OC_STACK_OK;
+}
+
+
+OCStackResult GroupSynchronization::createGroup (std::string collectionResourceType)
+{
+    foundGroupResourceList.clear();
+
+    OCResourceHandle collectionResHandle = NULL;
+    OCResourceHandle groupSyncResHandle = NULL;
+
+    if (0 != collectionResourceType.length())
+    {
+        cout << "GroupSynchronization::createGroup - The created group is added." << endl;
+
+        OCStackResult result;
+
+/*        result = OCPlatform::startPresence (30);        // time is temporary
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::createGroup : startPresence was unsuccessful. result - " << result << endl;
+        }
+        else
+        {
+            cout << "GroupSynchronization::createGroup : startPresence" << endl;
+        }
+*/
+        // creating master collection resource
+        std::string collectionUri = "/" + collectionResourceType;
+        int i;
+        while ((i = collectionUri.find(".")) != std::string::npos)
+        {
+            collectionUri.replace (i, 1, "/");
+        }
+        cout << "GroupSynchronization::createGroup : collection uri - " << collectionUri << ", type - " << collectionResourceType << endl;
+
+        std::string resourceInterface = DEFAULT_INTERFACE;
+
+        result = OCPlatform::registerResource (collectionResHandle, collectionUri, collectionResourceType, resourceInterface, NULL, OC_DISCOVERABLE | OC_OBSERVABLE);
+        if (OC_STACK_OK != result)
+        {
+            cout << "Resource creation (" << collectionUri << ") was unsuccessful. result - " << result << endl;
+            goto Error;
+        }
+
+        collectionResourceHandleList[collectionResourceType] = collectionResHandle;
+
+        // creating master group sync resource
+        std::string groupSyncUri = collectionUri + "/groupsync";
+        std::string groupSyncResType = collectionResourceType + ".groupsync";
+
+        cout << "GroupSynchronization::createGroup : groupSync uri - " << groupSyncUri << ", type - " << collectionResourceType<< endl;
+
+        result = OCPlatform::registerResource (groupSyncResHandle, groupSyncUri, groupSyncResType, resourceInterface,
+                                                            std::bind(&GroupSynchronization::groupEntityHandler, this, std::placeholders::_1),
+                                                            OC_DISCOVERABLE | OC_OBSERVABLE);
+        if (OC_STACK_OK != result)
+        {
+            cout << "Resource creation (groupsync) was unsuccessful. result - " << result << endl;
+            goto Error;
+        }
+
+        groupSyncResourceHandleList[collectionResourceType] = groupSyncResHandle;
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        cout << "GroupSynchronization::createGroup : Error! Input params are wrong." << endl;
+        return OC_STACK_INVALID_PARAM;
+    }
+
+Error :
+
+    std::map<std::string, OCResourceHandle>::iterator It;
+    if (collectionResHandle)
+    {
+        OCPlatform::unregisterResource (collectionResHandle);
+        It = collectionResourceHandleList.find(collectionResourceType);
+        if (It != collectionResourceHandleList.end())
+        {
+            collectionResourceHandleList.erase(It);
+        }
+    }
+
+    if (groupSyncResHandle)
+    {
+        OCPlatform::unregisterResource (groupSyncResHandle);
+        It = groupSyncResourceHandleList.find(collectionResourceType);
+        if (It != groupSyncResourceHandleList.end())
+        {
+            groupSyncResourceHandleList.erase(It);
+        }
+    }
+
+    return OC_STACK_NO_RESOURCE;
+}
+
+
+OCStackResult GroupSynchronization::joinGroup (std::string collectionResourceType, OCResourceHandle resourceHandle)
+{
+    if ((0 != collectionResourceType.length()) && (resourceHandle))
+    {
+        std::map<std::string, OCResourceHandle>::iterator resIt = collectionResourceHandleList.find(collectionResourceType);
+        if (resIt == groupSyncResourceHandleList.end())
+        {
+            cout << "GroupSynchronization::joinGroup : error! There is no collection to join" << endl;
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCResourceHandle collectionResHandle = resIt->second;
+
+        OCStackResult result = OCPlatform::bindResource(collectionResHandle, resourceHandle);
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::joinGroup : Resource bind was unsuccessful. result - " << result << endl;
+            return OC_STACK_ERROR;
+        }
+        cout << "GroupSynchronization::joinGroup : binding collectionResHandle and resourceHandle" << endl;
+
+        std::vector<OCResourceHandle> childHandleList;
+
+        std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator childIt = childResourceHandleList.find(collectionResHandle);
+        if (childIt != childResourceHandleList.end())
+        {
+            childHandleList = childIt->second;
+        }
+
+        childHandleList.push_back(resourceHandle);
+        childResourceHandleList[collectionResHandle] = childHandleList;
+
+        deviceResourceHandleList.push_back(resourceHandle);
+
+        debugGroupSync();
+    }
+    else
+    {
+        cout << "GroupSynchronization::joinGroup : error! input params are wrong." << endl;
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return OC_STACK_OK;
+}
+
+
+
+OCStackResult GroupSynchronization::joinGroup (const std::shared_ptr<OCResource> resource, OCResourceHandle resourceHandle)
+{
+    if ((resource) && (resourceHandle))
+    {
+        cout << "GroupSynchronization::joinGroup" << endl;
+
+        // making representation to join group
+        std::string method = "joinGroup";
+        std::vector<std::string> type = resource->getResourceTypes();
+        std::string resourceType;
+        resourceType.append(OCGetResourceTypeName (resourceHandle, 0));
+
+        OCRepresentation rep;
+        rep.setValue("method", method);
+        rep.setValue("collectionResourceType", type[0]);
+        rep.setValue("resourceType", resourceType);
+
+        cout << "\tmethod - " << method << endl;
+        cout << "\tcollectionResourceType - " << type[0] << endl;
+        cout << "\tresourceType - " << resourceType << endl;
+
+        // creating group sync resource with the received collection resource. entity handler of group sync is used to join group.
+        std::string host = resource->host();
+        std::string uri = resource->uri() + "/groupsync";
+
+        std::vector<std::string> resourceTypes;
+        std::string temp;
+        for (unsigned int i = 0; i < type.size(); ++i)
+        {
+            temp = type[0] + ".groupsync";
+            resourceTypes.push_back(temp);
+        }
+
+        std::vector<std::string> resourceInterface;
+        resourceInterface.push_back (DEFAULT_INTERFACE);
+
+        OCResource::Ptr groupSyncResource = OCPlatform::constructResourceObject(host, uri, 1, resourceTypes, resourceInterface);
+        groupSyncResourceList[type[0]] = groupSyncResource;
+
+        cout << "GroupSynchronization::joinGroup : creating groupSyncResource." << endl;
+
+        // Create QueryParameters Map and add query params (if any)
+        QueryParamsMap queryParamsMap;
+
+        // request to join group to the remote group sync resource
+        OCStackResult result = groupSyncResource->put(rep, queryParamsMap, std::bind(&GroupSynchronization::onJoinGroup, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::joinGroup : groupSyncResource->put was unsuccessful. result - " << result << endl;
+        }
+        else
+        {
+            cout << "GroupSynchronization::joinGroup : groupSyncResource->put" << endl;
+        }
+
+        // saving the remote collection resource. It is used in onJoinGroup() and onGetJoinedRemoteChild().
+        remoteCollectionResource = resource;
+
+        // saving the resource handle to join. It is used in onGetJoinedRemoteChild()
+        deviceResourceHandle = resourceHandle;
+
+        return OC_STACK_OK;
+    }
+    else
+    {
+        cout << "GroupSynchronization::joinGroup : Error! Input params are wrong." << endl;
+        return OC_STACK_INVALID_PARAM;
+    }
+}
+
+
+OCStackResult GroupSynchronization::leaveGroup (std::string collectionResourceType, OCResourceHandle resourceHandle)
+{
+    if ((0 != collectionResourceType.length()) && (resourceHandle))
+    {
+        cout << "GroupSynchronization::leaveGroup : collectionResourceType - " << collectionResourceType << endl;
+
+        OCResourceHandle collectionResHandle;
+
+        std::map<std::string, OCResourceHandle>::iterator handleIt = groupSyncResourceHandleList.find(collectionResourceType);
+
+        // if groupSyncResourceHandleList has resourceType, this app created collection resource handle.
+        if (handleIt != groupSyncResourceHandleList.end())
+        {
+            handleIt = collectionResourceHandleList.find(collectionResourceType);
+            if (handleIt == collectionResourceHandleList.end())
+            {
+                cout << "GroupSynchronization::leaveGroup : Error! There is no collection resource handle to leave." << endl;
+                return OC_STACK_INVALID_PARAM;
+            }
+
+            collectionResHandle = handleIt->second;
+            cout << "GroupSynchronization::leaveGroup : collection handle uri - " << OCGetResourceUri(collectionResHandle)<< endl;
+
+            OCStackResult result = OCPlatform::unbindResource (collectionResHandle, resourceHandle);
+            if (OC_STACK_OK == result)
+            {
+                cout << "GroupSynchronization::leaveGroup : UnbindResource was successful." << endl;
+            }
+            else
+            {
+                cout << "GroupSynchronization::leaveGroup : UnbindResource was unsuccessful. result - " << result << endl;
+            }
+
+            std::vector<OCResourceHandle>::iterator It = std::find(deviceResourceHandleList.begin(), deviceResourceHandleList.end(), resourceHandle);
+            if (It == deviceResourceHandleList.end())    // there is no resource handle to find
+            {
+                result = OCPlatform::unregisterResource (resourceHandle);
+                if (OC_STACK_OK == result)
+                {
+                    cout << "GroupSynchronization::leaveGroup : UnregisterResource was successful." << endl;
+                }
+                else
+                {
+                    cout << "GroupSynchronization::leaveGroup : UnregisterResource was unsuccessful. result - " << result << endl;
+                }
+            }
+            else
+            {
+                cout << "GroupSynchronization::leaveGroup : This resource cannot be unregistered." << endl;
+                deviceResourceHandleList.erase(It);
+            }
+
+            std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator handleListIt = childResourceHandleList.find(collectionResHandle);
+            if (handleListIt == childResourceHandleList.end())
+            {
+                cout << "GroupSynchronization::leaveGroup : Error! There is no child resource list to delete." << endl;
+                return OC_STACK_INVALID_PARAM;
+            }
+
+            std::vector<OCResourceHandle> childList = handleListIt->second;
+            std::vector<OCResourceHandle>::iterator childIt = std::find(childList.begin(), childList.end(), resourceHandle);
+            if (childIt != childList.end())
+            {
+                cout << "GroupSynchronization::groupEntityHandler : Found! The resource to leave is found in the child resource handle list." << endl;
+                childList.erase(childIt);
+            }
+
+            childResourceHandleList[collectionResHandle] = childList;
+
+            debugGroupSync();
+        }
+        else    // requesting to unbind this resourceHandle to the remote collection resource
+        {
+            std::map<std::string, std::shared_ptr< OCResource>>::iterator resourceIt = groupSyncResourceList.find(collectionResourceType);
+
+            if (resourceIt == groupSyncResourceList.end())
+            {
+                cout << "GroupSynchronization::leaveGroup : Error! There is no collectin resource type to leave." << endl;
+                return OC_STACK_INVALID_PARAM;
+            }
+
+            std::shared_ptr< OCResource> resource = resourceIt->second;
+            cout << "GroupSynchronization::leaveGroup : group sync resource uri - " << resource->uri() << endl;
+
+            handleIt = collectionResourceHandleList.find(collectionResourceType);
+            if (handleIt == collectionResourceHandleList.end())
+            {
+                cout << "GroupSynchronization::leaveGroup : Error! There is no collection resource handle to leave." << endl;
+                return OC_STACK_INVALID_PARAM;
+            }
+
+            collectionResHandle = handleIt->second;
+
+            // making representation to leave group
+            std::string method = "leaveGroup";
+            std::string type = OCGetResourceTypeName(collectionResHandle,0);
+            std::string resourceType;
+            resourceType.append(OCGetResourceTypeName (resourceHandle, 0));
+
+            OCRepresentation rep;
+            rep.setValue("method", method);
+            rep.setValue("collectionResourceType", type);
+            rep.setValue("resourceType", resourceType);
+
+            cout << "\tmethod - " << method << endl;
+            cout << "\tcollectionResourceType - " << type << endl;
+            cout << "\tresourceType - " << resourceType << endl;
+
+            QueryParamsMap queryParamsMap;
+
+            // request to leave group to the remote group sync resource
+            OCStackResult result = resource->put(rep, queryParamsMap, std::bind(&GroupSynchronization::onLeaveGroup, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+            if (OC_STACK_OK == result)
+            {
+                cout << "GroupSynchronization::leaveGroup : groupSyncResource->put was successful." << endl;
+            }
+            else
+            {
+                cout << "GroupSynchronization::leaveGroup : groupSyncResource->put was unsuccessful. result - " << result << endl;
+            }
+
+            // deleting all remote resources. These are copied in onGetJoinedRemoteChild()
+            deleteGroup (collectionResourceType);
+        }
+    }
+    else
+    {
+        cout << "GroupSynchronization::leaveGroup : Error! Input params are wrong." << endl;
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return OC_STACK_OK;
+}
+
+
+void GroupSynchronization::deleteGroup (std::string collectionResourceType)
+{
+    cout << "GroupSynchronization::deleteGroup" << endl;
+
+    OCStackResult result;
+/*    result = OCPlatform::stopPresence();
+    if (OC_STACK_OK != result)
+    {
+        cout << "GroupSynchronization::leaveGroup : StopPresence was unsuccessful. result - " << result << endl;
+    }
+    else
+    {
+        cout << "GroupSynchronization::leaveGroup : StopPresence" << endl;
+    }
+*/
+    std::map<std::string, OCResourceHandle>::iterator handleIt = collectionResourceHandleList.find(collectionResourceType);
+    if (handleIt == collectionResourceHandleList.end())
+    {
+        cout << "GroupSynchronization::deleteGroup : Error! There is no collection resource handle to delete." << endl;
+        return;
+    }
+    OCResourceHandle collectionResHandle = handleIt->second;
+
+    collectionResourceHandleList.erase(handleIt);
+
+    std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator handleListIt = childResourceHandleList.find(collectionResHandle);
+    if (handleListIt == childResourceHandleList.end())
+    {
+        cout << "GroupSynchronization::deleteGroup : Error! There is no child resource list to delete." << endl;
+        return;
+    }
+    std::vector<OCResourceHandle> childList = handleListIt->second;
+
+    childResourceHandleList.erase(handleListIt);
+
+    result = OCPlatform::unbindResources (collectionResHandle, childList);
+    if (OC_STACK_OK == result)
+    {
+        cout << "GroupSynchronization::deleteGroup : UnbindResources was successful." << endl;
+    }
+    else
+    {
+        cout << "GroupSynchronization::deleteGroup : UnbindResources was unsuccessful. result - " << result << endl;
+    }
+
+    result = OCPlatform::unregisterResource (collectionResHandle);
+    if (OC_STACK_OK != result)
+    {
+        cout << "GroupSynchronization::deleteGroup : UnregisterResource(collection resource handle) was successful." << endl;
+    }
+    else
+    {
+        cout << "GroupSynchronization::deleteGroup : UnregisterResource(collection resource handle) was unsuccessful. result - " << result << endl;
+    }
+
+    OCResourceHandle resourceHandle;
+    std::vector<OCResourceHandle>::iterator It;
+
+    for (unsigned int i = 0; i < childList.size(); i++)
+    {
+        resourceHandle = childList.at(i);
+
+        It = std::find(deviceResourceHandleList.begin(), deviceResourceHandleList.end(), resourceHandle);
+        if (It != deviceResourceHandleList.end())    // find !!
+        {
+            cout << "GroupSynchronization::deleteGroup : This resource cannot be unregistered. uri - " << OCGetResourceUri(resourceHandle)<< endl;
+            deviceResourceHandleList.erase(It);
+        }
+        else
+        {
+            result = OCPlatform::unregisterResource (resourceHandle);
+            if (OC_STACK_OK == result)
+            {
+                cout << "GroupSynchronization::deleteGroup : UnregisterResource(" << i+1 <<") was successful." << endl;
+            }
+            else
+            {
+                cout << "GroupSynchronization::deleteGroup : UnregisterResource(" << i+1 <<") was unsuccessful. result - " << result << endl;
+            }
+        }
+    }
+
+    handleIt = groupSyncResourceHandleList.find(collectionResourceType);
+
+    // if groupSyncResourceHandleList has resourceType, group sync of this app created collection resource.
+    if (handleIt != groupSyncResourceHandleList.end())
+    {
+        resourceHandle = handleIt->second;    // group sync resource handle
+        result = OCPlatform::unregisterResource (resourceHandle);
+        if (OC_STACK_OK == result)
+        {
+            cout << "GroupSynchronization::deleteGroup : UnregisterResource(group sync resource handle) was successful." << endl;
+        }
+        else
+        {
+            cout << "GroupSynchronization::deleteGroup : UnregisterResource(group sync resource handle) was unsuccessful. result - " << result << endl;
+        }
+
+        groupSyncResourceHandleList.erase(handleIt);
+    }
+
+    std::map<std::string, std::shared_ptr< OCResource>>::iterator resourceIt = groupSyncResourceList.find(collectionResourceType);
+    if (resourceIt != groupSyncResourceList.end())
+    {
+        cout << "GroupSynchronization::deleteGroup : Since OCResource is share_ptr, only groupSyncResourceList is updated and OCResource is not deleted." << endl;
+        groupSyncResourceList.erase(resourceIt);
+    }
+
+    debugGroupSync();
+}
+
+
+std::map<std::string, OCResourceHandle> GroupSynchronization::getGroupList ()
+{
+    return collectionResourceHandleList;
+}
+
+
+OCEntityHandlerResult GroupSynchronization::groupEntityHandler(const std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "GroupSynchronization::groupEntityHandler\n";
+
+    if (request)
+    {
+        // Get the request type and request flag
+        std::string requestType = request->getRequestType();
+        int requestFlag = request->getRequestHandlerFlag();
+
+        if (requestFlag == RequestHandlerFlag::InitFlag)
+        {
+            cout << "\trequestFlag : Init\n";
+
+            // entity handler to perform resource initialization operations
+        }
+        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+        {
+            cout << "\trequestFlag : Request\n";
+
+            // If the request type is GET
+            if (requestType == "GET")
+            {
+                cout << "\t\trequestType : GET\n";
+            }
+            else if (requestType == "PUT")
+            {
+                cout << "\t\trequestType : PUT\n";
+
+                //get method name, group resource type and resource type to join group
+                OCRepresentation rp = request->getResourceRepresentation();
+                std::string methodType = rp.getValue<std::string>("method");
+                std::string collectionResourceType = rp.getValue<std::string>("collectionResourceType");
+                std::string resourceType = rp.getValue<std::string>("resourceType");
+
+                cout << "\t\t\tmethod : " << methodType << endl;
+                cout << "\t\t\tcollection resourceType : " << collectionResourceType << endl;
+                cout << "\t\t\tresourceType : " << resourceType << endl;
+
+                std::map<std::string, OCResourceHandle>::iterator handleIt = collectionResourceHandleList.find(collectionResourceType);
+                if (handleIt == collectionResourceHandleList.end())
+                {
+                    cout << "GroupSynchronization::groupEntityHandler : Error! There is no collection resource handle to delete." << endl;
+                    return OC_EH_ERROR;
+                }
+                collectionResourceHandle = handleIt->second;        // in case of join group it is used in onFindResource()
+
+                if (methodType == "joinGroup")
+                {
+                    std::string resourceName = "coap://224.0.1.187/oc/core?rt=";
+                    resourceName += resourceType;
+                    cout << "\t\t\tresourceName : " << resourceName << endl;
+
+                    resourceRequest = request;
+
+                    OCPlatform::findResource ("", resourceName, std::bind(&GroupSynchronization::onFindResource, this, std::placeholders::_1));
+                }
+                else if (methodType == "leaveGroup")
+                {
+                    std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator it = childResourceHandleList.find(collectionResourceHandle);
+                    if (it == childResourceHandleList.end())
+                    {
+                        cout << "GroupSynchronization::groupEntityHandler : Error! There is no child resource list." << endl;
+                        return OC_EH_ERROR;
+                    }
+
+                    std::vector<OCResourceHandle> childList = it->second;
+                    std::vector<OCResourceHandle>::iterator childIt;
+                    OCResourceHandle resourceHandle;
+                    for(childIt = childList.begin(); childIt != childList.end(); )
+                    {
+                        resourceHandle = (*childIt);
+                        char* type = (char*)OCGetResourceTypeName (resourceHandle, 0);
+
+                        if (0 == resourceType.compare(type))
+                        {
+                            cout << "GroupSynchronization::groupEntityHandler : Found! The resource to leave is found. - " << type << endl;
+
+                            childIt = childList.erase(childIt++);
+
+                            OCStackResult result = OCPlatform::unbindResource (collectionResourceHandle, resourceHandle);
+                            if (OC_STACK_OK == result)
+                            {
+                                cout << "GroupSynchronization::groupEntityHandler : UnbindResource was successful." << endl;
+                            }
+                            else
+                            {
+                                cout << "GroupSynchronization::groupEntityHandler : UnbindResource was unsuccessful. result - " << result << endl;
+                            }
+
+                            result = OCPlatform::unregisterResource (resourceHandle);
+                            if (OC_STACK_OK == result)
+                            {
+                                cout << "GroupSynchronization::groupEntityHandler : UnregisterResource was successful." << endl;
+                            }
+                            else
+                            {
+                                cout << "GroupSynchronization::groupEntityHandler : UnregisterResource was unsuccessful. result - " << result << endl;
+                            }
+
+//                            break;
+                        }
+                        else
+                        {
+                            ++childIt;
+                        }
+                    }
+
+                    childResourceHandleList[collectionResourceHandle] = childList;
+
+                    debugGroupSync();
+
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
+                    pResponse->setErrorCode(200);
+                    pResponse->setResponseResult(OC_EH_OK);
+
+                    OCRepresentation rep = request->getResourceRepresentation();
+                    pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        cout << "GroupSynchronization::groupEntityHandler : sendResponse is successful." << endl;
+                    }
+                }
+
+                if (methodType != "") //TODO: Check groupmethodtype NULL
+                {
+                }
+            }
+            else if (requestType == "POST")
+            {
+                // POST request operations
+            }
+            else if (requestType == "DELETE")
+            {
+                // DELETE request operations
+            }
+        }
+        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+        {
+            cout << "\trequestFlag : Observer\n";
+        }
+    }
+    else
+    {
+        std::cout << "Request invalid" << std::endl;
+    }
+
+    return OC_EH_OK;
+}
+
+
+void GroupSynchronization::onFindGroup(std::shared_ptr< OCResource > resource)
+{
+    cout << "GroupSynchronization::onFindGroup" << endl;
+
+    try
+    {
+        if (resource)
+        {
+//////////////////////////////////////////////////////////////////////////////////////////////////
+////////////debugging
+            std::string resourceURI;
+            std::string hostAddress;
+
+            // Get the resource URI
+            resourceURI = resource->uri();
+            cout << "\tURI of the resource: " << resourceURI << endl;
+
+            // Get the resource host address
+            hostAddress = resource->host();
+            cout << "\tHost address of the resource: " << hostAddress << endl;
+
+            hostAddress.append(resourceURI);
+
+            // Get the resource types
+            cout << "\tList of resource types: " << endl;
+
+            for (auto &resourceTypes : resource->getResourceTypes())
+            {
+                cout << "\t\t" << resourceTypes << endl;
+            }
+
+            // Get the resource interfaces
+            cout << "\tList of resource interfaces: " << endl;
+            for (auto &resourceInterfaces : resource->getResourceInterfaces())
+            {
+                cout << "\t\t" << resourceInterfaces << endl;
+            }
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+            if (false == IsSameGroup(resource))
+            {
+                saveGroup (resource);
+                findCallback (resource);
+            }
+        }
+        else
+        {
+            // Resource is invalid
+            cout << "Resource is invalid" << endl;
+            findCallback (NULL);
+        }
+
+    }
+    catch (std::exception& e)
+    {
+        //log(e.what());
+    }
+}
+
+
+void GroupSynchronization::checkFindGroup (void)
+{
+    cout << "GroupSynchronization::checkFindGroup" << endl;
+
+    for (int i = 0; i < 15; i++)
+    {
+        std::chrono::milliseconds workTime(300);
+        std::this_thread::sleep_for(workTime);
+
+        std::lock_guard<std::mutex> guard(foundGroupMutex);
+
+        if (false == foundGroupResourceList.empty())
+        {
+            cout << "GroupSynchronization::checkFoundGroup : Some group is received." << endl;
+            return;
+        }
+    }
+
+    cout << "GroupSynchronization::checkFoundGroup : It is failed to find resource within 3s." << endl;
+
+    onFindGroup (NULL);
+    return;
+}
+
+
+bool GroupSynchronization::IsSameGroup (std::shared_ptr< OCResource > resource)
+{
+    std::lock_guard<std::mutex> guard(foundGroupMutex);
+
+    if (true == foundGroupResourceList.empty())
+    {
+        cout << "GroupSynchronization::IsSameGroup : There is no found group." << endl;
+        return false;
+    }
+
+    std::string foundHostAddress, savedHostAddress;
+    foundHostAddress = resource->host();
+//    foundHostAddress.append (resource->uri());
+
+    for (unsigned int i = 0; i < foundGroupResourceList.size(); ++i)
+    {
+        savedHostAddress = (foundGroupResourceList.at(i))->host();
+//        savedHostAddress.append ((foundGroupResourceList.at(i))->uri());
+        cout << "GroupSynchronization::IsSameGroup : foundHostAddress - " << foundHostAddress << ", savedHostAddress - " << savedHostAddress << endl;
+
+        if (0 == foundHostAddress.compare(savedHostAddress.c_str()))
+        {
+            cout << "GroupSynchronization::IsSameGroup : Found! The same group is found." << endl;
+            return true;
+        }
+    }
+
+    cout << "GroupSynchronization::IsSameGroup :  There is no same group." << endl;
+    return false;
+}
+
+
+void GroupSynchronization::saveGroup (std::shared_ptr< OCResource > resource)
+{
+    cout << "GroupSynchronization::saveGroup" << endl;
+
+    std::lock_guard<std::mutex> guard(foundGroupMutex);
+
+    foundGroupResourceList.push_back(resource);
+}
+
+
+void GroupSynchronization::onJoinGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+{
+    if(eCode == OC_STACK_OK)
+    {
+        cout << "GroupSynchronization::onJoinGroup : " << endl;
+
+        if (remoteCollectionResource)
+        {
+            std::string resourceInterface = DEFAULT_INTERFACE;
+            QueryParamsMap queryParamsMap;
+
+            OCStackResult result = remoteCollectionResource->get("", resourceInterface, queryParamsMap,
+                                            std::bind(&GroupSynchronization::onGetJoinedRemoteChild, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+            if (OC_STACK_OK == result)
+            {
+                cout << "GroupSynchronization::onJoinGroup : remoteCollectionResource->get was successful." << endl;
+            }
+            else
+            {
+                cout << "GroupSynchronization::onJoinGroup : remoteCollectionResource->get was unsuccessful. result - " << result << endl;
+            }
+
+//            OCPlatform::OCPresenceHandle presenceHandle;
+//            std::vector<std::string> types = remoteCollectionResource->getResourceTypes();
+//            result = OCPlatform::subscribePresence (presenceHandle, remoteCollectionResource->host(), types[0],
+//                            std::function< void(OCStackResult result, const unsigned int nonce)>
+//                            (std::bind(&GroupSynchronization::onSubscribePresence, this, std::placeholders::_1, std::placeholders::_2/*, types[0], remoteCollectionResource->host()*/)));
+        }
+    }
+    else
+    {
+        cout << "GroupSynchronization::onJoinGroup : error - " << eCode << endl;
+    }
+}
+
+
+void GroupSynchronization::onFindResource (std::shared_ptr<OCResource> resource)
+{
+    cout << "GroupSynchronization::onFindResource" << endl;
+
+    if (resource)
+    {
+////////////////////////////////////////////////////////////////////////////////////////////////// 
+////////// debugging
+        std::string resourceURI;
+        std::string hostAddress;
+
+        // Get the resource URI
+        resourceURI = resource->uri();
+        cout << "\tURI of the resource: " << resourceURI << endl;
+
+        // Get the resource host address
+        hostAddress = resource->host();
+        cout << "\tHost address of the resource: " << hostAddress << endl;
+
+        hostAddress.append(resourceURI);
+
+        // Get the resource types
+        cout << "\tList of resource types: " << endl;
+
+        for (auto &resourceTypes : resource->getResourceTypes())
+        {
+            cout << "\t\t" << resourceTypes << endl;
+        }
+
+        // Get the resource interfaces
+        cout << "\tList of resource interfaces: " << endl;
+        for (auto &resourceInterfaces : resource->getResourceInterfaces())
+        {
+            cout << "\t\t" << resourceInterfaces << endl;
+        }
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+        OCResourceHandle resourceHandle;
+        OCStackResult result = OCPlatform::registerResource (resourceHandle, resource);
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::onFindResource - Resource to join creation was unsuccessful. result - " << result << endl;
+            return;
+        }
+        cout << "GroupSynchronization::onFindResource : creating resourceHandle. resource type - " << OCGetResourceTypeName (resourceHandle,0)<< endl;
+
+        result = OCPlatform::bindResource(collectionResourceHandle, resourceHandle);
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::onFindResource : Resource bind was unsuccessful. result - " << result << endl;
+            return;
+        }
+        cout << "GroupSynchronization::onFindResource : binding joinGroupHandle and resourceHandle" << endl;
+
+        std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator it = childResourceHandleList.find(collectionResourceHandle);
+        std::vector<OCResourceHandle> childHandleList;
+        if (it != childResourceHandleList.end())
+        {
+            childHandleList = it->second;
+        }
+
+        childHandleList.push_back(resourceHandle);
+        childResourceHandleList[collectionResourceHandle] = childHandleList;
+
+        auto pResponse = std::make_shared<OC::OCResourceResponse>();
+        pResponse->setRequestHandle(resourceRequest->getRequestHandle());
+        pResponse->setResourceHandle(resourceRequest->getResourceHandle());
+        pResponse->setErrorCode(200);
+        pResponse->setResponseResult(OC_EH_OK);
+
+        OCRepresentation rep = resourceRequest->getResourceRepresentation();
+        pResponse->setResourceRepresentation(rep, DEFAULT_INTERFACE);
+        if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+        {
+            cout << "GroupSynchronization::onFindResource : sendResponse is successful." << endl;
+        }
+    }
+    else
+    {
+        cout << "GroupSynchronization::onFindResource : Resource is invalid. So a new Group Resource has to be created." << endl;
+    }
+
+    debugGroupSync();
+}
+
+
+void GroupSynchronization::onGetJoinedRemoteChild(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+{
+    if(eCode == OC_STACK_OK)
+    {
+        cout << "GroupSynchronization::onGetJoinedRemoteChild" << endl;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+////////// debugging
+        std::string resourceURI;
+
+        // Get the resource URI
+        resourceURI = rep.getUri();
+        cout << "\tURI of the resource: " << resourceURI << endl;
+
+        // Get the resource types
+        cout << "\tList of resource types: " << endl;
+
+        for (auto &resourceTypes : rep.getResourceTypes())
+        {
+            cout << "\t\t" << resourceTypes << endl;
+        }
+
+        // Get the resource interfaces
+        cout << "\tList of resource interfaces: " << endl;
+        for (auto &resourceInterfaces : rep.getResourceInterfaces())
+        {
+            cout << "\t\t" << resourceInterfaces << endl;
+        }
+
+        std::vector<OCRepresentation> childList = rep.getChildren();
+        OCRepresentation child;
+        for (unsigned int i = 0; i < childList.size(); ++i)
+        {
+            cout << "\n\tchild resource - " << i+1 << endl;
+
+            child = childList.at(i);
+            resourceURI = child.getUri();
+            cout << "\t\tURI of the resource: " << resourceURI << endl;
+
+            cout << "\t\tList of resource types: " << endl;
+            for (auto &types : child.getResourceTypes())
+            {
+                cout << "\t\t\t" << types << endl;
+            }
+
+            cout << "\tList of resource interfaces: " << endl;
+            for (auto &interfaces : child.getResourceInterfaces())
+            {
+                cout << "\t\t\t" << interfaces << endl;
+            }
+        }
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+        // creating remote collection resource handle
+        OCResourceHandle remoteCollectionResourceHandle;
+        resourceURI = remoteCollectionResource->uri();
+        std::vector<std::string> types = remoteCollectionResource->getResourceTypes();
+        std::vector<std::string> interfaces = remoteCollectionResource->getResourceInterfaces();
+
+        OCStackResult result = OCPlatform::registerResource (remoteCollectionResourceHandle, resourceURI, types[0], interfaces[0], NULL, OC_OBSERVABLE);
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::onGetJoinedRemoteChild - remoteCollectionResourceHandle creation was unsuccessful. result - " << result << endl;
+            return;
+        }
+        cout << "GroupSynchronization::onGetJoinedRemoteChild : creating remoteCollectionResourceHandle" << endl;
+
+        // binding remote collection resource handle and resource handle to join
+        collectionResourceHandleList[types[0]] = remoteCollectionResourceHandle;
+
+        result = OCPlatform::bindResource(remoteCollectionResourceHandle, deviceResourceHandle);
+        if (OC_STACK_OK == result)
+        {
+            cout << "GroupSynchronization::onGetJoinedRemoteChild : binding remoteCollectionResourceHandle and deviceResourceHandle" << endl;
+        }
+        else
+        {
+            cout << "GroupSynchronization::onGetJoinedRemoteChild - binding remoteCollectionResourceHandle and deviceResourceHandle was unsuccessful. result - " << result << endl;
+        }
+
+        std::vector<OCResourceHandle> childHandleList;
+        childHandleList.push_back(deviceResourceHandle);
+        deviceResourceHandleList.push_back(deviceResourceHandle);
+
+        // binding copied remote collection resource handle and copied remote resource
+        OCResourceHandle resourceHandle;
+        for (unsigned int i = 0; i < childList.size(); ++i)
+        {
+            cout << "\tremote resource - " << i+1 << endl;
+
+            child = childList.at(i);
+            resourceURI = child.getUri();
+            types = child.getResourceTypes();
+            interfaces = child.getResourceInterfaces();
+
+            if (0 == types[0].compare(OCGetResourceTypeName (deviceResourceHandle,0)))
+            {
+                cout << "GroupSynchronization::onGetJoinedRemoteChild : " << types[0] << " is bind already." << endl;
+                continue;
+            }
+
+            result = OCPlatform::registerResource (resourceHandle, resourceURI, types[0], interfaces[0], NULL, OC_OBSERVABLE);
+            if (OC_STACK_OK == result)
+            {
+                result = OCPlatform::bindResource(remoteCollectionResourceHandle, resourceHandle);
+                if (OC_STACK_OK != result)
+                {
+                    cout << "GroupSynchronization::onGetJoinedRemoteChild - binding remoteCollectionResourceHandle and resourceHandle was unsuccessful. result - " << result << endl;
+                    OCPlatform::unregisterResource (resourceHandle);
+                }
+
+                childHandleList.push_back(resourceHandle);
+                cout << "GroupSynchronization::onGetJoinedRemoteChild : binding remoteCollectionResourceHandle and resourceHandle" << endl;
+            }
+            else
+            {
+                cout << "GroupSynchronization::onGetJoinedRemoteChild - remoteCollectionResourceHandle creation was unsuccessful. result - " << result << endl;
+            }
+        }
+
+        childResourceHandleList[remoteCollectionResourceHandle] = childHandleList;    // this handle list is used to leave group
+
+/*        OCPlatform::OCPresenceHandle presenceHandle;
+        types = remoteCollectionResource->getResourceTypes();
+        result = OCPlatform::subscribePresence (presenceHandle, remoteCollectionResource->host(), types[0],onSubscribePresence);
+        if (OC_STACK_OK != result)
+        {
+            cout << "GroupSynchronization::onGetJoinedRemoteChild : subscribePresence was unsuccessful. result - " << result << endl;
+        }
+        else
+        {
+            cout << "GroupSynchronization::onGetJoinedRemoteChild : subscribePresence. types - " << types[0] << endl;
+        }
+*/    }
+    else
+    {
+        cout << "GroupSynchronization::onGetJoinedRemoteChild : error - " << eCode << endl;
+    }
+
+    debugGroupSync();
+}
+
+
+void GroupSynchronization::onLeaveGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+{
+    if(eCode == OC_STACK_OK)
+    {
+        cout << "GroupSynchronization::onLeaveGroup" << endl;
+    }
+    else
+    {
+        cout << "GroupSynchronization::onLeaveGroup : error - " << eCode << endl;
+    }
+    debugGroupSync();
+}
+
+/*
+void onSubscribePresence (OCStackResult result, const unsigned int nonce, std::string resourceType, std::string host)
+{
+    cout << "GroupSynchronization::onSubscribePresence" << endl;
+
+//    std::cout << "resourceType : " << resourceType << std::endl;
+//    std::cout << "host : " << host << std::endl;
+    std::cout << "result : " << result << std::endl;
+
+    switch(result)
+    {
+        case OC_STACK_OK:
+            std::cout << "Nonce# " << nonce << std::endl;
+            break;
+        case OC_STACK_PRESENCE_STOPPED:
+            std::cout << "Presence Stopped\n";
+            break;
+        case OC_STACK_PRESENCE_DO_NOT_HANDLE:
+            std::cout << "Presence do not handle\n";
+            break;
+        case OC_STACK_PRESENCE_TIMEOUT:
+            std::cout << "Presence TIMEOUT\n";
+            break;
+        default:
+            std::cout << "Error\n";
+            break;
+    }
+}
+*/
+
+void GroupSynchronization::debugGroupSync (void)
+{
+    cout << "GroupSynchronization::debugGroupSync" << endl;
+
+    unsigned int i;
+    std::map<std::string, OCResourceHandle>::iterator handleIt;
+    std::map<OCResourceHandle, std::vector<OCResourceHandle>>::iterator childIt;
+    std::string type;
+    OCResourceHandle resourceHandle;
+    std::vector<OCResourceHandle> handleList;
+    std::shared_ptr< OCResource> resource;
+
+    cout << "Resource Handle Created by App" << endl;
+    for (i = 0; i < deviceResourceHandleList.size(); i++)
+    {
+        resourceHandle = deviceResourceHandleList.at(i);
+
+        cout << i+1 << ". details" << endl;
+        cout << "  uri - " << OCGetResourceUri (resourceHandle)<< endl;
+        cout << "  resource type - " << OCGetResourceTypeName (resourceHandle, 0) << endl;
+        cout << "  resource interface - " << OCGetResourceInterfaceName (resourceHandle, 0) << endl;
+        cout << "  resource property - " << OCGetResourceProperties (resourceHandle) << endl << endl;
+    }
+
+
+    cout << "The number of collection Resource Handle is " << collectionResourceHandleList.size() << endl;
+    cout << "The number of child resource handle list is " << childResourceHandleList.size() << endl;
+
+    cout << "Collection Resource Handle List" << endl;
+    i = 1;
+    for (handleIt = collectionResourceHandleList.begin(); handleIt != collectionResourceHandleList.end(); ++handleIt)
+    {
+        type = handleIt->first;
+        cout << "\t" << i << ". collection resource type - " << type << endl;
+        cout << "\t  details" << endl;
+
+        resourceHandle = handleIt->second;
+        cout << "\t  uri - " << OCGetResourceUri (resourceHandle)<< endl;
+        cout << "\t  resource type - " << OCGetResourceTypeName (resourceHandle, 0) << endl;
+        cout << "\t  resource interface - " << OCGetResourceInterfaceName (resourceHandle, 0) << endl;
+        cout << "\t  resource property - " << OCGetResourceProperties (resourceHandle) << endl << endl;
+
+        childIt = childResourceHandleList.find(resourceHandle);
+        if (childIt != childResourceHandleList.end())
+        {
+            handleList = childIt->second;
+            for (unsigned int j = 0; j < handleList.size(); j++)
+            {
+
+                cout << "\t\t" << j + 1 << ". child resource details" << endl;
+
+                resourceHandle = handleList.at(j);
+                cout << "\t\t  uri - " << OCGetResourceUri (resourceHandle)<< endl;
+                cout << "\t\t  resource type - " << OCGetResourceTypeName (resourceHandle, 0) << endl;
+                cout << "\t\t  resource interface - " << OCGetResourceInterfaceName (resourceHandle, 0) << endl;
+                cout << "\t\t  resource property - " << OCGetResourceProperties (resourceHandle) << endl << endl;
+            }
+        }
+
+        i++;
+    }
+
+    cout << "Group Sync Resource Handle List. The number is " << groupSyncResourceHandleList.size() << endl;
+    i = 1;
+    for (handleIt = groupSyncResourceHandleList.begin(); handleIt != groupSyncResourceHandleList.end(); ++handleIt)
+    {
+        type = handleIt->first;
+        cout << "\t" << i << ". group sync resource type - " << type << endl;
+        cout << "\t  details" << endl;
+
+        resourceHandle = handleIt->second;
+        cout << "\t  uri - " << OCGetResourceUri (resourceHandle)<< endl;
+        cout << "\t  resource type - " << OCGetResourceTypeName (resourceHandle, 0) << endl;
+        cout << "\t  resource interface - " << OCGetResourceInterfaceName (resourceHandle, 0) << endl;
+        cout << "\t  resource property - " << OCGetResourceProperties (resourceHandle) << endl << endl;;
+        i++;
+    }
+
+    cout << "Copied Remote Group Sync Resource List. The number is " << groupSyncResourceList.size() << endl;
+    std::map<std::string, std::shared_ptr< OCResource>>::iterator resourceIt;
+    std::vector<std::string> list;
+    i = 1;
+    for (resourceIt = groupSyncResourceList.begin(); resourceIt != groupSyncResourceList.end(); ++resourceIt)
+    {
+        type = resourceIt->first;
+        cout << "\t" << i << ". group sync resource type - " << type << endl;
+        cout << "\t details" << endl;
+
+        resource = resourceIt->second;
+        cout << "\t  host - " << resource->host() << endl;
+        cout << "\t  uri - " << resource->uri() << endl;
+        list = resource->getResourceTypes();
+        cout << "\t  resource type - " << list[0] << endl;
+        list = resource->getResourceInterfaces();
+        cout << "\t  resource interface - " << list[0] << endl << endl;
+        i++;
+    }
+}
\ No newline at end of file
diff --git a/service/things-manager/sdk/src/GroupSynchronization.h b/service/things-manager/sdk/src/GroupSynchronization.h
new file mode 100755 (executable)
index 0000000..5fe9745
--- /dev/null
@@ -0,0 +1,121 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file   GroupSynchronizatin.h
+
+/// @brief  This file contains the declaration of classes and its members related to GroupSynchronization.
+
+#ifndef __OC_GROUPSYNCHRONIZATION__
+#define __OC_GROUPSYNCHRONIZATION__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+
+class GroupSynchronization
+{
+private :
+
+    std::map<std::string, OCResourceHandle> collectionResourceHandleList;        // collection resource handle list
+
+    std::map<std::string, OCResourceHandle> groupSyncResourceHandleList;        // group sync resource handle list
+    std::map<std::string, std::shared_ptr< OCResource>> groupSyncResourceList;    // remote group sync resource list
+
+    std::vector<OCResourceHandle> deviceResourceHandleList;            // these cannot be removed.
+    OCResourceHandle deviceResourceHandle;
+
+    OCResourceHandle collectionResourceHandle;        // collection handle
+    std::shared_ptr< OCResource> remoteCollectionResource;
+
+    std::map<OCResourceHandle, std::vector<OCResourceHandle>> childResourceHandleList;
+
+    FindCallback findCallback;
+    std::vector<std::shared_ptr< OCResource >> foundGroupResourceList;
+
+    std::mutex foundGroupMutex;
+    std::mutex groupSyncMutex;
+
+    std::shared_ptr<OCResourceRequest> resourceRequest;        // this is used for slow response
+
+    static GroupSynchronization* groupSyncnstance;
+
+
+    GroupSynchronization ()
+    {
+        collectionResourceHandleList.clear();
+        groupSyncResourceHandleList.clear();
+        groupSyncResourceList.clear();
+        foundGroupResourceList.clear();
+        deviceResourceHandleList.clear();
+
+        deviceResourceHandle = NULL;
+        remoteCollectionResource = NULL;
+        findCallback = NULL;
+    };
+
+    ~GroupSynchronization ()
+    {
+        std::map<std::string, OCResourceHandle>::iterator handleIt;
+        for (handleIt = collectionResourceHandleList.begin(); handleIt != collectionResourceHandleList.end(); ++handleIt)
+        {
+            deleteGroup (handleIt->first);
+        }
+    };
+
+
+public :
+
+    static GroupSynchronization* getInstance ();
+    void deleteInstance();
+
+    OCStackResult findGroup (std::vector <std::string> collectionResourceTypes, FindCallback resourceHandler);
+    OCStackResult createGroup (std::string collectionResourceType);
+    OCStackResult joinGroup (std::string collectionResourceTyps, OCResourceHandle resourceHandle);
+    OCStackResult joinGroup (const std::shared_ptr<OCResource> resource, OCResourceHandle resourceHandle);
+    OCStackResult leaveGroup (std::string collectionResourceType, OCResourceHandle resourceHandle);
+    void deleteGroup (std::string collectionResourceType);
+
+    std::map<std::string, OCResourceHandle> getGroupList ();
+
+private : 
+
+    OCEntityHandlerResult groupEntityHandler(const std::shared_ptr<OCResourceRequest> request);
+
+    void onFindGroup(std::shared_ptr< OCResource > resource);
+    void onJoinGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode);
+    void onFindResource (std::shared_ptr<OCResource> resource);
+    void onGetJoinedRemoteChild(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode);
+    void onLeaveGroup(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode);
+//    void onSubscribePresence (OCStackResult result, const unsigned int nonce/*, std::string resourceType, std::string host*/);
+
+    void checkFindGroup (void);
+    bool IsSameGroup (std::shared_ptr< OCResource > resource);
+    void saveGroup (std::shared_ptr< OCResource > resource);
+
+    void debugGroupSync (void);
+
+};
+
+#endif    // __OC_GROUPSYNCHRONIZATION__
\ No newline at end of file
diff --git a/service/things-manager/sdk/src/TGMClient.cpp b/service/things-manager/sdk/src/TGMClient.cpp
deleted file mode 100644 (file)
index 7534a00..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/// @file    TGMClient.cpp
-///  @brief   
-
-#include "TGMClient.h"
-#include <algorithm>
-#include <thread>
-
-using namespace OC;
-
-std::map< std::vector< std::string >, CandidateCallback > candidateRequest;
-std::map< std::vector< std::string >, CandidateCallback > candidateRequestForTimer;
-std::map< std::string, std::map< std::string, std::shared_ptr< OCResource > > > rtForResourceList;
-std::vector< std::string > allFoundResourceTypes;
-
-template< typename T >
-bool IsSubset(std::vector< T > full, std::vector< T > sub)
-{
-    std::sort(full.begin(), full.end());
-    std::sort(sub.begin(), sub.end());
-    return std::includes(full.begin(), full.end(), sub.begin(), sub.end());
-}
-
-void TGMClient::onFoundResource(std::shared_ptr< OCResource > resource, int waitsec)
-{
-
-    std::string resourceURI;
-    std::string hostAddress;
-    try
-    {
-        // Do some operations with resource object.
-        if (resource)
-        {
-
-            std::cout << "DISCOVERED Resource:" << std::endl;
-            // Get the resource URI
-            resourceURI = resource->uri();
-            std::cout << "\tURI of the resource: " << resourceURI << std::endl;
-
-            // Get the resource host address
-            hostAddress = resource->host();
-            std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
-
-            // Get the resource types
-            std::cout << "\tList of resource types: " << std::endl;
-
-            hostAddress.append(resourceURI);
-
-            for (auto &resourceTypes : resource->getResourceTypes())
-            {
-                std::cout << "\t\t" << resourceTypes << std::endl;
-
-                if (std::find(allFoundResourceTypes.begin(), allFoundResourceTypes.end(),
-                        resourceTypes) == allFoundResourceTypes.end())
-                {
-                    allFoundResourceTypes.push_back(resourceTypes);
-                }
-
-                rtForResourceList[resourceTypes][hostAddress] = resource;
-            }
-
-            // Get the resource interfaces
-            std::cout << "\tList of resource interfaces: " << std::endl;
-            for (auto &resourceInterfaces : resource->getResourceInterfaces())
-            {
-                std::cout << "\t\t" << resourceInterfaces << std::endl;
-            }
-
-            if (waitsec == -1)
-            {
-                findPreparedRequest(candidateRequest);
-            }
-        }
-        else
-        {
-            // Resource is invalid
-            std::cout << "Resource is invalid" << std::endl;
-        }
-
-    }
-    catch (std::exception& e)
-    {
-        //log(e.what());
-    }
-}
-
-TGMClient::TGMClient(void)
-{
-    ;
-}
-
-/**
- * Virtual destructor
- */
-TGMClient::~TGMClient(void)
-{
-    candidateRequest.clear();
-    candidateRequestForTimer.clear();
-    rtForResourceList.clear();
-    allFoundResourceTypes.clear();
-}
-
-void TGMClient::findPreparedRequest(
-        std::map< std::vector< std::string >, CandidateCallback > &request)
-{
-    std::vector < std::shared_ptr < OCResource >> resources;
-
-    for (auto it = request.begin(); it != request.end();)
-    {
-
-        if (IsSubset(allFoundResourceTypes, it->first))
-        {
-            //std::cout << "IS SUBSET !!! \n";
-
-            for (unsigned int i = 0; i < it->first.size(); ++i)
-            {
-
-                for (auto secondIt = rtForResourceList[it->first.at(i)].begin();
-                        secondIt != rtForResourceList[it->first.at(i)].end(); ++secondIt)
-                {
-                    resources.push_back(secondIt->second);
-                }
-            }
-
-            it->second(resources);
-
-            //TODO : decide policy - callback only once 
-            request.erase(it++);
-        }
-        else
-        {
-            ++it;
-        }
-
-    }
-
-}
-
-void TGMClient::lazyCallback(int second)
-{
-    sleep(second);
-    findPreparedRequest(candidateRequestForTimer);
-
-}
-OCStackResult TGMClient::findCandidateResources(std::vector< std::string > resourceTypes,
-        CandidateCallback callback, int waitsec)
-{
-    if (resourceTypes.size() < 1)
-    {
-        return OC_STACK_ERROR;
-    }
-
-    std::sort(resourceTypes.begin(), resourceTypes.end());
-    resourceTypes.erase(std::unique(resourceTypes.begin(), resourceTypes.end()),
-            resourceTypes.end());
-
-    if (waitsec != -1)
-    {
-        candidateRequestForTimer.insert(std::make_pair(resourceTypes, callback));
-    }
-    else
-    {
-        candidateRequest.insert(std::make_pair(resourceTypes, callback));
-    }
-
-    for (unsigned int i = 0; i < resourceTypes.size(); ++i)
-    {
-        std::cout << "resourceTypes : " << resourceTypes.at(i) << std::endl;
-        std::string query = "coap://224.0.1.187/oc/core?rt=";
-        query.append(resourceTypes.at(i));
-        OCPlatform::findResource("", query.c_str(),
-                std::function < void(std::shared_ptr < OCResource > resource)
-                        > (std::bind(&TGMClient::onFoundResource, this, std::placeholders::_1,
-                                waitsec)));
-    }
-
-    if (waitsec != -1)
-    {
-        std::thread exec(
-                std::function< void(int second) >(
-                        std::bind(&TGMClient::lazyCallback, this, std::placeholders::_1)), waitsec);
-        exec.detach();
-    }
-
-    return OC_STACK_OK;
-}
diff --git a/service/things-manager/sdk/src/ThingsConfiguration.cpp b/service/things-manager/sdk/src/ThingsConfiguration.cpp
new file mode 100755 (executable)
index 0000000..829ed1d
--- /dev/null
@@ -0,0 +1,607 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file    ThingsConfiguration.cpp
+/// @brief
+
+#include <OCApi.h>
+#include <OCPlatform.h>
+#include <cstdlib>
+#include <algorithm>
+#include "ThingsConfiguration.h"
+
+using namespace OC;
+
+const int SUCCESS_RESPONSE = 0;
+int cnt = 0;
+
+std::map< std::string, ConfigurationRequestEntry > configurationRequestTable;
+
+ThingsConfiguration* ThingsConfiguration::thingsConfigurationInstance = NULL;
+
+ConfigurationCallback g_bootstrapCallback;
+
+ThingsConfiguration* ThingsConfiguration::getInstance()
+{
+    if (thingsConfigurationInstance == NULL)
+    {
+        thingsConfigurationInstance = new ThingsConfiguration();
+    }
+    return thingsConfigurationInstance;
+}
+
+void ThingsConfiguration::deleteInstance()
+{
+    if (thingsConfigurationInstance)
+    {
+        delete thingsConfigurationInstance;
+        thingsConfigurationInstance = NULL;
+    }
+}
+
+std::string ThingsConfiguration::getAttributeByConfigurationName(ConfigurationName name)
+{
+    for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
+    {
+        if ((*it).m_name == name)
+            return (*it).m_attribute;
+    }
+
+    return "";
+}
+
+std::string ThingsConfiguration::getUriByConfigurationName(ConfigurationName name)
+{
+    for (auto it = ConfigurationUnitTable.begin(); ConfigurationUnitTable.end() != it; it++)
+    {
+        if ((*it).m_name == name)
+            return (*it).m_uri;
+    }
+
+    return "";
+}
+
+std::string ThingsConfiguration::getUpdateVal(std::string conf)
+{
+    std::map< std::string, ConfigurationRequestEntry >::iterator it =
+            configurationRequestTable.find(conf);
+
+    if (it == configurationRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_updateVal;
+
+}
+std::shared_ptr< OCResource > ThingsConfiguration::getResource(std::string conf)
+{
+    std::map< std::string, ConfigurationRequestEntry >::iterator it =
+            configurationRequestTable.find(conf);
+
+    if (it == configurationRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_resource;
+}
+
+ConfigurationCallback ThingsConfiguration::getCallback(std::string conf)
+{
+    std::map< std::string, ConfigurationRequestEntry >::iterator it =
+            configurationRequestTable.find(conf);
+
+    if (it == configurationRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_callback;
+}
+
+std::string ThingsConfiguration::getListOfSupportedConfigurationUnits()
+{
+    std::string res;
+
+    res = "{\"Configuration Units\":[";
+
+    auto it = ConfigurationUnitTable.begin();
+    while (1)
+    {
+        res = res + (*it).getJSON();
+        it++;
+
+        if (it == ConfigurationUnitTable.end())
+            break;
+        else
+            res += ",";
+    }
+
+    res += "]}";
+
+    return res;
+}
+
+std::string ThingsConfiguration::getHostFromURI(std::string oldUri)
+{
+    size_t f;
+    std::string newUri;
+
+    if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
+        newUri = oldUri.replace(f, oldUri.size(), "");
+    else if ((f = oldUri.find("/oic/")) != string::npos)
+        newUri = oldUri.replace(f, oldUri.size(), "");
+
+    return newUri;
+}
+
+void ThingsConfiguration::onDeleteActionSet(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string conf)
+{
+    std::shared_ptr < OCResource > resource = getResource(conf);
+
+    std::cout << __func__ << std::endl;
+
+    if (resource)
+    {
+        QueryParamsMap query;
+
+        // After deletion of the left action set, find target child resource's URIs by sending GET
+        // message. Note that, this resource is surely a collection resource which has child
+        // resources.
+        resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsConfiguration::onGetChildInfoForUpdate, this,
+                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                                conf)));
+
+    }
+
+}
+
+void ThingsConfiguration::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "GET request was successful" << std::endl;
+
+        std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+
+        std::vector < OCRepresentation > children = rep.getChildren();
+        for (auto oit = children.begin(); oit != children.end(); ++oit)
+        {
+            std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
+        }
+
+        // Get information by using configuration name(conf)
+        std::shared_ptr < OCResource > resource = getResource(conf);
+        std::string actionstring = conf;
+        std::string uri = getUriByConfigurationName(conf);
+        std::string attr = getAttributeByConfigurationName(conf);
+
+        if (uri == "")
+            return;
+
+        if (resource)
+        {
+            // In this nest, we create a new action set of which name is the configuration name.
+            // Required information consists of a host address, URI, attribute key, and attribute
+            // value.
+            ActionSet *newActionSet = new ActionSet();
+            newActionSet->actionsetName = conf;
+
+            for (auto oit = children.begin(); oit != children.end(); ++oit)
+            {
+                Action *newAction = new Action();
+
+                // oit->getUri() includes a host address as well as URI.
+                // We should split these to each other and only use the host address to create
+                // a child resource's URI. Note that the collection resource and its child resource
+                // are located in same host.
+                newAction->target = getHostFromURI(oit->getUri()) + uri;
+
+                Capability *newCapability = new Capability();
+                newCapability->capability = attr;
+                newCapability->status = getUpdateVal(conf);
+
+                newAction->listOfCapability.push_back(newCapability);
+                newActionSet->listOfAction.push_back(newAction);
+            }
+
+            // Request to create a new action set by using the above actionSet
+            g_groupmanager->addActionSet(resource, newActionSet,
+                    std::function<
+                            void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                    const int eCode) >(
+                            std::bind(&ThingsConfiguration::onCreateActionSet, this,
+                                    std::placeholders::_1, std::placeholders::_2,
+                                    std::placeholders::_3, conf)));
+        }
+
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsConfiguration::onGetChildInfoForGet(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "GET request was successful" << std::endl;
+        std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+
+        std::shared_ptr< OCResource > resource, tempResource;
+        std::vector < std::shared_ptr < OCResource >> p_resources;
+        std::vector < std::string > m_if;
+        std::string uri = getUriByConfigurationName(conf);
+
+        if (uri == "")
+            return;
+
+        if (uri == "/oic/con" || uri == "/factoryset" || uri == "/factoryset/oic/con")
+            m_if.push_back(BATCH_INTERFACE);
+        else
+            m_if.push_back(DEFAULT_INTERFACE);
+
+        std::vector < OCRepresentation > children = rep.getChildren();
+        for (auto oit = children.begin(); oit != children.end(); ++oit)
+        {
+            std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
+
+            // Using a host address and child URIs, we can dynamically create resource objects.
+            // Note that, the child resources have not found before, we have no resource objects.
+            // For this reason, we create the resource objects.
+
+            std::string host = getHostFromURI(oit->getUri());
+            tempResource = OCPlatform::constructResourceObject(host, uri, true,
+                    oit->getResourceTypes(), m_if);
+
+            p_resources.push_back(tempResource);
+        }
+
+        // Send GET messages to the child resources in turn.
+        for (unsigned int i = 0; i < p_resources.size(); ++i)
+        {
+            resource = p_resources.at(i);
+            if (resource)
+            {
+                try
+                {
+                    if (isSimpleResource(resource))
+                    {
+                        QueryParamsMap test;
+                        resource->get(test, getCallback(conf));
+                    }
+                    else
+                    {
+                        QueryParamsMap test;
+                        resource->get(resource->getResourceTypes().at(0), BATCH_INTERFACE, test,
+                                getCallback(conf));
+                    }
+                }
+                catch (OCException& e)
+                {
+                    std::cout << e.reason() << std::endl;
+                }
+
+            }
+        }
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsConfiguration::onCreateActionSet(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        std::shared_ptr < OCResource > resource = getResource(conf);
+        if (resource)
+        {
+            // Now, it is time to execute the action set.
+            g_groupmanager->executeActionSet(resource, conf,
+                    std::function<
+                            void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                    const int eCode) >(
+                            std::bind(&ThingsConfiguration::onExecuteForGroupAction, this,
+                                    std::placeholders::_1, std::placeholders::_2,
+                                    std::placeholders::_3, conf)));
+        }
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsConfiguration::onExecuteForGroupAction(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        getCallback(conf)(headerOptions, rep, eCode);
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+bool ThingsConfiguration::isSimpleResource(std::shared_ptr< OCResource > resource)
+{
+    for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
+    {
+        if (resource->getResourceInterfaces().at(i) == BATCH_INTERFACE)
+            return false;
+    }
+    return true;
+}
+
+void ThingsConfiguration::onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+        const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "Get request was successful" << std::endl;
+
+        getCallback(conf)(headerOptions, rep, eCode);
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsConfiguration::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+        const int eCode, std::string conf)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        // Callback
+        getCallback(conf)(headerOptions, rep, eCode);
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+OCStackResult ThingsConfiguration::updateConfigurations(std::shared_ptr< OCResource > resource,
+        std::map< ConfigurationName, ConfigurationValue > configurations,
+        ConfigurationCallback callback)
+{
+    // For M2, # of configurations is 1
+    // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
+    if (configurations.size() == 0)
+    {
+        std::cout << "# of request configuration is 0" << std::endl;
+        return OC_STACK_ERROR;
+    }
+
+    if (!resource)
+    {
+        std::cout << "resource is NULL\n";
+        return OC_STACK_ERROR;
+    }
+
+    std::map< ConfigurationName, ConfigurationValue >::iterator it = configurations.begin();
+    std::string conf = it->first; // configuration name
+    std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
+
+    // Check the request queue if a previous request is still left. If so, remove it.
+    std::map< std::string, ConfigurationRequestEntry >::iterator iter =
+            configurationRequestTable.find(conf);
+    if (iter != configurationRequestTable.end())
+        configurationRequestTable.erase(iter);
+
+    // Create new request entry stored in the queue
+    ConfigurationRequestEntry newCallback(conf, callback, resource, it->second);
+    configurationRequestTable.insert(std::make_pair(conf, newCallback));
+
+    OCRepresentation rep;
+    QueryParamsMap query;
+    if (isSimpleResource(resource))
+    {
+        // This resource does not need to use a group manager. Just send a PUT message
+        rep.setValue(getAttributeByConfigurationName(conf), getUpdateVal(conf));
+        return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
+                                std::placeholders::_2, std::placeholders::_3, conf)));
+    }
+    else
+    {
+        // This resource is a collection resource which uses group manager functionalities.
+        // First, delete an existing action set of which name is same as a current action set name.
+        // As of now, the name is determined by "Configuration Name" which a user just specifies.
+        return g_groupmanager->deleteActionSet(resource, conf,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsConfiguration::onDeleteActionSet, this,
+                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                                conf)));
+    }
+}
+
+OCStackResult ThingsConfiguration::getConfigurations(std::shared_ptr< OCResource > resource,
+        std::vector< ConfigurationName > configurations, ConfigurationCallback callback)
+{
+    // For M2, # of configurations is 1
+    // First, mapping a semantic name(ConfigurationUnit) into resource's name(uri ...)
+    if (configurations.size() == 0)
+    {
+        std::cout << "# of request configuration is 0" << std::endl;
+        return OC_STACK_ERROR;
+    }
+    if (!resource)
+    {
+        std::cout << "resource is NULL\n";
+        return OC_STACK_ERROR;
+    }
+
+    std::vector< ConfigurationName >::iterator it = configurations.begin();
+    std::string conf = (*it); // configuration name
+    std::transform(conf.begin(), conf.end(), conf.begin(), ::tolower); // to lower case
+
+    // Check the request queue if a previous request is still left. If so, remove it.
+    std::map< std::string, ConfigurationRequestEntry >::iterator iter =
+            configurationRequestTable.find(conf);
+    if (iter != configurationRequestTable.end())
+        configurationRequestTable.erase(iter);
+
+    // Create new request entry stored in the queue
+    ConfigurationRequestEntry newCallback(conf, callback, resource, conf);
+    configurationRequestTable.insert(std::make_pair(conf, newCallback));
+
+    QueryParamsMap query;
+    OCRepresentation rep;
+
+    if (isSimpleResource(resource))
+    {
+        // This resource is a simple resource. Just send a PUT message
+        return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsConfiguration::onGet, this, std::placeholders::_1,
+                                std::placeholders::_2, std::placeholders::_3, conf)));
+    }
+    else
+    {
+        // This resource is a collection resource. On the contrary of a update, it does not use
+        // group manager functionality. It just acquires child resource's URI and send GET massages
+        // to the child resources in turn.
+        // First, request the child resources's URI.
+        return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsConfiguration::onGetChildInfoForGet, this,
+                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                                conf)));
+    }
+
+}
+
+// callback handler on GET request
+void ThingsConfiguration::onGetBootstrapInformation(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode)
+{
+    if(eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "GET request was successful" << std::endl;
+
+        std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+        g_bootstrapCallback(headerOptions, rep,  eCode);
+    }
+
+    else
+    {
+        std::cout << "onGET Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsConfiguration::onFoundBootstrapServer(std::vector< std::shared_ptr< OCResource > > resources)
+{
+    std::string resourceURI;
+    std::string hostAddress;
+
+    try
+    {
+        // Do some operations with resource object.
+        for (unsigned int i = 0; i < resources.size(); ++i)
+        {
+            std::shared_ptr < OCResource > resource = resources.at(i);
+
+            if (resource)
+            {
+                std::cout << "DISCOVERED Resource:" << std::endl;
+                // Get the resource URI
+                resourceURI = resource->uri();
+                std::cout << "\tURI of the resource: " << resourceURI << std::endl;
+
+                // Get the resource host address
+                hostAddress = resource->host();
+                std::cout << "\tHost address of the resource: " << hostAddress << std::endl;
+
+                // Get the resource types
+                std::cout << "\tList of resource types: " << std::endl;
+                for (auto &resourceTypes : resource->getResourceTypes())
+                {
+                    std::cout << "\t\t" << resourceTypes << std::endl;
+                }
+
+                // Get the resource interfaces
+                cout << "\tList of resource interfaces: " << endl;
+                for (auto &resourceInterfaces : resource->getResourceInterfaces())
+                {
+                    cout << "\t\t" << resourceInterfaces << endl;
+                }
+
+                // Request configuration resources
+                std::cout << "Getting bootstrap server representation on: "<< DEFAULT_INTERFACE << std::endl;
+
+                resource->get("bootstrap", DEFAULT_INTERFACE, QueryParamsMap(), &onGetBootstrapInformation);
+
+            }
+            else
+            {
+                // Resource is invalid
+                std::cout << "Resource is invalid" << std::endl;
+            }
+        }
+
+    }
+    catch (std::exception& e)
+    {
+        //log(e.what());
+    }
+}
+
+OCStackResult ThingsConfiguration::doBootstrap(ConfigurationCallback callback)
+{
+    g_bootstrapCallback = callback;
+
+    // Find bootstrap server.
+    std::vector<std::string> type;
+    type.push_back("bootstrap");
+
+    std::cout << "Finding Bootstrap Server resource... " << std::endl;
+    return g_groupmanager->findCandidateResources(type, &onFoundBootstrapServer);
+}
diff --git a/service/things-manager/sdk/src/ThingsConfiguration.h b/service/things-manager/sdk/src/ThingsConfiguration.h
new file mode 100755 (executable)
index 0000000..c5e67b4
--- /dev/null
@@ -0,0 +1,275 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file   ThingsConfiguration.h
+
+/// @brief  This file contains the declaration of classes and its members related to
+///         ThingsConfiguration.
+
+#ifndef __OC_THINGSCONFIGURATION__
+#define __OC_THINGSCONFIGURATION__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include "GroupManager.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+
+/// Declearation of Configuation Callback funtion type
+typedef std::function<
+        void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > ConfigurationCallback;
+
+typedef std::string ConfigurationName;
+typedef std::string ConfigurationValue;
+
+/**
+ * @brief
+ * The following class is used as a item stacking in request queue. The class stores a request and
+ * referential information (e.g., a configuration name, a target resource object, a callback functi-
+ * on passed from the applications, and a update value). When the function for updating/getting
+ * configuration value is called from applications, this class instance is created and stored in the
+ * request queue. The queue is maintained in a std::map structure so if desiring to find a specific
+ * request, you can find it by querying a configuration name.
+ */
+class ConfigurationRequestEntry
+{
+public:
+    ConfigurationRequestEntry(std::string ID, ConfigurationCallback callback,
+            std::shared_ptr< OCResource > resource, std::string updateVal) :
+            m_ID(ID), m_callback(callback), m_resource(resource), m_updateVal(updateVal)
+    {
+    }
+    ;
+
+    // Configuration Name (used in key value in std::map structure)
+    // e.g., time, network, security, and so on
+    std::string m_ID;
+
+    // Reference callback pointer
+    ConfigurationCallback m_callback;
+
+    // Reference resource object
+    std::shared_ptr< OCResource > m_resource;
+
+    // Update value only used for configuration update
+    std::string m_updateVal;
+};
+
+/**
+ * @brief
+ * The following class is used to store providing configuration name and its relevant information
+ * The relevant information includes a brief description, uri, and attribute key.
+ * Note that a developer only specifies a configuration name, not URI nor attribute key, to
+ * update/get a value to a remote. Thus, using configuration name, we convert it to more specific
+ * information (i.e. uri and attribute key) to send a request. This class is reponsible to storing
+ * these information.
+ */
+class ConfigurationUnitInfo
+{
+public:
+
+    std::string m_name;
+    std::string m_description;
+    std::string m_uri;
+    std::string m_attribute;
+
+    ConfigurationUnitInfo(std::string name, std::string description, std::string uri,
+            std::string attribute) :
+            m_name(name), m_description(description), m_uri(uri), m_attribute(attribute)
+    {
+    }
+    ;
+
+    // If a developer wants to know a list of configuration names, gives it in JSON format.
+    std::string getJSON()
+    {
+        std::string res;
+
+        res = "{\"name\":\"" + m_name + "\",\"description\":\"" + m_description + "\"}";
+
+        return res;
+    }
+};
+
+#define NUMCONFUNIT 6
+typedef std::string ConfigurationName;
+typedef std::string ConfigurationValue;
+
+class ThingsConfiguration
+{
+public:
+    /**
+     * Constructor for ThingsConfiguration. Constructs a new ThingsConfiguration
+     */
+    ThingsConfiguration(void)
+    {
+        ConfigurationUnitInfo unit[] =
+        {
+        { "installedlocation", "the semantic location at a specific area (e.g., living room)",
+                "/oic/con", "installedLocation" },
+        { "time", "Resource for system time information including time zones etc.", "/oic/time",
+                "currentTime" },
+        { "network", "Resource for network information", "/oic/net", "address" },
+        { "security", "Resource for security information (credentials, access control list etc.)",
+                "/oic/sec", "mode" },
+        { "setattr1", "attribute 1 of Set Resource", "/oic/customset", "attr1" },
+        { "getfactoryset", "get all default configuration value", "/factoryset/oic/con", "" } };
+
+        for (int i = 0; i < NUMCONFUNIT; i++)
+            ConfigurationUnitTable.push_back(unit[i]);
+    }
+    ;
+
+    /**
+     * Virtual destructor
+     */
+    ~ThingsConfiguration(void)
+    {
+    }
+    ;
+
+    static ThingsConfiguration *thingsConfigurationInstance;
+    static ThingsConfiguration* getInstance();
+    void deleteInstance();
+
+    void setGroupManager(GroupManager *groupmanager)
+    {
+        g_groupmanager = groupmanager;
+    }
+    ;
+
+    /**
+     * @brief
+     * API for updating configuration value of multiple things of a target group or a single thing.
+     * Callback is called when a response arrives.
+     * Before using the below function, a developer should acquire a resource pointer of
+     * (collection) resource that he want to send a request by calling findResource() function
+     * provided in OCPlatform. And he should also notice a "Configuration Name" term which
+     * represents a nickname of a target attribute of a resource that he wants to update.
+     * The base motivation to introduce the term is to avoid a usage of URI to access a resource
+     * from a developer. Thus, a developer should know which configuration names are supported
+     * by Things Configuration class and what the configuration name means.
+     * To get a list of supported configuration names, use getListOfSupportedConfigurationUnits()
+     * function, which provides the list in JSON format.
+     * NOTICE: A series of callback functions is called from updateConfigurations() function:
+     * (1) For a collection resource
+     * updateConfiguration()->onDeleteActionSet()->onGetChildInfoForUpdate()->onCreateActionSet()
+     * ->...(CoAP msg. is transmitted)->OnExecuteForGroupAction()->callback function in APP.
+     * (2) For a simple resource
+     * updateConfiguration()->...(CoAP msg. is transmitted)->OnPut()->callback function in APP.
+     *
+     * @param resource - resource pointer representing the target group or the single thing.
+     * @param configurations - ConfigurationUnit: a nickname of attribute of target resource
+     *                         (e.g., installedlocation, currency, (IP)address)
+     *                         Value : a value to be updated
+     * @param callback - callback.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult updateConfigurations(std::shared_ptr< OCResource > resource,
+            std::map< ConfigurationName, ConfigurationValue > configurations,
+            ConfigurationCallback callback);
+
+    /**
+     * API for getting configuration value of multiple things of a target group or a single thing.
+     * Callback is called when a response arrives.
+     * NOTICE: A series of callback functions is called from getConfigurations() function:
+     * (1) For a collection resource
+     * getConfigurations()->onGetChildInfoForGet()->...(CoAP msg. is transmitted)
+     * ->callback function in APP.
+     * (2) For a simple resource
+     * getConfigurations()->...(CoAP msg. is transmitted)->onGet()->callback function in APP.
+     *
+     * @param resource - resource pointer representing the target group or the single thing.
+     * @param configurations - ConfigurationUnit: a nickname of attribute of target resource.
+     * @param callback - callback.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult getConfigurations(std::shared_ptr< OCResource > resource,
+            std::vector< ConfigurationName > configurations, ConfigurationCallback callback);
+
+    /**
+     * API to show a list of supported configuration units (configurable parameters)
+     * Callback call when a response arrives.
+     *
+     * @return the list in JSON format
+     */
+    std::string getListOfSupportedConfigurationUnits();
+
+    /**
+     * API for bootstrapping functionality. Find a bootstrap server and get configuration
+     * information from the bootstrap server. With the information, make a configuration resource.
+     *
+     * @param callback - callback.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult doBootstrap(ConfigurationCallback callback);
+
+private:
+
+    GroupManager *g_groupmanager;
+
+    std::vector< ConfigurationUnitInfo > ConfigurationUnitTable;
+
+    void onExecuteForGroupAction(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGetChildInfoForUpdate(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGetChildInfoForGet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onCreateActionSet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGetActionSet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onDeleteActionSet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode,
+            std::string conf);
+    void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode,
+            std::string conf);
+    static void onFoundBootstrapServer(std::vector< std::shared_ptr< OCResource > > resources);
+    static void onGetBootstrapInformation(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode);
+
+    std::shared_ptr< OCResource > getResource(std::string conf);
+    ConfigurationCallback getCallback(std::string conf);
+    std::string getUpdateVal(std::string conf);
+    std::string getAttributeByConfigurationName(ConfigurationName name);
+    std::string getUriByConfigurationName(ConfigurationName name);
+
+    std::string getHostFromURI(std::string oldUri);
+
+    bool isSimpleResource(std::shared_ptr< OCResource > resource);
+
+};
+
+#endif  /* __OC_THINGSCONFIGURATION__*/
+
diff --git a/service/things-manager/sdk/src/ThingsDiagnostics.cpp b/service/things-manager/sdk/src/ThingsDiagnostics.cpp
new file mode 100755 (executable)
index 0000000..03bd998
--- /dev/null
@@ -0,0 +1,391 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file    ThingsDiagnostics.cpp
+///  @brief
+
+#include <OCApi.h>
+#include <OCPlatform.h>
+#include <cstdlib>
+
+#include "ThingsDiagnostics.h"
+
+using namespace OC;
+
+const int SUCCESS_RESPONSE = 0;
+
+std::map< std::string, DiagnosticsRequestEntry > diagnosticsRequestTable;
+
+ThingsDiagnostics* ThingsDiagnostics::thingsDiagnosticsInstance = NULL;
+
+ThingsDiagnostics* ThingsDiagnostics::getInstance()
+{
+    if (thingsDiagnosticsInstance == NULL)
+    {
+        thingsDiagnosticsInstance = new ThingsDiagnostics();
+    }
+    return thingsDiagnosticsInstance;
+}
+
+void ThingsDiagnostics::deleteInstance()
+{
+    if (thingsDiagnosticsInstance)
+    {
+        delete thingsDiagnosticsInstance;
+        thingsDiagnosticsInstance = NULL;
+    }
+}
+
+std::string ThingsDiagnostics::getAttributeByDiagnosticsName(DiagnosticsName name)
+{
+    for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
+    {
+        if ((*it).m_name == name)
+            return (*it).m_attribute;
+    }
+
+    return "";
+}
+
+std::string ThingsDiagnostics::getUriByDiagnosticsName(DiagnosticsName name)
+{
+    for (auto it = DiagnosticsUnitTable.begin(); DiagnosticsUnitTable.end() != it; it++)
+    {
+        if ((*it).m_name == name)
+            return (*it).m_uri;
+    }
+
+    return "";
+}
+
+std::string ThingsDiagnostics::getUpdateVal(std::string diag)
+{
+    std::map< std::string, DiagnosticsRequestEntry >::iterator it = diagnosticsRequestTable.find(
+            diag);
+
+    if (it == diagnosticsRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_updateVal;
+
+}
+std::shared_ptr< OCResource > ThingsDiagnostics::getResource(std::string diag)
+{
+    std::map< std::string, DiagnosticsRequestEntry >::iterator it = diagnosticsRequestTable.find(
+            diag);
+
+    if (it == diagnosticsRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_resource;
+}
+
+DiagnosticsCallback ThingsDiagnostics::getCallback(std::string diag)
+{
+    std::map< std::string, DiagnosticsRequestEntry >::iterator it = diagnosticsRequestTable.find(
+            diag);
+
+    if (it == diagnosticsRequestTable.end())
+        return NULL;
+    else
+        return it->second.m_callback;
+}
+
+std::string ThingsDiagnostics::getHostFromURI(std::string oldUri)
+{
+    size_t f;
+    std::string newUri;
+
+    if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
+        newUri = oldUri.replace(f, oldUri.size(), "");
+    else if ((f = oldUri.find("/oic/")) != string::npos)
+        newUri = oldUri.replace(f, oldUri.size(), "");
+
+    return newUri;
+}
+
+std::string ThingsDiagnostics::getListOfSupportedDiagnosticsUnits()
+{
+    std::string res;
+
+    res = "{\"Diagnostics Units\":[";
+
+    auto it = DiagnosticsUnitTable.begin();
+    while (1)
+    {
+        res = res + (*it).getJSON();
+        it++;
+
+        if (it == DiagnosticsUnitTable.end())
+            break;
+        else
+            res += ",";
+    }
+
+    res += "]}";
+
+    return res;
+}
+
+void ThingsDiagnostics::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string diag)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "GET request was successful" << std::endl;
+
+        std::cout << "\tResource URI: " << rep.getUri() << std::endl;
+
+        std::vector < OCRepresentation > children = rep.getChildren();
+        for (auto oit = children.begin(); oit != children.end(); ++oit)
+        {
+            std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
+        }
+
+        // Get information by using diagnostics name(diag)
+        std::shared_ptr < OCResource > resource = getResource(diag);
+        std::string actionstring = diag;
+        std::string uri = getUriByDiagnosticsName(diag);
+        std::string attr = getAttributeByDiagnosticsName(diag);
+
+        if (uri == "")
+            return;
+
+        if (resource)
+        {
+            // In this nest, we create a new action set of which name is the dignostics name.
+            // Required information consists of a host address, URI, attribute key, and attribute
+            // value.
+            ActionSet *newActionSet = new ActionSet();
+            newActionSet->actionsetName = diag;
+
+            for (auto oit = children.begin(); oit != children.end(); ++oit)
+            {
+                Action *newAction = new Action();
+
+                // oit->getUri() includes a host address as well as URI.
+                // We should split these to each other and only use the host address to create
+                // a child resource's URI. Note that the collection resource and its child resource
+                // are located in same host.
+                newAction->target = getHostFromURI(oit->getUri()) + uri;
+
+                Capability *newCapability = new Capability();
+                newCapability->capability = attr;
+                newCapability->status = getUpdateVal(diag);
+
+                newAction->listOfCapability.push_back(newCapability);
+                newActionSet->listOfAction.push_back(newAction);
+            }
+
+            // Request to create a new action set by using the above actionSet
+            g_groupmanager->addActionSet(resource, newActionSet,
+                    std::function<
+                            void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                    const int eCode) >(
+                            std::bind(&ThingsDiagnostics::onCreateActionSet, this,
+                                    std::placeholders::_1, std::placeholders::_2,
+                                    std::placeholders::_3, diag)));
+
+        }
+
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsDiagnostics::onCreateActionSet(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string diag)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        std::shared_ptr < OCResource > resource = getResource(diag);
+        if (resource)
+        {
+            // Now, it is time to execute the action set.
+            g_groupmanager->executeActionSet(resource, diag,
+                    std::function<
+                            void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                    const int eCode) >(
+                            std::bind(&ThingsDiagnostics::onExecuteForGroupAction, this,
+                                    std::placeholders::_1, std::placeholders::_2,
+                                    std::placeholders::_3, diag)));
+        }
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsDiagnostics::onExecuteForGroupAction(const HeaderOptions& headerOptions,
+        const OCRepresentation& rep, const int eCode, std::string diag)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        getCallback(diag)(headerOptions, rep, eCode);
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+void ThingsDiagnostics::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+        const int eCode, std::string diag)
+{
+    if (eCode == SUCCESS_RESPONSE)
+    {
+        std::cout << "PUT request was successful" << std::endl;
+
+        getCallback(diag)(headerOptions, rep, eCode);
+    }
+    else
+    {
+        std::cout << "onPut Response error: " << eCode << std::endl;
+        std::exit(-1);
+    }
+}
+
+bool ThingsDiagnostics::isSimpleResource(std::shared_ptr< OCResource > resource)
+{
+    for (unsigned int i = 0; i < resource->getResourceInterfaces().size(); ++i)
+    {
+        //std::cout << resource->getResourceInterfaces().at(0) << std::endl;
+        if (resource->getResourceInterfaces().at(0) == BATCH_INTERFACE)
+            return false;
+    }
+    return true;
+}
+
+OCStackResult ThingsDiagnostics::reboot(std::shared_ptr< OCResource > resource,
+        DiagnosticsCallback callback)
+{
+    if (!resource)
+    {
+        std::cout << "resource is NULL\n";
+        return OC_STACK_ERROR;
+    }
+
+    std::string diag = "reboot";
+
+    // Check the request queue if a previous request is still left. If so, remove it.
+    std::map< std::string, DiagnosticsRequestEntry >::iterator iter = diagnosticsRequestTable.find(
+            diag);
+    if (iter != diagnosticsRequestTable.end())
+        diagnosticsRequestTable.erase(iter);
+
+    // Create new request entry stored in the queue
+    DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
+    diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
+
+    QueryParamsMap query;
+    OCRepresentation rep;
+
+    if (isSimpleResource(resource))
+    {
+        // This resource is a simple resource. Just send a PUT message
+        OCRepresentation rep;
+        rep.setValue<std::string>(diag, "true");
+
+        return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
+                                std::placeholders::_2, std::placeholders::_3, diag)));
+    }
+    else
+    {
+        // This resource is a collection resource. It just acquires child resource's URI and send
+        // GET massages to the child resources in turn.
+        // First, request the child resources's URI.
+        // TODO: Add a deletion of actionset
+        return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
+                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                                diag)));
+    }
+}
+
+OCStackResult ThingsDiagnostics::factoryReset(std::shared_ptr< OCResource > resource,
+        DiagnosticsCallback callback)
+{
+    if (!resource)
+    {
+        std::cout << "resource is NULL\n";
+        return OC_STACK_ERROR;
+    }
+
+    std::string diag = "factoryreset";
+
+    // Check the request queue if a previous request is still left. If so, remove it.
+    std::map< std::string, DiagnosticsRequestEntry >::iterator iter = diagnosticsRequestTable.find(
+            diag);
+    if (iter != diagnosticsRequestTable.end())
+        diagnosticsRequestTable.erase(iter);
+
+    // Create new request entry stored in the queue
+    DiagnosticsRequestEntry newCallback(diag, callback, resource, "true");
+    diagnosticsRequestTable.insert(std::make_pair(diag, newCallback));
+
+    QueryParamsMap query;
+    OCRepresentation rep;
+
+    if (isSimpleResource(resource))
+    {
+        // This resource is a simple resource. Just send a PUT message
+        OCRepresentation rep;
+        rep.setValue<std::string>("factoryReset", "true");
+
+        return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsDiagnostics::onPut, this, std::placeholders::_1,
+                                std::placeholders::_2, std::placeholders::_3, diag)));
+    }
+    else
+    {
+        // This resource is a collection resource. It just acquires child resource's URI and send
+        // GET massages to the child resources in turn.
+        // First, request the child resources's URI.
+        // TODO: Add a deletion of actionset
+        return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
+                std::function<
+                        void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+                                const int eCode) >(
+                        std::bind(&ThingsDiagnostics::onGetChildInfoForUpdate, this,
+                                std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
+                                diag)));
+    }
+}
+
diff --git a/service/things-manager/sdk/src/ThingsDiagnostics.h b/service/things-manager/sdk/src/ThingsDiagnostics.h
new file mode 100755 (executable)
index 0000000..0327a4a
--- /dev/null
@@ -0,0 +1,224 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file   ThingsDiagnostics.h
+
+/// @brief  This file contains the declaration of classes and its members related to
+///         ThingsDiagnostics.
+
+#ifndef __OC_THINGSDIAGNOSTICS__
+#define __OC_THINGSDIAGNOSTICS__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <cstdlib>
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "GroupManager.h"
+
+using namespace OC;
+
+/// Declearation of Diagnostics Callback funtion type
+typedef std::function<
+        void(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode) > DiagnosticsCallback;
+
+/**
+ *  @brief
+ *  The following class is used as a item stacking in request queue. The class stores a request and
+ *  referential information (e.g., a diagnostics name, a target resource object, a callback functi-
+ *  on passed from the applications, and a update value). When the function for updating/getting
+ *  diagnostics value is called from applications, this class instance is created and stored in the
+ *  request queue. The queue is maintained in a std::map structure so if desiring to find a specific
+ *  request, you can find it by querying a diagnostics name.
+ */
+class DiagnosticsRequestEntry
+{
+public:
+    DiagnosticsRequestEntry(std::string ID, DiagnosticsCallback callback,
+            std::shared_ptr< OCResource > resource, std::string updateVal) :
+            m_ID(ID), m_callback(callback), m_resource(resource), m_updateVal(updateVal)
+    {
+    }
+    ;
+
+    // Diagnostics Name (used in key value in std::map structure)
+    // e.g., reboot and factoryset
+    std::string m_ID;
+
+    // Reference callback pointer
+    DiagnosticsCallback m_callback;
+
+    // Reference resource object
+    std::shared_ptr< OCResource > m_resource;
+
+    // Update value only used for diagnostics update (always "true")
+    std::string m_updateVal;
+};
+
+/**
+ *  @brief
+ *  The following class is used to store providing diagnostics name and its relevant information
+ *  The relevant information includes a brief description, uri, and attribute key.
+ *  Note that a developer only specifies a diagnostics name, not URI nor attribute key, to
+ *  update a value to a remote. Thus, using diagnostics name, we convert it to more specific
+ *  information (i.e. uri and attribute key) to send a request. This class is reponsible to storing
+ *  these information.
+ */
+class DiagnosticsUnitInfo
+{
+public:
+    DiagnosticsUnitInfo(std::string name, std::string description, std::string uri,
+            std::string attribute) :
+            m_name(name), m_description(description), m_uri(uri), m_attribute(attribute)
+    {
+    }
+    ;
+
+    std::string m_name;
+    std::string m_description;
+    std::string m_uri;
+    std::string m_attribute;
+
+    // If a developer wants to know a list of diagnostics names, gives it in JSON format.
+    std::string getJSON()
+    {
+        std::string res;
+
+        res = "{\"name\":\"" + m_name + "\",\"description\":\"" + m_description + "\"}";
+
+        return res;
+    }
+};
+
+#define NUMDIAGUNIT 3
+typedef std::string DiagnosticsName;
+typedef std::string DiagnosticsValue;
+
+class ThingsDiagnostics
+{
+public:
+    /**
+     * Constructor for ThingsDiagnostics. Constructs a new ThingsDiagnostics
+     */
+    ThingsDiagnostics(void)
+    {
+        DiagnosticsUnitInfo unit[] =
+        {
+            { "reboot",
+                "reboot",
+                "/oic/diag", "reboot" },
+            { "startcollection",
+                "Toggles between collecting and not collecting any device statistics depending on the value being 0 or 1",
+                "/oic/diag", "startCollection" },
+            { "factoryreset",
+                "restore all configuration values to default values",
+                "/oic/diag", "factoryReset" } };
+
+        for (int i = 0; i < NUMDIAGUNIT; i++)
+            DiagnosticsUnitTable.push_back(unit[i]);
+    }
+    ;
+
+    /**
+     * Virtual destructor
+     */
+    ~ThingsDiagnostics(void)
+    {
+    }
+    ;
+
+    static ThingsDiagnostics *thingsDiagnosticsInstance;
+    static ThingsDiagnostics* getInstance();
+    void deleteInstance();
+
+    void setGroupManager(GroupManager *groupmanager)
+    {
+        g_groupmanager = groupmanager;
+    }
+    ;
+
+    /**
+     * API to make things reboot
+     * Callback call when a response arrives.
+     *
+     * @param resource - resource pointer representing the target group
+     * @param callback - callback.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+    OCStackResult reboot(std::shared_ptr< OCResource > resource, DiagnosticsCallback callback);
+
+    /**
+     * API for factory reset on device
+     * Callback call when a response arrives.
+     *
+     * @param resource - resource pointer representing the target group
+     * @param callback - callback.
+     *
+     * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+     *
+     * NOTE: OCStackResult is defined in ocstack.h.
+     */
+
+    OCStackResult factoryReset(std::shared_ptr< OCResource > resource,
+            DiagnosticsCallback callback);
+
+    /**
+     * API to show a list of supported diagnostics units
+     * Callback call when a response arrives.
+     *
+     * @return the list in JSON format
+     */
+    std::string getListOfSupportedDiagnosticsUnits();
+
+private:
+
+    GroupManager *g_groupmanager;
+
+    std::vector< DiagnosticsUnitInfo > DiagnosticsUnitTable;
+
+    void onExecuteForGroupAction(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGetChildInfoForUpdate(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onCreateActionSet(const HeaderOptions& headerOptions, const OCRepresentation& rep,
+            const int eCode, std::string conf);
+    void onGet(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode,
+            std::string conf);
+    void onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep, const int eCode,
+            std::string conf);
+
+    std::shared_ptr< OCResource > getResource(std::string conf);
+    DiagnosticsCallback getCallback(std::string conf);
+    std::string getUpdateVal(std::string conf);
+    std::string getAttributeByDiagnosticsName(DiagnosticsName name);
+    std::string getUriByDiagnosticsName(DiagnosticsName name);
+
+    std::string getHostFromURI(std::string oldUri);
+
+    bool isSimpleResource(std::shared_ptr< OCResource > resource);
+
+};
+
+#endif  /* __OC_THINGSCONFIGURATION__*/
+
diff --git a/service/things-manager/sdk/src/ThingsManager.cpp b/service/things-manager/sdk/src/ThingsManager.cpp
new file mode 100755 (executable)
index 0000000..8138bde
--- /dev/null
@@ -0,0 +1,176 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file    ThingsManager.cpp
+///  @brief
+
+#include "ThingsManager.h"
+#include "GroupManager.h"
+#include "GroupSynchronization.h"
+#include "ThingsConfiguration.h"
+#include "ThingsDiagnostics.h"
+#include <algorithm>
+#include <thread>
+
+
+using namespace OC;
+
+GroupManager *g_groupManager;
+GroupSynchronization *g_groupSync = NULL;
+ThingsConfiguration *g_thingsConf = NULL;
+ThingsDiagnostics *g_thingsDiag = NULL;
+
+ThingsManager::ThingsManager(void)
+{
+    g_groupManager = new GroupManager();
+       g_groupSync = GroupSynchronization::getInstance();
+    g_thingsConf = ThingsConfiguration::getInstance();
+    g_thingsDiag = ThingsDiagnostics::getInstance();
+    g_thingsConf->setGroupManager(g_groupManager);
+    g_thingsDiag->setGroupManager(g_groupManager);
+}
+
+/**
+ * Virtual destructor
+ */
+ThingsManager::~ThingsManager(void)
+{
+    delete g_groupManager;
+       g_groupSync->deleteInstance();
+    g_thingsConf->deleteInstance();
+    g_thingsDiag->deleteInstance();
+}
+
+
+
+OCStackResult ThingsManager::findCandidateResources(std::vector< std::string > resourceTypes,
+        std::function< void(std::vector< std::shared_ptr< OCResource > >) >  callback, int waitsec)
+{
+    OCStackResult result = g_groupManager->findCandidateResources(resourceTypes,callback,waitsec);
+
+    return result;
+}
+
+OCStackResult ThingsManager::subscribeCollectionPresence(std::shared_ptr< OCResource > resource, std::function< void(std::string, OCStackResult) >  callback)
+{
+    OCStackResult result = g_groupManager->subscribeCollectionPresence(resource,callback);
+
+    return result;
+}
+
+OCStackResult ThingsManager::findGroup (std::vector<std::string> collectionResourceTypes, FindCallback resourceHandler)
+{
+       OCStackResult result = g_groupSync->findGroup(collectionResourceTypes, resourceHandler);
+
+       return result;
+}
+
+OCStackResult ThingsManager::createGroup (std::string collectionResourceType)
+{
+       OCStackResult result = g_groupSync->createGroup(collectionResourceType);
+
+       return result;
+}
+
+OCStackResult ThingsManager::joinGroup (std::string collectionResourceType, OCResourceHandle resourceHandle)
+{
+       OCStackResult result = g_groupSync->joinGroup(collectionResourceType, resourceHandle);
+
+       return result;
+}
+
+OCStackResult ThingsManager::joinGroup (const std::shared_ptr<OCResource> resource, OCResourceHandle resourceHandle)
+{
+       OCStackResult result = g_groupSync->joinGroup(resource, resourceHandle);
+
+       return result;
+}
+
+OCStackResult ThingsManager::leaveGroup (std::string collectionResourceType, OCResourceHandle resourceHandle)
+{
+       OCStackResult result = g_groupSync->leaveGroup(collectionResourceType, resourceHandle);
+
+       return result;
+}
+
+void ThingsManager::deleteGroup (std::string collectionResourceType)
+{
+       g_groupSync->deleteGroup(collectionResourceType);
+}
+
+std::map<std::string, OCResourceHandle> ThingsManager::getGroupList ()
+{
+       return g_groupSync->getGroupList();
+}
+
+OCStackResult ThingsManager::updateConfigurations(std::shared_ptr< OCResource > resource, std::map<ConfigurationName, ConfigurationValue> configurations, ConfigurationCallback callback)
+{
+    return g_thingsConf->updateConfigurations(resource, configurations, callback);
+}
+OCStackResult ThingsManager::getConfigurations(std::shared_ptr< OCResource > resource, std::vector<ConfigurationName> configurations, ConfigurationCallback callback)
+{
+    return g_thingsConf->getConfigurations( resource,  configurations, callback);
+}
+std::string ThingsManager::getListOfSupportedConfigurationUnits()
+{
+    return g_thingsConf->getListOfSupportedConfigurationUnits();
+}
+
+OCStackResult ThingsManager::doBootstrap(ConfigurationCallback callback)
+{
+    return g_thingsConf->doBootstrap(callback);
+}
+
+
+OCStackResult ThingsManager::reboot(std::shared_ptr< OCResource > resource, ConfigurationCallback callback)
+{
+    return g_thingsDiag->reboot( resource, callback);
+}
+OCStackResult ThingsManager::factoryReset(std::shared_ptr< OCResource > resource, ConfigurationCallback callback)
+{
+    return g_thingsDiag->factoryReset(  resource,  callback);
+}
+
+
+
+std::string ThingsManager::getStringFromActionSet(const ActionSet *newActionSet)
+{
+    return g_groupManager->getStringFromActionSet(newActionSet);
+}
+ActionSet* ThingsManager::getActionSetfromString(std::string desc)
+{
+   return g_groupManager->getActionSetfromString(desc);
+}
+OCStackResult ThingsManager::addActionSet(std::shared_ptr< OCResource > resource, const ActionSet* newActionSet, PutCallback cb)
+{
+    return g_groupManager->addActionSet(resource, newActionSet, cb);
+}
+OCStackResult ThingsManager::executeActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb)
+{
+    return g_groupManager->executeActionSet(resource, actionsetName, cb);
+}
+OCStackResult ThingsManager::getActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, GetCallback cb)
+{
+    return g_groupManager->getActionSet(resource, actionsetName, cb);
+}
+OCStackResult ThingsManager::deleteActionSet(std::shared_ptr< OCResource > resource, std::string actionsetName, PostCallback cb)
+{
+    return g_groupManager->deleteActionSet(resource, actionsetName, cb);
+}