replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / stack / src / occollection.c
old mode 100644 (file)
new mode 100755 (executable)
index 3c8f113..66b5dce
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+// Defining _POSIX_C_SOURCE macro with 200112L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1-2001 base
+// specification (excluding the XSI extension).
+// For POSIX.1-2001 base specification,
+// Refer http://pubs.opengroup.org/onlinepubs/009695399/
 #define _POSIX_C_SOURCE 200112L
-#include <string.h>
-#include "ocstack.h"
-#include "ocstackinternal.h"
-#include "ocresourcehandler.h"
-#include "logger.h"
-#include "debug.h"
-#include "cJSON.h"
-/// Module Name
-#include <stdio.h>
-
-#define WITH_GROUPACTION 1
 
+#include "occollection.h"
+#include "ocpayload.h"
+#include "ocstack.h"
 #include "oicgroup.h"
+#include "oic_string.h"
+#include "payload_logging.h"
 
-#define TAG PCF("occollection")
-
-#define NUM_PARAM_IN_QUERY  2
-
-static OCStackResult CheckRTParamSupport(const OCResource* resource, const char* rtPtr)
-{
-    OCResourceType* rTPointer = resource->rsrcType;
-    while (rTPointer)
-    {
-        if( strcmp (rTPointer->resourcetypename, rtPtr) == 0)
-            return OC_STACK_OK;
-
-        rTPointer = rTPointer->next;
-    }
-    return OC_STACK_ERROR;
-}
-
-static OCStackResult CheckIFParamSupport(const OCResource* resource, const char* ifPtr)
-{
-    OCResourceInterface* iFPointer = resource->rsrcInterface;
-    while (iFPointer)
-    {
-        if( strcmp (iFPointer->name, ifPtr) == 0)
-             return OC_STACK_OK;
-
-        iFPointer = iFPointer->next;
-    }
-    return OC_STACK_ERROR;
-}
+#define TAG "OIC_RI_COLLECTION"
 
-static OCStackResult
-ValidateQuery (const unsigned char *query, OCResourceHandle resource,
-                             OCStackIfTypes *ifParam, char **rtParam)
+static bool AddRTSBaslinePayload(OCRepPayload **linkArray, int size, OCRepPayload **colPayload)
 {
-    uint8_t numFields = 0, numParam;
-
-    //TODO: Query and URL validation is being done for virtual resource case
-    // using ValidateUrlQuery function. We should be able to merge it with this
-    // function.
-    OC_LOG(INFO, TAG, PCF("Entering ValidateQuery"));
-
-    if (!query)
-        return OC_STACK_ERROR;
-
-    if (!(*query))
-    {
-        // Query string is empty
-        OC_LOG_V(INFO, TAG, PCF("Empty query string, use default IF and RT"));
-        *ifParam = STACK_IF_DEFAULT;
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
-        return OC_STACK_OK;
-    }
-
-    // Break the query string to validate it and determine IF and RT parameters
-    // Validate there are atmost 2 parameters in string and that one is 'if' and other 'rt'
-    char *endStr, *ifPtr = NULL, *rtPtr = NULL;
-    char *token = strtok_r ((char *)query, "&", &endStr);
-
-    // External loop breaks query string into fields using the & separator
-    while (token != NULL)
+    size_t arraySize = 0;
+    for (int j = 0; j < size; j++)
     {
-        numFields++;
-        char *endToken;
-        char *innerToken = strtok_r (token, "=", &endToken);
-        numParam = 0;
-
-        // Internal loop parses the field to extract values (parameters) assigned to each field
-        while (innerToken != NULL)
-        {
-            numParam++;
-            if (strcmp (innerToken, OC_RSRVD_INTERFACE) == 0)
-            {
-                // Determine the value of IF parameter
-                innerToken = strtok_r (NULL, "=", &endToken);
-                ifPtr = innerToken;
-            } else if (strcmp (innerToken, OC_RSRVD_RESOURCE_TYPE) == 0) {
-                // Determine the value of RT parameter
-                innerToken = strtok_r (NULL, "=", &endToken);
-                rtPtr = innerToken;
-            } else {
-                innerToken = strtok_r (NULL, "=", &endToken);
-            }
-        }
-        if (numParam != 2)
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+        char **rt = NULL;
+        OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+        arraySize += rtDim[0];
+        for (size_t l = 0; l < rtDim[0]; l++)
         {
-            // Query parameter should be of the form if=<string>. String should not have & or =
-            return OC_STACK_INVALID_QUERY;
+            OICFree(rt[l]);
         }
-        token = strtok_r (NULL, "&", &endStr);
-    }
-    if (numFields > NUM_PARAM_IN_QUERY)
-    {
-        // M1 release supports one IF value, one RT value and no other params
-        return OC_STACK_INVALID_QUERY;
+        OICFree(rt);
     }
 
-    if (ifPtr)
-    {
-        if(CheckIFParamSupport((OCResource *)resource, ifPtr) != OC_STACK_OK)
-        {
-            return OC_STACK_INVALID_QUERY;
-        }
-        if (strcmp (ifPtr, OC_RSRVD_INTERFACE_DEFAULT) == 0)
-        {
-            *ifParam = STACK_IF_DEFAULT;
-        }
-        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_LL) == 0)
-        {
-            *ifParam = STACK_IF_LL;
-        }
-        else if (strcmp (ifPtr, OC_RSRVD_INTERFACE_BATCH) == 0)
-        {
-            *ifParam = STACK_IF_BATCH;
-        }
-        else if(strcmp (ifPtr, OC_RSRVD_INTERFACE_GROUP) == 0)
-        {
-            *ifParam = STACK_IF_GROUP;
-        }
-        else
-        {
-            return OC_STACK_ERROR;
-        }
-    }
-    else
+    for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, arraySize++);
+
+    OIC_LOG_V(DEBUG, TAG, "Number of RTS elements : %zd", arraySize);
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {arraySize, 0, 0};
+    char **rts = (char **)OICMalloc(sizeof(char *) * arraySize);
+    if (!rts)
     {
-        // IF not specified in query, use default IF
-        *ifParam = STACK_IF_DEFAULT;
+        OIC_LOG(ERROR, TAG, "Memory allocation failed!");
+        return OC_STACK_NO_MEMORY;
     }
-
-    if (rtPtr)
+    int k = 0;
+    for (int j = 0; j < size; j++)
     {
-        if (CheckRTParamSupport((OCResource *)resource, rtPtr) == OC_STACK_OK)
-        {
-            *rtParam = rtPtr;
-        }
-        else
+        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+        char **rt = NULL;
+        OCRepPayloadGetStringArray(linkArray[j], OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+        for (size_t l = 0; l < rtDim[0]; l++)
         {
-            return OC_STACK_INVALID_QUERY;
+            rts[k++] = OICStrdup(rt[l]);
+            OICFree(rt[l]);
         }
+        OICFree(rt);
     }
-    else
+    for (OCStringLL *rsrcType = (*colPayload)->types; rsrcType; rsrcType = rsrcType->next, size++)
     {
-        // RT not specified in query. Use the first resource type for the resource as default.
-        *rtParam = (char *) OCGetResourceTypeName (resource, 0);
+        rts[k++] = OICStrdup(rsrcType->value);
     }
-    OC_LOG_V(INFO, TAG, "Query params: IF = %d, RT = %s", *ifParam, *rtParam);
 
-    return OC_STACK_OK;
+    return OCRepPayloadSetStringArrayAsOwner(*colPayload, OC_RSRVD_RTS, rts, dim);
 }
 
-
-static OCStackResult BuildRootResourceJSON(OCResource *resource,
-        unsigned char * bufferPtr, uint16_t *remaining)
+static OCStackResult SendResponse(const OCRepPayload *payload, const OCEntityHandlerRequest *ehRequest,
+    const OCResource* collResource, OCEntityHandlerResult ehResult)
 {
-    OCStackResult ret = OC_STACK_ERROR;
-    cJSON *resObj;
-    char *jsonStr;
-    uint16_t jsonLen;
-
-    OC_LOG(INFO, TAG, PCF("Entering BuildRootResourceJSON"));
-    resObj = cJSON_CreateObject();
+    OCEntityHandlerResponse response = {0};
+    response.ehResult = ehResult;
+    response.payload = (OCPayload*)payload;
+    response.persistentBufferFlag = 0;
+    response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
+    response.resourceHandle = (OCResourceHandle) collResource;
+    return OCDoResponse(&response);
+}
 
