Commit 2d036285 authored by koushik.girijala's avatar koushik.girijala Committed by Nathan Heldt-Sheller

[IOT-3055]Fixed Handle collection resource payload

Fixed Handle collection resource payload for all interfaces
And also fixed batch interface for normal respources

Change-Id: I35c11597f2f55d1e3d40317209fe127cdd076d46
Signed-off-by: default avatarkoushik.girijala <g.koushik@samsung.com>
parent 57a24fe3
......@@ -1447,12 +1447,23 @@ typedef enum
PAYLOAD_TYPE_INTROSPECTION
} OCPayloadType;
/** Enum to describe payload interface interface.*/
/** Enum to describe payload representation for collection and non collection resources.*/
typedef enum
{
PAYLOAD_NON_BATCH_INTERFACE,
PAYLOAD_BATCH_INTERFACE
} OCPayloadInterfaceType;
/** Used for collection resource when the payload to be created for representation
* with one or more resource representations should be created as an array of object/ objects
* 1. Collection resource with Link list and Batch interface etc.
*/
PAYLOAD_REP_ARRAY,
/** Used for Non Collection resources when payload to be created for the representation with
* zero or one child representation should be created as an Object and the payload with more
* than one representation should be created as an Array of Objects.
* 1. Non Collection resource with Link list, Default interfaces etc.
* 2. Collection resource with Default interface.
*/
PAYLOAD_REP_OBJECT_ARRAY
} OCPayloadRepresentationType;
/**
* A generic struct representing a payload returned from a resource operation
......@@ -1533,11 +1544,11 @@ typedef struct OCRepPayloadValue
typedef struct OCRepPayload
{
OCPayload base;
OCPayloadInterfaceType ifType;
char* uri;
OCStringLL* types;
OCStringLL* interfaces;
OCRepPayloadValue* values;
OCPayloadRepresentationType repType;
struct OCRepPayload* next;
} OCRepPayload;
......
......@@ -114,7 +114,8 @@ void OC_CALL OCRepPayloadAppend(OCRepPayload* parent, OCRepPayload* child);
bool OC_CALL OCRepPayloadSetUri(OCRepPayload* payload, const char* uri);
bool OC_CALL OCRepPayloadSetInterfaceType(OCRepPayload* payload, OCPayloadInterfaceType type);
bool OC_CALL OCRepPayloadSetPayloadRepType(OCRepPayload* payload,
OCPayloadRepresentationType type);
bool OC_CALL OCRepPayloadAddResourceType(OCRepPayload* payload, const char* resourceType);
bool OC_CALL OCRepPayloadAddInterface(OCRepPayload* payload, const char* iface);
......
......@@ -120,7 +120,7 @@ OCRepPayloadSetPropStringAsOwner
OCRepPayloadSetStringArray
OCRepPayloadSetStringArrayAsOwner
OCRepPayloadSetUri
OCRepPayloadSetInterfaceType
OCRepPayloadSetPayloadRepType
OCResourcePayloadAddNewEndpoint
OCResourcePayloadAddStringLL
OCSecurityPayloadCreate
......
......@@ -198,6 +198,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
else if(query.find(OC_RSRVD_INTERFACE_LL) != std::string::npos)
{
OCRepPayloadSetUri(payload, gRoomResourceUri);
OCRepPayloadSetPayloadRepType(payload, PAYLOAD_REP_ARRAY);
OCRepPayload *tempPayload = OCRepPayloadCreate();
OCRepPayloadSetUri(tempPayload, gLightResourceUri);
......@@ -211,7 +212,7 @@ OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,
{
OCRepPayloadSetUri(payload, gRoomResourceUri);
OCRepPayloadSetInterfaceType(payload, PAYLOAD_BATCH_INTERFACE);
OCRepPayloadSetPayloadRepType(payload, PAYLOAD_REP_ARRAY);
OCRepPayload *tempPayload = OCRepPayloadCreate();
OCRepPayloadSetUri(tempPayload, gLightResourceUri);
......
......@@ -190,6 +190,15 @@ static OCStackResult HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest
ret = OC_STACK_OK;
}
exit:
if (0 == strcmp(ifQueryParam, OC_RSRVD_INTERFACE_LL))
{
OCRepPayloadSetPayloadRepType(colPayload, PAYLOAD_REP_ARRAY);
}
else
{
OCRepPayloadSetPayloadRepType(colPayload, PAYLOAD_REP_OBJECT_ARRAY);
}
if (ret == OC_STACK_OK)
{
ehResult = OC_EH_OK;
......@@ -583,7 +592,7 @@ OCRepPayload** BuildCollectionLinksPayloadArray(const char* resourceUri,
OIC_LOG(ERROR, TAG, "Failed setting rel property");
result = false;
goto exit;
}
}
}
result = true;
}
......
......@@ -85,7 +85,7 @@ OCRepPayload* OC_CALL OCRepPayloadCreate(void)
return NULL;
}
payload->ifType = PAYLOAD_NON_BATCH_INTERFACE;
payload->repType = PAYLOAD_REP_OBJECT_ARRAY;
payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
return payload;
......@@ -496,14 +496,14 @@ bool OC_CALL OCRepPayloadSetUri(OCRepPayload* payload, const char* uri)
return payload->uri != NULL;
}
bool OC_CALL OCRepPayloadSetInterfaceType(OCRepPayload* payload, OCPayloadInterfaceType type)
bool OC_CALL OCRepPayloadSetPayloadRepType(OCRepPayload* payload, OCPayloadRepresentationType type)
{
if (!payload)
{
return false;
}
payload->ifType = type;
payload->repType = type;
return true;
}
......@@ -1634,7 +1634,7 @@ OCRepPayload* OC_CALL OCRepPayloadBatchClone(const OCRepPayload* repPayload)
}
clone->types = CloneOCStringLL(repPayload->types);
clone->ifType = repPayload->ifType;
clone->repType = repPayload->repType;
clone->interfaces = CloneOCStringLL(repPayload->interfaces);
clone->values = OCRepPayloadValueClone(repPayload->values);
OCRepPayloadSetPropObjectAsOwner(newPayload, OC_RSRVD_REPRESENTATION, clone);
......
......@@ -942,28 +942,36 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s
cbor_encoder_init(&encoder, outPayload, *size, 0);
int isBatch = 0;
if (payload != NULL && payload->ifType == PAYLOAD_BATCH_INTERFACE)
size_t objectCount = 0;
for (OCRepPayload *temp = payload; temp; temp = temp->next)
{
isBatch = 1;
objectCount++;
}
size_t arrayCount = 0;
for (OCRepPayload *temp = payload; temp; temp = temp->next)
int isColResource = 0;
if (payload != NULL && (payload->repType == PAYLOAD_REP_ARRAY))
{
arrayCount++;
isColResource = 1;
}
// As per OCF spec
// 1. Create an array of objects for collection resource payload when 0 <=objectCount <=1
// for ll and batch interfaces.
// 2. Create single object for non collection resource payload when 0 <= objectCount <= 1
// for non batch interfaces.
// 3. Create an array of objects for any kind of resource when objectCount > 1 and for any
// interfaces.
CborEncoder rootArray;
if (arrayCount > 1 || isBatch)
if ((objectCount > 1) ||(objectCount <= 1 && isColResource))
{
err |= cbor_encoder_create_array(&encoder, &rootArray, arrayCount);
err |= cbor_encoder_create_array(&encoder, &rootArray, objectCount);
VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed adding rep root map");
}
while (payload != NULL && (err == CborNoError))
{
CborEncoder rootMap;
err |= cbor_encoder_create_map(((arrayCount == 1 && !isBatch)? &encoder: &rootArray),
err |= cbor_encoder_create_map(((objectCount == 1 && !isColResource)? &encoder: &rootArray),
&rootMap, CborIndefiniteLength);
VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed creating root map");
......@@ -971,12 +979,13 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s
VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed setting rep payload");
// Close main array
err |= cbor_encoder_close_container(((arrayCount == 1 && !isBatch) ? &encoder: &rootArray),
err |= cbor_encoder_close_container(((objectCount == 1 && !isColResource) ? &encoder: &rootArray),
&rootMap);
VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed closing root map");
payload = payload->next;
}
if (arrayCount > 1 || isBatch)
if (objectCount > 1 || (objectCount <= 1 && isColResource))
{
err |= cbor_encoder_close_container(&encoder, &rootArray);
VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, err, "Failed closing root array");
......
......@@ -875,9 +875,10 @@ OCStackResult HandleAggregateResponse(OCEntityHandlerResponse * ehResponse)
OCRepPayload *newPayload = OCRepPayloadBatchClone((OCRepPayload *)ehResponse->payload);
OCRepPayloadSetPayloadRepType(newPayload, PAYLOAD_REP_ARRAY);
if(!serverResponse->payload)
{
OCRepPayloadSetInterfaceType(newPayload, PAYLOAD_BATCH_INTERFACE);
serverResponse->payload = (OCPayload *)newPayload;
}
else
......
......@@ -3544,6 +3544,44 @@ OCStackResult OC_CALL OCDoRequest(OCDoHandle *handle,
}
requestInfo.info.payloadVersion = payloadVersion;
// for fixing collection resource POST/PUT requests
if (payload->type == PAYLOAD_TYPE_REPRESENTATION)
{
OCRepPayload *repPayload = (OCRepPayload *)payload;
// PAYLOAD_REP_ARRAY is set only for case of collection resource
// Here we are differentiating DEFAULT with LL and BATCH interface
// For DEFAULT interface repType will be PAYLOAD_REP_OBJECT_ARRAY
if (requestUri && repPayload->repType == PAYLOAD_REP_ARRAY)
{
char *interfaceName = NULL;
char *rtTypeName = NULL;
char *uriQuery = NULL;
char *uriWithoutQuery = NULL;
if (OC_STACK_OK == getQueryFromUri(requestUri, &uriQuery, &uriWithoutQuery))
{
if (OC_STACK_OK == ExtractFiltersFromQuery(uriQuery, &interfaceName,
&rtTypeName))
{
if (interfaceName &&
(0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceName)))
{
repPayload->repType = PAYLOAD_REP_OBJECT_ARRAY;
}
}
else if (NULL == uriQuery)
{
repPayload->repType = PAYLOAD_REP_OBJECT_ARRAY;
}
}
OICFree(interfaceName);
OICFree(rtTypeName);
OICFree(uriQuery);
OICFree(uriWithoutQuery);
}
}
if ((result =
OCConvertPayload(payload, CAToOCPayloadFormat(requestInfo.info.payloadFormat),
&requestInfo.info.payload, &requestInfo.info.payloadSize))
......
......@@ -106,6 +106,10 @@ namespace OC
InterfaceType getInterfaceType() const;
void setIsCollectionResource(bool isColResource);
bool isCollectionResource() const;
void addChild(const OCRepresentation&);
void clearChildren();
......@@ -480,6 +484,7 @@ namespace OC
std::vector<std::string> m_dataModelVersions;
InterfaceType m_interfaceType;
bool m_isCollectionResource;
};
std::ostream& operator <<(std::ostream& os, const OCRepresentation::AttributeItem& ai);
......
......@@ -52,7 +52,8 @@ namespace OC
m_representation{},
m_requestHandle{nullptr},
m_resourceHandle{nullptr},
m_responseResult{}
m_responseResult{},
m_isCollectionResource{}
{
}
......@@ -64,7 +65,8 @@ namespace OC
m_representation(std::move(o.m_representation)),
m_requestHandle(std::move(o.m_requestHandle)),
m_resourceHandle(std::move(o.m_resourceHandle)),
m_responseResult(std::move(o.m_responseResult))
m_responseResult(std::move(o.m_responseResult)),
m_isCollectionResource(std::move(o.m_isCollectionResource))
{
}
OCResourceResponse& operator=(OCResourceResponse&& o)
......@@ -76,6 +78,7 @@ namespace OC
m_requestHandle = std::move(o.m_requestHandle);
m_resourceHandle = std::move(o.m_resourceHandle);
m_responseResult = std::move(o.m_responseResult);
m_isCollectionResource = std::move(o.m_isCollectionResource);
}
#else
OCResourceResponse(OCResourceResponse&&) = default;
......@@ -140,6 +143,29 @@ namespace OC
m_responseResult = responseResult;
}
/**
* API to set the entire resource attribute representation
* @param rep reference to the resource's representation
* @param iface specifies the interface
*/
void setResourceRepresentation(OCRepresentation& rep, std::string iface,
bool isCollectionResource)
{
m_interface = iface;
m_representation = rep;
m_isCollectionResource = isCollectionResource;
}
/**
* API to set the entire resource attribute representation
* @param rep rvalue reference to the resource's representation
* @param iface specifies the interface
*/
void setResourceRepresentation(OCRepresentation&& rep, std::string iface,
bool isCollectionResource) {
setResourceRepresentation(rep, iface, isCollectionResource);
}
/**
* API to set the entire resource attribute representation
* @param rep reference to the resource's representation
......@@ -148,6 +174,7 @@ namespace OC
void setResourceRepresentation(OCRepresentation& rep, std::string iface) {
m_interface = iface;
m_representation = rep;
m_isCollectionResource = false;
}
/**
......@@ -167,6 +194,7 @@ namespace OC
// Call the default
m_interface = DEFAULT_INTERFACE;
m_representation = rep;
m_isCollectionResource = false;
}
/**
......@@ -185,6 +213,7 @@ namespace OC
OCRequestHandle m_requestHandle;
OCResourceHandle m_resourceHandle;
OCEntityHandlerResult m_responseResult;
bool m_isCollectionResource;
private:
friend class InProcServerWrapper;
......@@ -207,6 +236,8 @@ namespace OC
first.setInterfaceType(InterfaceType::DefaultParent);
}
first.setIsCollectionResource(m_isCollectionResource);
inf.addRepresentation(first);
for(const OCRepresentation& rep : m_representation.getChildren())
......@@ -249,6 +280,14 @@ namespace OC
return m_headerOptions;
}
/**
* Get the resource type collection/non-collection
*/
bool isCollectionResource() const
{
return m_isCollectionResource;
}
/**
* This API retrieves the request handle
*
......
......@@ -83,9 +83,13 @@ namespace OC
if (!root)
{
root = r.getPayload();
if (r.getInterfaceType() == InterfaceType::BatchParent)
if (r.isCollectionResource())
{
root->ifType = PAYLOAD_BATCH_INTERFACE;
root->repType = PAYLOAD_REP_ARRAY;
}
else
{
root->repType = PAYLOAD_REP_OBJECT_ARRAY;
}
}
else
......@@ -403,6 +407,16 @@ namespace OC
return m_interfaceType;
}
void OCRepresentation::setIsCollectionResource(bool isColResource)
{
m_isCollectionResource = isColResource;
}
bool OCRepresentation::isCollectionResource() const
{
return m_isCollectionResource;
}
size_t calcArrayDepth(const size_t dimensions[MAX_REP_ARRAY_DEPTH])
{
if (dimensions[0] == 0)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment