Implementation of Group action feature for Things Manager.
authorHyunJun Kim <hyunjun2.kim@samsung.com>
Mon, 15 Dec 2014 06:55:14 +0000 (15:55 +0900)
committerHyunJun Kim <hyunjun2.kim@samsung.com>
Mon, 15 Dec 2014 06:55:14 +0000 (15:55 +0900)
Add GROUP_INTERFACE and OC_RSRVD_INTERFACE_GROUP.
These interfaces are supported Group Action.

When DefaultCollectionEntityHandler is received an message
which Using GROUP_INTERFACE,
It is called BuildCollectionGroupActionJSONResponse.

PUT : Action Create and Delete
POST : Action Read and Execute

Change-Id: I14519fa85b5319c3e9df72fa27e85a5d8df6ea87
Signed-off-by: HyunJun Kim <hyunjun2.kim@samsung.com>
resource/csdk/makefile [changed mode: 0644->0755]
resource/csdk/stack/include/internal/ocresource.h [changed mode: 0644->0755]
resource/csdk/stack/include/internal/ocresourcehandler.h [changed mode: 0644->0755]
resource/csdk/stack/include/internal/oicgroup.h [new file with mode: 0755]
resource/csdk/stack/src/occollection.c [changed mode: 0644->0755]
resource/csdk/stack/src/oicgroup.c [new file with mode: 0755]
resource/include/OCApi.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 238a65d..ca77f30
@@ -135,6 +135,7 @@ OCTBSTACK_SOURCES   += $(OCTBSTACK_SRC)/ocresource.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocobserve.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocserverrequest.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/occollection.c
+OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/oicgroup.c
 OCTBSTACK_SOURCES      += $(OCTBSTACK_SRC)/ocsecurity.c
 
 SOURCES                        := $(CJSON_SOURCES)
old mode 100644 (file)
new mode 100755 (executable)
index 542cfb6..01611c1
@@ -49,9 +49,43 @@ typedef enum {
     STACK_IF_DEFAULT = 0,
     STACK_IF_LL,
     STACK_IF_BATCH,
+    STACK_IF_GROUP,
     STACK_IF_INVALID
 } OCStackIfTypes;
 
+// following structure will be create in occollection.
+typedef struct occapability {
+    struct occapability* next;
+
+    char *capability;           // It is a name about resource capability.
+    char *status;               //
+} OCCapability;
+
+
+// following structure will be create in occollection.
+typedef struct ocaction {
+    struct ocaction *next;
+
+    // Target Uri.
+    // It will be used to execute the action.
+    char *resourceUri;
+
+    OCCapability* head;
+    
+} OCAction;
+
+// following structure will be created in occollection.
+typedef struct ocactionset {
+
+    struct ocactionset *next;
+
+    char *actionsetName;
+
+    OCAction* head;
+} OCActionSet;
+
+
+
 typedef struct resourcetype_t {
     struct resourcetype_t *next; // linked list; for multiple types on resource
 
@@ -116,6 +150,9 @@ typedef struct rsrc_t {
     /* method_t methods; */
     // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
     uint32_t sequenceNum;
+
+       // Pointer of ActionSet which to support group action.
+    OCActionSet *actionsetHead;
 } OCResource;
 
 
old mode 100644 (file)
new mode 100755 (executable)
index e5a24bc..505a598
@@ -34,6 +34,9 @@
 #define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
 #define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
 #define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
+#define OC_RSRVD_INTERFACE_GROUP        "oc.mi.c"
+
+
 #define OC_RSRVD_OBSERVABLE             "obs"
 #define OC_RSRVD_SECURE                 "sec"
 #define OC_RSRVD_HOSTING_PORT           "port"
diff --git a/resource/csdk/stack/include/internal/oicgroup.h b/resource/csdk/stack/include/internal/oicgroup.h
new file mode 100755 (executable)
index 0000000..2493fba
--- /dev/null
@@ -0,0 +1,57 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OIC_GROUP_H
+#define OIC_GROUP_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+
+void AddCapability(OCCapability** head, OCCapability* node);
+
+void AddAction(OCAction** head, OCAction* node);
+
+void AddActionSet(OCActionSet **head, OCActionSet* node);
+
+void DeleteCapability(OCCapability *del);
+
+void DeleteAction(OCAction** action);
+
+void DeleteActionSet(OCActionSet** actionset);
+
+OCStackResult DeleteActionSets(OCResource** resource);
+
+OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName);
+
+OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method,
+        char **actionsetName);
+
+OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc);
+
+OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
+        OCClientResponse* clientResponse);
+
+void ActionSetCD(void *context);
+
+OCStackResult
+BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
+        OCResource *resource, OCEntityHandlerRequest *ehRequest);
+
+#endif // OIC_GROUP_H
old mode 100644 (file)
new mode 100755 (executable)
index 2efba22..23980ba
 #include "debug.h"
 #include "cJSON.h"
 /// Module Name