-    if (resource)
-    {
-        cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resource->uri));
-    }
-    jsonStr = cJSON_PrintUnformatted (resObj);
-    jsonLen = strlen(jsonStr);
-    if (jsonLen < *remaining)
+uint8_t GetNumOfResourcesInCollection(const OCResource *collResource)
+{
+    uint8_t size = 0;
+    for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+        tempChildResource; tempChildResource = tempChildResource->next)
     {
-        strcpy((char*) bufferPtr, jsonStr);
-        *remaining -= jsonLen;
-        bufferPtr += jsonLen;
-        ret = OC_STACK_OK;
+        size++;
     }
-
-    cJSON_Delete (resObj);
-    free (jsonStr);
-
-    return ret;
+    return size;
 }
 
-
-static OCStackResult
-HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
-                       uint8_t filterOn, char *filterValue)
+static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest, char *ifQueryParam)
 {
-    OCStackResult ret = OC_STACK_ERROR;
-    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
-    size_t jsonbufferLength = 0;
-    uint16_t remaining = 0;
-    unsigned char * ptr = NULL;
-    OCResource * collResource = (OCResource *) ehRequest->resource;
-
-    ptr = jsonbuffer;
-    remaining = MAX_RESPONSE_LENGTH;
-
-    ret = BuildRootResourceJSON(collResource, ptr, &remaining);
-    ptr += strlen((char*)ptr);
+    if (!ehRequest)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    if (ret == OC_STACK_OK && remaining >= (sizeof(OC_JSON_SEPARATOR) + 1))
+    OCResource *collResource = (OCResource *)ehRequest->resource;
+    if (!collResource)
     {
-        *ptr = OC_JSON_SEPARATOR;
-        ptr++;
-        remaining--;
+        return OC_STACK_INVALID_PARAM;
     }
-    else
+
+    uint8_t size = GetNumOfResourcesInCollection(collResource);
+    OCRepPayload *colPayload = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    int i = 0;
+    OCStackResult ret = OC_STACK_OK;
+    size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0};
+    OCRepPayload **linkArr = (OCRepPayload **)OICCalloc(size, sizeof(OCRepPayload *));
+    VERIFY_PARAM_NON_NULL(TAG, linkArr, "Failed creating LinkArray");
+
+    for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+        tempChildResource && ret == OC_STACK_OK; tempChildResource = tempChildResource->next)
     {
-        ret = OC_STACK_ERROR;
+        OCResource* temp = tempChildResource->rsrcResource;
+        if (temp)
+        {
+            ret = BuildResponseRepresentation(temp, &linkArr[i++], &ehRequest->devAddr);
+        }
     }
-    *(ptr + 1) = '\0';
 
     if (ret == OC_STACK_OK)
     {
-        for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+        colPayload = OCRepPayloadCreate();
+        if (colPayload)
         {
-            OCResource* temp = collResource->rsrcResources[i];
-            if (temp)
+            if (0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, ifQueryParam))
             {
-                //TODO : Update needed here to get correct connectivity type
-                //from ServerRequest data structure
-                ret = BuildVirtualResourceResponse(temp, filterOn, filterValue,
-                         (char*)ptr, &remaining, CA_WIFI );
-                if (ret != OC_STACK_OK)
+                //TODO : Add resource type filtering once collections
+                // start supporting queries.
+                OCRepPayloadAddResourceType(colPayload, OC_RSRVD_RESOURCE_TYPE_COLLECTION);
+                for (OCResourceType *types = collResource->rsrcType; types; types = types->next)
                 {
-                    break;
+                    if (0 != strcmp(OC_RSRVD_RESOURCE_TYPE_COLLECTION, types->resourcetypename))
+                    {
+                        OCRepPayloadAddResourceType(colPayload, types->resourcetypename);
+                    }
                 }
-                ptr += strlen((char*)ptr);
-                if (collResource->rsrcResources[i+1] && remaining > sizeof(OC_JSON_SEPARATOR))
+                for (OCResourceInterface *itf = collResource->rsrcInterface; itf; itf = itf->next)
                 {
-                    *ptr = OC_JSON_SEPARATOR;
-                    ptr++;
-                    remaining--;
+                    OCRepPayloadAddInterface(colPayload, itf->name);
                 }
-                *(ptr + 1) = '\0';
-            }
-            else
-            {
-                break;
+                AddRTSBaslinePayload(linkArr, i, &colPayload);
             }
+            OCRepPayloadSetPropObjectArrayAsOwner(colPayload, OC_RSRVD_LINKS, linkArr, dim);
         }
     }
 
-    jsonbufferLength = strlen((const char *)jsonbuffer);
-    if(ret == OC_STACK_OK && jsonbufferLength)
+exit:
+    if (ret == OC_STACK_OK)
     {
-        OCEntityHandlerResponse response = {0};
-        response.ehResult = OC_EH_OK;
-        response.payload = jsonbuffer;
-        response.payloadSize = jsonbufferLength + 1;
-        response.persistentBufferFlag = 0;
-        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
-        response.resourceHandle = (OCResourceHandle) collResource;
-        ret = OCDoResponse(&response);
+        ehResult = OC_EH_OK;
     }
+    else
+    {
+        ehResult = (ret == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR;
+    }
+    ret = SendResponse(colPayload, ehRequest, collResource, ehResult);
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)colPayload);
+    OCRepPayloadDestroy(colPayload);
     return ret;
 }
 
-static OCStackResult
-HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
+static OCStackResult HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
 {
-    OCStackResult stackRet = OC_STACK_ERROR;
-    OCEntityHandlerResult ehResult = OC_EH_ERROR;
-    unsigned char jsonbuffer[MAX_RESPONSE_LENGTH] = {0};
-    size_t jsonbufferLength = 0;
-    uint16_t remaining = 0;
-    unsigned char * ptr = NULL;
-    OCResource * collResource = (OCResource *) ehRequest->resource;
-
-    ptr = jsonbuffer;
-    remaining = MAX_RESPONSE_LENGTH;
-
-    stackRet = BuildRootResourceJSON(collResource, ptr, &remaining);
-    ptr += strlen((char*)ptr);
-    *(ptr + 1) = '\0';
-
-    jsonbufferLength = strlen((const char *)jsonbuffer);
-    if(jsonbufferLength)
+    if (!ehRequest)
     {
-        OCEntityHandlerResponse response = {0};
-        response.ehResult = OC_EH_OK;
-        response.payload = jsonbuffer;
-        response.payloadSize = jsonbufferLength + 1;
-        response.persistentBufferFlag = 0;
-        response.requestHandle = (OCRequestHandle) ehRequest->requestHandle;
-        response.resourceHandle = (OCResourceHandle) collResource;
-        stackRet = OCDoResponse(&response);
+        return OC_STACK_INVALID_PARAM;
     }
 
+    OCStackResult stackRet = OC_STACK_OK;
+    char *storeQuery = NULL;
+    OCResource *collResource = (OCResource *)ehRequest->resource;
+
     if (stackRet == OC_STACK_OK)
     {
-        for  (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+
+        if (collResource->rsrcChildResourcesHead)
         {
-            OCResource* temp = collResource->rsrcResources[i];
-            if (temp)
+            storeQuery = ehRequest->query;
+            ehRequest->query = NULL;
+            OIC_LOG_V(DEBUG, TAG, "Query : %s", ehRequest->query);
+        }
+
+        uint8_t numRes = 0;
+        for (OCChildResource *tempChildResource = collResource->rsrcChildResourcesHead;
+            tempChildResource; tempChildResource = tempChildResource->next, numRes++)
+        {
+            OCResource* tempRsrcResource = tempChildResource->rsrcResource;
+            if (tempRsrcResource)
             {
                 // Note that all entity handlers called through a collection
                 // will get the same pointer to ehRequest, the only difference
                 // is ehRequest->resource
-                ehRequest->resource = (OCResourceHandle) temp;
-
-                ehResult = temp->entityHandler(OC_REQUEST_FLAG, ehRequest);
+                ehRequest->resource = (OCResourceHandle) tempRsrcResource;
+                OCEntityHandlerResult ehResult = tempRsrcResource->entityHandler(OC_REQUEST_FLAG,
+                                           ehRequest, tempRsrcResource->entityHandlerCallbackParam);
 
                 // The default collection handler is returning as OK
-                if(stackRet != OC_STACK_SLOW_RESOURCE)
+                if (stackRet != OC_STACK_SLOW_RESOURCE)
                 {
                     stackRet = OC_STACK_OK;
                 }
                 // if a single resource is slow, then entire response will be treated
                 // as slow response
-                if(ehResult == OC_EH_SLOW)
+                if (ehResult == OC_EH_SLOW)
                 {
-                    OC_LOG(INFO, TAG, PCF("This is a slow resource"));
-                    ((OCServerRequest *)ehRequest->requestHandle)->slowFlag = 1;
+                    OIC_LOG(INFO, TAG, "This is a slow resource");
+                    OCServerRequest *request =
+                            GetServerRequestUsingHandle(ehRequest->requestHandle);
+                    if (request)
+                    {
+                        request->slowFlag = 1;
+                    }
                     stackRet = EntityHandlerCodeToOCStackCode(ehResult);
                 }
             }
@@ -357,118 +240,71 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
         }
         ehRequest->resource = (OCResourceHandle) collResource;
     }
+    ehRequest->query = storeQuery;
     return stackRet;
 }
 
-uint8_t GetNumOfResourcesInCollection (OCResource *resource)
+OCStackResult DefaultCollectionEntityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest *ehRequest)
 {
-    uint8_t num = 0;
-    for (int i = 0; i < MAX_CONTAINED_RESOURCES; i++)
+    if (!ehRequest || !ehRequest->query)
     {
-        if (resource->rsrcResources[i])
-        {
-            num++;
-        }
+        return OC_STACK_INVALID_PARAM;
     }
-    return num;
-}
-
-
-OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag,
-                                              OCEntityHandlerRequest *ehRequest)
-{
-    OCStackResult result = OC_STACK_ERROR;
-    OCStackIfTypes ifQueryParam = STACK_IF_INVALID;
-    char *rtQueryParam = NULL;
-
-    OC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
-
-    if (flag != OC_REQUEST_FLAG)
+    // Delete is not supported for any interface query method.
+    if (ehRequest->method == OC_REST_DELETE || flag != OC_REQUEST_FLAG)
+    {
         return OC_STACK_ERROR;
+    }
+    OIC_LOG_V(INFO, TAG, "DefaultCollectionEntityHandler with query %s", ehRequest->query);
 
-    result = ValidateQuery ((const unsigned char *)ehRequest->query,
-                            ehRequest->resource, &ifQueryParam, &rtQueryParam);
-
+    char *ifQueryParam = NULL;
+    char *rtQueryParam = NULL;
+    OCStackResult result = ExtractFiltersFromQuery(ehRequest->query, &ifQueryParam, &rtQueryParam);
     if (result != OC_STACK_OK)
-        return result;
+    {
+        result = OC_STACK_NO_RESOURCE;
+        goto exit;
+    }
+    if (!ifQueryParam)
+    {
+        ifQueryParam = OICStrdup(OC_RSRVD_INTERFACE_LL);
+    }
 
-  
-    if(!((ehRequest->method == OC_REST_GET) || 
-        (ehRequest->method == OC_REST_PUT) ||
-        (ehRequest->method == OC_REST_POST)))
-        return OC_STACK_ERROR;
+    VERIFY_PARAM_NON_NULL(TAG, ifQueryParam, "Invalid Parameter root");
 
-    if (ehRequest->method == OC_REST_GET)
+    if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL) || 0 == strcmp (ifQueryParam, OC_RSRVD_INTERFACE_DEFAULT))
     {
-        switch (ifQueryParam)
+        if (ehRequest->method == OC_REST_PUT || ehRequest->method == OC_REST_POST)
         {
-            case STACK_IF_DEFAULT:
-                // Get attributes of collection resource and properties of contined resource
-                // M1 release does not support attributes for collection resource, so the GET
-                // operation is same as the GET on LL interface.
-                OC_LOG(INFO, TAG, PCF("STACK_IF_DEFAULT"));
-                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-            case STACK_IF_LL:
-                OC_LOG(INFO, TAG, PCF("STACK_IF_LL"));
-                return HandleLinkedListInterface(ehRequest, STACK_RES_DISCOVERY_NOFILTER, NULL);
-
-            case STACK_IF_BATCH:
-                OC_LOG(INFO, TAG, PCF("STACK_IF_BATCH"));
-                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
-                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
-                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                return HandleBatchInterface(ehRequest);
-            case STACK_IF_GROUP:
-                return BuildCollectionGroupActionJSONResponse(OC_REST_GET/*flag*/,
-                        (OCResource *) ehRequest->resource, ehRequest);
-            default:
-                return OC_STACK_ERROR;
+            result =  OC_STACK_ERROR;
         }
-    } else if (ehRequest->method == OC_REST_PUT) {
-        switch (ifQueryParam)
+        else
         {
-            case STACK_IF_DEFAULT:
-                // M1 release does not support PUT on default interface
-                return OC_STACK_ERROR;
-
-            case STACK_IF_LL:
-                // LL interface only supports GET
-                return OC_STACK_ERROR;
-
-            case STACK_IF_BATCH:
-                ((OCServerRequest *)ehRequest->requestHandle)->ehResponseHandler = HandleAggregateResponse;
-                ((OCServerRequest *)ehRequest->requestHandle)->numResponses =
-                        GetNumOfResourcesInCollection((OCResource *)ehRequest->resource) + 1;
-                return HandleBatchInterface(ehRequest);
-
-            case STACK_IF_GROUP:
-            {
-                OC_LOG_V(INFO, TAG, "IF_COLLECTION PUT with request ::\n%s\n ",
-                        ehRequest->reqJSONPayload);
-                return BuildCollectionGroupActionJSONResponse(OC_REST_PUT/*flag*/,
-                        (OCResource *) ehRequest->resource, ehRequest);
-            }
-            default:
-                return OC_STACK_ERROR;
+            result = HandleLinkedListInterface(ehRequest, ifQueryParam);
         }
     }