+#include <stdio.h>
+
+#define WITH_GROUPACTION 1
+
+#ifdef WITH_GROUPACTION
+#include "oicgroup.h"
+#endif
+
 #define TAG PCF("occollection")
 
 #define NUM_PARAM_IN_QUERY  2
@@ -141,6 +149,10 @@ ValidateQuery (const unsigned char *query, OCResourceHandle resource,
         {
             *ifParam = STACK_IF_BATCH;
         }
+        else if(strcmp (ifPtr, OC_RSRVD_INTERFACE_GROUP) == 0)
+        {
+            *ifParam = STACK_IF_GROUP;
+        }
         else
         {
             return OC_STACK_ERROR;
@@ -379,8 +391,10 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
     if (result != OC_STACK_OK)
         return result;
 
-    if ((ehRequest->method != OC_REST_GET) &&
-        (ehRequest->method != OC_REST_PUT))
+  
+    if(!((ehRequest->method == OC_REST_GET) || 
+        (ehRequest->method == OC_REST_PUT) ||
+        (ehRequest->method == OC_REST_POST)))
         return OC_STACK_ERROR;
 
     if (ehRequest->method == OC_REST_GET)
@@ -404,7 +418,11 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                 ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
                         GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
                 return HandleBatchInterface(ehRequest);
-
+#ifdef WITH_GROUPACTION
+            case STACK_IF_GROUP:
+                return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/, (OCResource *)ehRequest->resource,
+                                ehRequest);
+#endif  // WITH_GROUPACTION
             default:
                 return OC_STACK_ERROR;
         }
@@ -425,10 +443,35 @@ OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
                         GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
                 return HandleBatchInterface(ehRequest);
 
+
+#ifdef WITH_GROUPACTION
+            case STACK_IF_GROUP:
+            {
+                OC_LOG_V(INFO, TAG, "IF_COLLECTION PUT with request ::\n%s\n ", ehRequest->reqJSONPayload);
+                printf("PUT ::\n%s\n", ehRequest->reqJSONPayload);
+                return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/, (OCResource *)ehRequest->resource, ehRequest);
+            }
+#endif // WITH_GROUPACTION
+            default:
+                return OC_STACK_ERROR;
+        }
+    }
+#ifdef WITH_GROUPACTION
+    else if(ehRequest->method == OC_REST_POST) {
+
+        switch(ifQueryParam)
+        {
+            case STACK_IF_GROUP:
+            {
+                OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ", ehRequest->reqJSONPayload);
+                printf("POST ::\n%s\n", ehRequest->reqJSONPayload);
+                return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/, (OCResource *)ehRequest->resource, ehRequest);
+            }
             default:
                 return OC_STACK_ERROR;
         }
     }
+#endif // WITH_GROUPACTION
     return result;
 }
 
diff --git a/resource/csdk/stack/src/oicgroup.c b/resource/csdk/stack/src/oicgroup.c
new file mode 100755 (executable)
index 0000000..35819d8
--- /dev/null
@@ -0,0 +1,722 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#define _POSIX_C_SOURCE 200112L
+#include <string.h>
+
+#include "cJSON.h"
+#include "ocmalloc.h"
+#include "oicgroup.h"
+#include "ocresource.h"
+#include "occollection.h"
+
+#define TAG PCF("OICGROUP")
+
+#define DESC_DELIMITER "\""
+#define ACTION_DELIMITER "*"
+#define ATTR_DELIMITER "|"
+
+void AddCapability(OCCapability** head, OCCapability* node)
+{
+    OCCapability *pointer = *head;
+    if (NULL == pointer)
+    {
+        *head = node;
+    }
+    else
+    {
+        while (pointer->next != NULL)
+        {
+            pointer = pointer->next;
+        }
+
+        pointer->next = node;
+    }
+}
+
+void AddAction(OCAction** head, OCAction* node)
+{
+    OCAction *pointer = *head;
+    if (NULL == pointer)
+    {
+        *head = node;
+    }
+    else
+    {
+
+        while (pointer->next != NULL)
+        {
+            pointer = pointer->next;
+        }
+
+        pointer->next = node;
+    }
+}
+
+void AddActionSet(OCActionSet **head, OCActionSet* node)
+{
+    OCActionSet *pointer = *head;
+    if (NULL == pointer)
+    {
+        *head = node;
+    }
+    else
+    {
+
+        while (pointer->next != NULL)
+        {
+            pointer = pointer->next;
+        }
+
+        pointer->next = node;
+    }
+}
+
+void DeleteCapability(OCCapability *del)
+{
+    free(del->capability);
+    del->capability = NULL;
+    free(del->status);
+    del->status = NULL;
+}
+
+void DeleteAction(OCAction** action)
+{
+    OCCapability* pointer = (*action)->head;
+    OCCapability* pDel = NULL;
+
+    while (pointer)
+    {
+        pDel = pointer;
+        pointer = pointer->next;
+
+        DeleteCapability(pDel);
+        pDel->next = NULL;
+    }
+    OCFree((*action)->resourceUri);
+    (*action)->resourceUri = NULL;
+    (*action)->next = NULL;
+}
+
+void DeleteActionSet(OCActionSet** actionset)
+{
+    OCAction* pointer = (*actionset)->head;
+    OCAction* pDel = NULL;
+
+    while (pointer)
+    {
+        pDel = pointer;
+        pointer = pointer->next;
+
+        DeleteAction(&pDel);
+        pDel->next = NULL;
+    }
+
+    OCFree((*actionset)->actionsetName);
+    (*actionset)->head = NULL;
+}
+
+OCStackResult FindAndDeleteActionSet(OCResource **resource, const char * actionsetName)
+{
+
+    if (*resource != NULL)
+    {
+
+        OCActionSet *pointer = NULL;
+        OCActionSet *pDel = NULL;
+
+        pointer = (*resource)->actionsetHead;
+
+        if (pointer == NULL)
+        {
+            return OC_STACK_ERROR;
+        }
+        else
+        {
+            if (strcmp(pointer->actionsetName, actionsetName) == 0)
+            {
+                if (pointer->next != NULL)
+                    (*resource)->actionsetHead = pointer->next;
+                else
+                    (*resource)->actionsetHead = NULL;
+
+                DeleteActionSet(&pointer);
+
+            }
+            else if (pointer->next != NULL)
+            {
+                while (pointer)
+                {
+                    if (pointer->next != NULL)
+                    {
+                        if (strcmp(pointer->next->actionsetName, actionsetName) == 0)
+                        {
+                            pDel = pointer->next;
+                            pointer->next = pointer->next->next;
+
+                            DeleteActionSet(&pDel);
+                        }
+                    }
+                }
+            }
+
+            return OC_STACK_OK;
+        }
+
+    }
+
+    return OC_STACK_ERROR;
+}
+
+OCStackResult DeleteActionSets(OCResource** resource)
+{
+    OCActionSet *pointer = (*resource)->actionsetHead;
+    OCActionSet *pDel = pointer;
+
+    while (pointer)
+    {
+        pDel = pointer;
+        pointer = pointer->next;
+
+        DeleteActionSet(&pDel);
+        pDel->next = NULL;
+    }
+
+    (*resource)->actionsetHead = NULL;
+    return OC_STACK_OK;
+}
+
+OCStackResult GetActionSet(const char *actionName, OCActionSet *head, OCActionSet** actionset)
+{
+    OCActionSet *pointer = head;
+
+    while (pointer)
+    {
+        //printf("%s :: %s\n", pointer->actionsetName, actionsetName);
+        if (strcmp(pointer->actionsetName, actionName) == 0)
+        {
+            *actionset = pointer;
+            return OC_STACK_OK;
+        }
+
+        pointer = pointer->next;
+    }
+
+    return OC_STACK_ERROR;
+
+}
+
+OCStackResult GetActionSetFromString(OCResource **resource, unsigned char *request, char** method,
+        char **actionsetName)
+{
+    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;
+
+    OCActionSet* actionset = NULL;
+    OCAction* action = NULL;
+
+    acitonRequest = (char *) OCMalloc(strlen((char *) request) + 1);
+    strncpy(acitonRequest, (char *) request, strlen((char *) request) + 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.
+
+                *method = (char *) OCMalloc(strlen(iterToken) + 1);
+                strncpy(*method, iterToken, strlen(iterToken) + 1);
+
+                //GetActionName(iterToken, &actionsetName);
+                // printf("%s\n", iterToken, &iterTokenPtr);
+                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
+                // printf("%s\n", iterToken);
+                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
+                // printf("%s\n", iterToken);
+
+                printf("DESC :: %s\n", iterToken);
+                description = (char *) OCMalloc(strlen(iterToken) + 1);
+                strncpy(description, iterToken, strlen(iterToken) + 1);
+                printf("DESC Copied :: %s\n", description);
+
+                // Find the action name from description.
+                iterDescPtr = NULL;
+                iterToken = (char *) strtok_r(description, ACTION_DELIMITER, &iterDescPtr);
+                //while(iterToken != NULL)
+                if (iterToken != NULL)
+                {
+                    if (*actionsetName != NULL)
+                    {
+                        printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
+                        return OC_STACK_ERROR; // ERROR OCCURED.
+                    }
+                    else
+                    {
+                        //  Actionset name.
+                        printf("ACTION SET NAME :: %s\n", iterToken);
+                        *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
+
+                        strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
+                        printf("ACTION SET NAME :: %s\n", *actionsetName);
+                        // break;
+                    }
+
+                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
+                }
+                else
+                {
+                    return OC_STACK_ERROR;
+
+                } // end Action Set Name.
+
+                // New ActionSet Add to OCResource's ActionSet list.
+                // 1. Allocate a new pointer for actionset.
+                actionset = (OCActionSet*) OCMalloc(sizeof(OCActionSet));
+                // 2. Initiate actionset.
+                memset(actionset, 0, sizeof(OCActionSet));
+                actionset->actionsetName = (char *) OCMalloc(strlen(*actionsetName) + 1);
+                strncpy(actionset->actionsetName, *actionsetName, strlen(*actionsetName) + 1);
+                printf("ACTION SET NAME :: %s\n", actionset->actionsetName);
+
+                while (iterToken != NULL)
+                {
+                    action = (OCAction *) OCMalloc(sizeof(OCAction));
+                    memset(action, 0, sizeof(OCAction));
+
+                    printf("ATTR Copied :: %s\n", iterToken);
+                    attributes = (char *) OCMalloc(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 = (char *) OCMalloc(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->resourceUri = (char *) OCMalloc(strlen(iterToken) + 1);
+                                strncpy(action->resourceUri, iterToken, strlen(iterToken) + 1);
+                            }
+                            else
+                            {
+                                OCCapability* capa = (OCCapability*) OCMalloc(sizeof(OCCapability));
+                                memset(capa, 0, sizeof(OCCapability));
+                                printf("%s :: ", iterToken);
+                                capa->capability = (char *) OCMalloc(strlen(iterToken) + 1);
+                                strncpy(capa->capability, iterToken, strlen(iterToken) + 1);
+                                iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
+                                printf("%s\n", iterToken);
+                                capa->status = (char *) OCMalloc(strlen(iterToken) + 1);
+                                strncpy(capa->status, iterToken, strlen(iterToken) + 1);
+
+                                AddCapability(&action->head, capa);
+                            }
+
+                            iterToken = (char *) strtok_r(NULL, "=", &iterAttrPtr);
+                        }
+
+                        iterToken = (char *) strtok_r(NULL, ATTR_DELIMITER, &iterAttrbutesPtr);
+                    } // End of Action
+
+                    AddAction(&actionset->head, action);
+
+                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
+                }
+
+                // 3. Add the pointer OCResource's ActionSet list.
+                AddActionSet(&(*resource)->actionsetHead, actionset);
+                return OC_STACK_OK;
+            }
+            else if (strcmp(iterToken, "DoAction") == 0 || strcmp(iterToken, "DelActionSet") == 0
+                    || strcmp(iterToken, "GetActionSet") == 0)
+            {
+                *method = (char *) OCMalloc(strlen(iterToken) + 1);
+                strncpy(*method, iterToken, strlen(iterToken) + 1);
+
+                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is mean ':'.
+                // printf("%s\n", iterToken);
+                iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr); // it is body of action description.
+                // printf("%s\n", iterToken);
+
+                description = (char *) OCMalloc(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);
+                if (iterToken != NULL)
+                {
+                    if (*actionsetName != NULL)
+                    {
+                        printf("ERROR :: ACTIONSET NAME as ActionSet(%s)\n", iterToken);
+                        return OC_STACK_ERROR; // ERROR OCCURED.
+                    }
+                    else
+                    {
+                        //  Actionset name.
+                        printf("ACTION SET NAME :: %s\n", iterToken);
+                        *actionsetName = (char *) OCMalloc(strlen(iterToken) + 1);
+
+                        strncpy(*actionsetName, iterToken, strlen(iterToken) + 1);
+                        printf("ACTION SET NAME :: %s\n", *actionsetName);
+                    }
+
+                    iterToken = (char *) strtok_r(NULL, ACTION_DELIMITER, &iterDescPtr);
+                    return OC_STACK_OK;
+                }
+                else
+                {
+                    return OC_STACK_ERROR;
+
+                } // end Action Set Name.
+                break;
+            }
+
+            iterToken = (char *) strtok_r(NULL, DESC_DELIMITER, &iterTokenPtr);
+        }
+    }
+
+    return OC_STACK_ERROR;
+}
+
+OCStackResult GetStringFromActionSet(OCActionSet* actionset, char** desc)
+{
+    char temp[1024] =
+    { 0 };
+    int remaining = 1023;
+
+    // OCActionSet *as = resource->actionsetHead;
+    // while(as != NULL)
+    // {
+    printf("\n\n\nAction Set Name :: %s\n", actionset->actionsetName);
+    OCAction *action = actionset->head;
+
+    if (remaining >= strlen(actionset->actionsetName) + 1)
+    {
+        strcat(temp, actionset->actionsetName);
+        remaining -= strlen(actionset->actionsetName);
+        strcat(temp, "*");
+        remaining--;
+    }
+    else
+    {
+        return OC_STACK_ERROR;
+    }
+
+    while (action != NULL)
+    {
+        printf("\tURI :: %s\n", action->resourceUri);
+        strcat(temp, "uri=");
+        remaining -= strlen("uri=");
+        strcat(temp, action->resourceUri);
+        remaining -= strlen(action->resourceUri);
+        strcat(temp, "|");
+        remaining--;
+
+        OCCapability *capas = action->head;
+        while (capas != NULL)
+        {
+            printf("\t\t%s = %s\n", capas->capability, capas->status);
+            strcat(temp, capas->capability);
+            remaining -= strlen(capas->capability);
+            strcat(temp, "=");
+            remaining--;
+            strcat(temp, capas->status);
+            remaining -= strlen(capas->capability);
+
+            capas = capas->next;
+            if (capas != NULL)
+            {
+                strcat(temp, "|");
+            }
+        }
+
+        action = action->next;
+        if (action != NULL)
+        {
+            strcat(temp, "*");
+            remaining--;
+        }
+    }
+    //     as = as->next;
+    // }
+
+    *desc = (char *) OCMalloc(1024 - remaining);
+    strcpy(*desc, temp);
+    // printf("\t\tPlain Text = %s(%i)\n", *desc, 1024 - remaining);
+
+    return OC_STACK_OK;
+}
+
+OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
+        OCClientResponse* clientResponse)
+{
+
+    // printf("\n\n\tcallback is called\n\n");
+    // printf("\t\tresponse JSON : %s\n", clientResponse->resJSONPayload);
+
+    return OC_STACK_KEEP_TRANSACTION;
+}
+
+void ActionSetCD(void *context)
+{
+    // printf("\n\t\tCD is called\n");
+
+    // free( context );
+}
+
+OCStackResult BuildActionJSON(OCAction* action, unsigned char* bufferPtr, uint16_t *remaining)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    cJSON *json;
+    cJSON *body;
+
+    char *jsonStr;
+    uint16_t jsonLen;
+
+    OC_LOG(INFO, TAG, PCF("Entering BuildActionJSON"));
+    json = cJSON_CreateObject();
+
+    cJSON_AddItemToObject(json, "rep", body = cJSON_CreateObject());
+
+    OCCapability* pointerCapa = action->head;
+    while (pointerCapa)
+    {
+        cJSON_AddStringToObject(body, pointerCapa->capability, pointerCapa->status);
+        pointerCapa = pointerCapa->next;
+    }
+
+    jsonStr = cJSON_PrintUnformatted(json);
+
+    jsonLen = strlen(jsonStr);
+    if (jsonLen < *remaining)
+    {
+        strcat((char*) bufferPtr, jsonStr);
+        *remaining -= jsonLen;
+        bufferPtr += jsonLen;
+        ret = OC_STACK_OK;
+    }
+
+    cJSON_Delete(json);
+    free(jsonStr);
+
+    return ret;
+}
+
+OCStackResult SendAction(const char *targetUri, const unsigned char *action)
+{
+    OCCallbackData cbdata =
+    { 0 };
+    cbdata.cb = &ActionSetCB;
+    cbdata.cd = &ActionSetCD;
+    cbdata.context = (void *) 0x99;
+
+    OCDoHandle handle;
+    return OCDoResource(&handle, OC_REST_PUT, targetUri,
+    //temp->rsrcType->resourcetypename,
+            NULL, (char *) action, OC_NA_QOS, &cbdata, NULL, 0);
+}
+
+OCStackResult BuildCollectionGroupActionJSONResponse(OCMethod method/*OCEntityHandlerFlag flag*/,
+        OCResource *resource, OCEntityHandlerRequest *ehRequest)
+{
+    OCStackResult stackRet = OC_STACK_ERROR;
+    // OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    OC_LOG(INFO, TAG, PCF("Group Action is requested."));
+    // if (stackRet == OC_STACK_OK)
+    {
+
+        char *doWhat = NULL;
+        char *actionName = NULL;
+
+        // uint16_t remaining = MAX_RESPONSE_LENGTH;
+        size_t bufferLength = 0;
+        unsigned char buffer[MAX_RESPONSE_LENGTH] =
+        { 0 };
+        unsigned char *bufferPtr = NULL;
+
+        bufferPtr = buffer;
+
+        OCResource * collResource = (OCResource *) ehRequest->resource;
+        // OCResourceHandle origResourceHandle = ehRequest->resource;
+
+        char *jsonResponse;
+
+        cJSON *json = cJSON_CreateObject();
+        cJSON *format;
+
+        cJSON_AddStringToObject(json, "href", resource->uri);
+        cJSON_AddItemToObject(json, "rep", format = cJSON_CreateObject());
+
+        if (method == OC_REST_GET)
+        {
+            OC_LOG(INFO, TAG, PCF("Group Action[GET]."));
+        }
+        else if (method == OC_REST_PUT)
+        {
+            OC_LOG(INFO, TAG, PCF("Group Action[PUT]."));
+
+            unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
+
+            GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
+
+            if (strcmp(doWhat, "DelActionSet") == 0)
+            {
+                if (FindAndDeleteActionSet(&resource, actionName) == OC_STACK_OK)
+                {
+                }
+                else
+                {
+                }
+            }
+            else
+            {
+            }
+
+            stackRet = OC_STACK_OK;
+
+        }
+        else if (method == OC_REST_POST)
+        {
+            OC_LOG(INFO, TAG, PCF("Group Action[POST]."));
+
+            OCActionSet *actionset = NULL;
+            unsigned char *actionPtr = (unsigned char *) ehRequest->reqJSONPayload;
+
+            GetActionSetFromString(&resource, actionPtr, &doWhat, &actionName);
+
+            if (strcmp(doWhat, "DoAction") == 0)
+            {
+                if (GetActionSet(actionName, resource->actionsetHead, &actionset) != OC_STACK_OK)
+                {
+                    OC_LOG(INFO, TAG, PCF("ERROR"));
+                    stackRet = OC_STACK_ERROR;
+                }
+
+                if (actionset == NULL)
+                {
+                    OC_LOG(INFO, TAG, PCF("ERROR"));
+                    stackRet = OC_STACK_ERROR;
+                } else {
+
+                    // printf("Execute ActionSet :: %s\n", actionset->actionsetName);
+
+                    OCAction *pointerAction = actionset->head;
+                    while (pointerAction != NULL)
+                    {
+                        // printf("Action Target :: %s\n", pointerAction->resourceUri);
+
+                        unsigned char actionDesc[MAX_RESPONSE_LENGTH] =
+                        { 0 };
+                        unsigned char* actionDescPtr = actionDesc;
+                        uint16_t remaining = MAX_RESPONSE_LENGTH;
+
+                        strcpy((char *) actionDescPtr, (const char *) OC_JSON_PREFIX);
+                        BuildActionJSON(pointerAction, actionDescPtr, &remaining);
+                        strcat((char *) actionDescPtr, (const char *) OC_JSON_SUFFIX);
+
+                        SendAction(pointerAction->resourceUri, actionDescPtr);
+
+                        pointerAction = pointerAction->next;
+                    }
+                    stackRet = OC_STACK_OK;
+                }
+            }
+            else if (strcmp(doWhat, "GetActionSet") == 0)
+            {
+                char *plainText = NULL;
+                OCActionSet *actionset = NULL;
+
+                // char *jsonResponse;
+
+                GetActionSet(actionName, resource->actionsetHead, &actionset);
+                if(actionset != NULL)
+                {
+                    GetStringFromActionSet(actionset, &plainText);
+
+                    if (plainText != NULL)
+                    {
+                        cJSON_AddStringToObject(format, "ActionSet", plainText);
+
+                        // jsonResponse = cJSON_Print(json);
+                        // cJSON_Delete(json);
+
+                        // strcat((char *)bufferPtr, jsonResponse);
+                    }
+
+                    stackRet = OC_STACK_OK;
+                }
+            }
+            else if (actionName == NULL)
+            {
+                // printf("Cannot find actionname\n");
+                return OC_STACK_ERROR;
+            }
+        }
+
+        jsonResponse = cJSON_Print(json);
+        cJSON_Delete(json);
+
+        strcat((char *) bufferPtr, jsonResponse);
+
+        // printf("\n\tRESONSE ::\n%s\n", buffer);
+        bufferLength = strlen((const char *) buffer);
+        if (bufferLength > 0)
+        {
+            OCEntityHandlerResponse response =
+            { 0 };
+            response.ehResult = OC_EH_OK;
+            response.payload = buffer;
+            response.payloadSize = bufferLength + 1;
+            response.persistentBufferFlag = 0;
+            response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+            response.resourceHandle = (OCResourceHandle) collResource;
+            stackRet = OCDoResponse(&response);
+        }
+
+        // ehRequest->resource = origResourceHandle;
+    }
+
+    return stackRet;
+
+    //return OC_STACK_OK;
+}
old mode 100644 (file)
new mode 100755 (executable)
index 97076c5..f46dac0
@@ -194,6 +194,10 @@ namespace OC
     // Used in GET, PUT, POST, DELETE methods on links to other resources of a collection.
     const std::string BATCH_INTERFACE = "oc.mi.b";
 
+    // Used in GET, PUT, POST methods on links to other remote resources of a group.
+    const std::string GROUP_INTERFACE = "oc.mi.c";
+
+
     typedef std::function<void(std::shared_ptr<OCResource>)> FindCallback;
 
     typedef std::function<OCEntityHandlerResult(