-    else if (ehRequest->method == OC_REST_POST)
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_BATCH))
     {
-
-        switch (ifQueryParam)
+        OCServerRequest *request = GetServerRequestUsingHandle(ehRequest->requestHandle);
+        if (request)
         {
-            case STACK_IF_GROUP:
-            {
-                OC_LOG_V(INFO, TAG, "IF_COLLECTION POST with request :: \n%s\n ",
-                        ehRequest->reqJSONPayload);
-                return BuildCollectionGroupActionJSONResponse(OC_REST_POST/*flag*/,
-                        (OCResource *) ehRequest->resource, ehRequest);
-            }
-            default:
-                return OC_STACK_ERROR;
+            request->numResponses = GetNumOfResourcesInCollection((OCResource *)ehRequest->resource);
+            request->ehResponseHandler = HandleAggregateResponse;
+            result = HandleBatchInterface(ehRequest);
         }
     }
+    else if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_GROUP))
+    {
+        OIC_LOG_V(INFO, TAG, "IF_COLLECTION %d with request ::\n", ehRequest->method);
+        OIC_LOG_PAYLOAD(INFO, ehRequest->payload);
+        result = BuildCollectionGroupActionCBORResponse(ehRequest->method, (OCResource *) ehRequest->resource, ehRequest);
+    }
+exit:
+    if (result != OC_STACK_OK)
+    {
+        result = SendResponse(NULL, ehRequest, (OCResource *)ehRequest->resource, OC_EH_BAD_REQ);
+    }
+    OICFree(ifQueryParam);
+    OICFree(rtQueryParam);
     return result;
 }
-