/* ****************************************************************************
*
* deleteIndividualContextEntityAttribute - 
*
* DELETE /v1/contextEntities/{entityId::id}/attributes/{attributeName}
* DELETE /ngsi10/contextEntities/{entityId::id}/attributes/{attributeName}
*
* Payload In:  None
* Payload Out: StatusCode
*
* URI parameters:
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*   [ attributesFormat=object: makes no sense for this operation as StatusCode is returned ]
*   
* 0. Take care of URI params
* 1. Fill in UpdateContextRequest from URL-path components
* 2. Call postUpdateContext standard service routine
* 3. Translate UpdateContextResponse to StatusCode
* 4. Cleanup and return result
*/
std::string deleteIndividualContextEntityAttribute
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  answer;
  std::string  entityId      = compV[2];
  std::string  entityType    = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  std::string  attributeName = compV[4];
  StatusCode   response;


  // 1. Fill in UpdateContextRequest from URL-path components
  parseDataP->upcr.res.fill(entityId, entityType, "false", attributeName, "", "DELETE");


  // 2. Call postUpdateContext standard service routine
  postUpdateContext(ciP, components, compV, parseDataP);


  // 3. Translate UpdateContextResponse to StatusCode
  response.fill(parseDataP->upcrs.res);


  // 4. Cleanup and return result
  TIMED_RENDER(answer = response.render("", false, false));

  response.release();
  parseDataP->upcr.res.release();

  return answer;
}
/* ****************************************************************************
*
* putEntityAttributeValue -
*
* PUT /v2/entities/<id>/attrs/<attrName>/value
*
* Payload In:  AttributeValue
* Payload Out: None
*
*
* 01. Fill in UpdateContextRequest with data from URI and payload
* 02. Call standard op postUpdateContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string putEntityAttributeValue
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  entityId       = compV[2];
  std::string  attributeName  = compV[4];
  std::string  type           = ciP->uriParam["type"];

  if (forbiddenIdChars(ciP->apiVersion, entityId.c_str(),      NULL) ||
      forbiddenIdChars(ciP->apiVersion, attributeName.c_str(), NULL))
  {
    OrionError oe(SccBadRequest, ERROR_DESC_BAD_REQUEST_INVALID_CHAR_URI, ERROR_BAD_REQUEST);
    ciP->httpStatusCode = oe.code;
    return oe.toJson();
  }

  // 01. Fill in UpdateContextRequest with data from URI and payload
  parseDataP->av.attribute.name = attributeName;
  parseDataP->av.attribute.type = "";  // Overwrite 'none', as no type can be given in 'value' payload
  parseDataP->av.attribute.onlyValue = true;

  std::string err = parseDataP->av.attribute.check(ciP->apiVersion, ciP->requestType);
  if (err != "OK")
  {
    OrionError oe(SccBadRequest, err, "BadRequest");
    ciP->httpStatusCode = oe.code;
    return oe.toJson();
  }
  parseDataP->upcr.res.fill(entityId, &parseDataP->av.attribute, ActionTypeUpdate, type);


  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);

  // 03. Check output from mongoBackend
  std::string answer = "";
  if (parseDataP->upcrs.res.oe.code != SccNone)
  {
    TIMED_RENDER(answer = parseDataP->upcrs.res.oe.toJson());
    ciP->httpStatusCode = parseDataP->upcrs.res.oe.code;
  }
  else
  {
    ciP->httpStatusCode = SccNoContent;
  }

  // 05. Cleanup and return result
  parseDataP->upcr.res.release();

  return answer;
}
/* ****************************************************************************
*
* putAttributeValueInstance - 
*
* PUT /v1/contextEntities/{entity::id}/attributes/{attribute::name}/{metaID}
* PUT /ngsi10/contextEntities/{entity::id}/attributes/{attribute::name}/{metaID}
*
* Payload In:  UpdateContextAttributeRequest
* Payload Out: StatusCode
*
* URI parameters
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that don't use the standard operation QueryContext as there is no Restriction otherwise.
*     Here, entity::type can be empty though, and it is, unless the URI parameter 'entity::type=TYPE' is used.
*
* 01. Check validity of path components VS payload
* 02. Fill in UpdateContextRequest
* 03. Call postUpdateContext
* 04. Fill in StatusCode from UpdateContextResponse
* 05. Render result
* 06. Cleanup and return result
*/
std::string putAttributeValueInstance
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  entityId      = compV[2];
  std::string  attributeName = compV[4];
  std::string  metaID        = compV[5];
  std::string  entityType    = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  std::string  answer;
  StatusCode   response;


  // 01. Check validity of path components VS payload
  Metadata* mP = parseDataP->upcar.res.metadataVector.lookupByName("ID");

  if ((mP != NULL) && (mP->value != metaID))
  {
    std::string details = "unmatching metadata ID value URI/payload: /" + metaID + "/ vs /" + mP->value + "/";
    
    response.fill(SccBadRequest, details);
    answer = response.render(ciP->outFormat, "", false, false);
    parseDataP->upcar.res.release();

    return answer;
  }


  // 02. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(&parseDataP->upcar.res, entityId, entityType, attributeName, metaID, "UPDATE");


  // 03. Call postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);


  // 04. Fill in StatusCode from UpdateContextResponse
  response.fill(parseDataP->upcrs.res);


  // 05. Render result
  answer = response.render(ciP->outFormat, "", false, false);


  // 06. Cleanup and return result
  response.release();
  parseDataP->upcar.res.release();
  parseDataP->upcr.res.release();
  parseDataP->upcrs.res.release();

  return answer;
}
/* ****************************************************************************
*
* deleteAttributeValueInstanceWithTypeAndId - 
*
* DELETE /v1/contextEntities/type/{entity::type}/id/{entity::id}/attributes/{attribute::name}/{metaID}
* DELETE /ngsi10/contextEntities/type/{entity::type}/id/{entity::id}/attributes/{attribute::name}/{metaID}
*
* Mapped Standard Operation: UpdateContextRequest/DELETE
*
* URI params:
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*
* 01. URI parameters
* 02. Check validity of URI params
* 03. Fill in UpdateContextRequest
* 04. Call postUpdateContext standard service routine
* 05. Translate UpdateContextResponse to StatusCode
* 06. Cleanup and return result
*/
std::string deleteAttributeValueInstanceWithTypeAndId
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  StatusCode              response;
  std::string             answer;
  std::string             entityTypeFromUriParam;
  std::string             entityTypeFromPath = compV[3];
  std::string             entityId           = compV[5];
  std::string             attributeName      = compV[7];
  std::string             metaId             = compV[8];


  // 01. URI parameters
  entityTypeFromUriParam    = ciP->uriParam[URI_PARAM_ENTITY_TYPE];


  // 02. Check validity of URI params
  if ((entityTypeFromUriParam != "") && (entityTypeFromUriParam != entityTypeFromPath))
  {
    LM_W(("Bad Input non-matching entity::types in URL"));

    response.fill(SccBadRequest, "non-matching entity::types in URL");

    answer = response.render(ciP->outFormat, "", false, false);

    return answer;
  }


  // 03. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(entityId, entityTypeFromPath, "false", attributeName, metaId, "DELETE");


  // 04. Call postUpdateContext standard service routine
  answer = postUpdateContext(ciP, components, compV, parseDataP);


  // 05. Translate UpdateContextResponse to StatusCode
  response.fill(parseDataP->upcrs.res);


  // 06. Cleanup and return result
  answer = response.render(ciP->outFormat, "", false, false);
  response.release();
  parseDataP->upcr.res.release();

  return answer;
}
/* ****************************************************************************
*
* putEntityAttribute -
*
* PUT /v2/entities/<id>/attrs/<attrName>
*
* Payload In:  None
* Payload Out: Entity Attribute
*
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op postQueryContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string putEntityAttribute
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  answer;
  std::string  entityId       = compV[2];
  std::string  attributeName  = compV[4];

  // 01. Fill in UpdateContextRequest from URL and payload
  parseDataP->attr.attribute.name = attributeName;

  parseDataP->upcr.res.fill(entityId, &parseDataP->attr.attribute, "UPDATE");

  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);


  // 03. Check output from mongoBackend - any errors?
  if (parseDataP->upcrs.res.contextElementResponseVector.size() == 1)
  {
    if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code != SccOk)
    {
      ciP->httpStatusCode = parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code;
    }
  }


  // 04. Prepare HTTP headers
  if ((ciP->httpStatusCode == SccOk) || (ciP->httpStatusCode == SccNone))
  {
    ciP->httpStatusCode = SccNoContent;
  }


  // 05. Cleanup and return result
  parseDataP->upcr.res.release();
  parseDataP->upcrs.res.release();

  if (ciP->httpStatusCode == SccInvalidModification)
  {
    std::string  details = "Request payload is missing some piece of information. Please, check Orion documentation."; 
    OrionError   orionError(SccInvalidModification, details);     

    TIMED_RENDER(answer = orionError.render(ciP, ""));
  }

  return answer;
}
Ejemplo n.º 6
0
/* ****************************************************************************
*
* postEntities - 
*
* POST /v2/entities
*
* Payload In:  Entity
* Payload Out: None
*
* URI parameters:
*   - 
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op postUpdateContext
* 03. Prepare HTTP headers
* 04. Cleanup and return result
*/
std::string postEntities
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entity*  eP = &parseDataP->ent.res;

  if (!legalEntityLength(eP, ciP->servicePath))
  {
    OrionError oe(SccBadRequest, "Too long entity id/type/servicePath combination");
    ciP->httpStatusCode = SccBadRequest;
    eP->release();
    return oe.render(ciP, "");
  }

  // 01. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(eP, "APPEND_STRICT");
  

  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP, true);

  HttpStatusCode rcode = parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code;

  std::string answer;

  // 03. Prepare HTTP headers
  if (rcode == SccOk || rcode == SccNone)
  {
    std::string location = "/v2/entities/" + eP->id;

    ciP->httpHeader.push_back("Location");
    ciP->httpHeaderValue.push_back(location);
    ciP->httpStatusCode = SccCreated;
  }
  else if (rcode == SccInvalidModification)
  {
    OrionError oe(SccInvalidModification, "Entity already exists");
    ciP->httpStatusCode = SccInvalidModification;
    answer = oe.render(ciP, "");
  }


  // 04. Cleanup and return result
  eP->release();

  return answer;
}
Ejemplo n.º 7
0
/* ****************************************************************************
*
* putEntity - 
*
* PUT /v2/entities
*
* Payload In:  Entity
* Payload Out: None
*
* URI parameters:
*   - 
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op putUpdateContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string putEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entity*     eP     = &parseDataP->ent.res;

  eP->id   = compV[2];
  eP->type = ciP->uriParam["type"];

  if (forbiddenIdChars(ciP->apiVersion, compV[2].c_str() , NULL))
  {
    OrionError oe(SccBadRequest, ERROR_DESC_BAD_REQUEST_INVALID_CHAR_URI, ERROR_BAD_REQUEST);
    ciP->httpStatusCode = oe.code;
    return oe.toJson();
  }

  // 01. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(eP, ActionTypeReplace);


  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);

  // 03. Check error
  std::string answer = "";
  if (parseDataP->upcrs.res.oe.code != SccNone )
  {
    TIMED_RENDER(answer = parseDataP->upcrs.res.oe.toJson());
    ciP->httpStatusCode = parseDataP->upcrs.res.oe.code;
  }
  else
  {
    ciP->httpStatusCode = SccNoContent;
  }

  // 04. Cleanup and return result
  eP->release();

  return answer;
}
/* ****************************************************************************
*
* putIndividualContextEntity -
*
* Corresponding Standard Operation: UpdateContext/UPDATE
*
* PUT /v1/contextEntities/{entityId::id}
* PUT /ngsi10/contextEntities/{entityId::id}
*
* Payload In:  UpdateContextElementRequest
* Payload Out: UpdateContextElementResponse
*
* URI parameters:
*   - attributesFormat=object
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*
* 01. Take care of URI params
* 02. Fill in UpdateContextRequest from UpdateContextElementRequest
* 03. Call postUpdateContext standard service routine
* 04. Translate UpdateContextResponse to UpdateContextElementResponse
* 05. Cleanup and return result
*/
std::string putIndividualContextEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string                   answer;
  std::string                   entityId = compV[2];
  UpdateContextElementResponse  response;
  std::string                   entityType;

  bool asJsonObject = (ciP->uriParam[URI_PARAM_ATTRIBUTE_FORMAT] == "object" && ciP->outMimeType == JSON);

  // 01. Take care of URI params
  entityType = ciP->uriParam[URI_PARAM_ENTITY_TYPE];


  // 02. Fill in UpdateContextRequest from UpdateContextElementRequest and entityId
  parseDataP->upcr.res.fill(&parseDataP->ucer.res, entityId, entityType);

  // And, set the UpdateActionType to UPDATE
  parseDataP->upcr.res.updateActionType = ActionTypeUpdate;


  // 03. Call postUpdateContext standard service routine
  postUpdateContext(ciP, components, compV, parseDataP);


  // 04. Translate UpdateContextResponse to UpdateContextElementResponse
  response.fill(&parseDataP->upcrs.res);


  // 05. Cleanup and return result
  TIMED_RENDER(answer = response.toJsonV1(asJsonObject, IndividualContextEntity));


  response.release();
  parseDataP->upcr.res.release();

  return answer;
}
Ejemplo n.º 9
0
/* ****************************************************************************
*
* putEntity - 
*
* PUT /v2/entities
*
* Payload In:  Entity
* Payload Out: None
*
* URI parameters:
*   - 
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op putUpdateContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string putEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entity*  eP = &parseDataP->ent.res;

  eP->id = compV[2];

  // 01. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(eP, "REPLACE");
  

  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);


  // 03. Check output from mongoBackend - any errors?
  if (parseDataP->upcrs.res.contextElementResponseVector.size() == 1)
  {
    if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code != SccOk)
    {
      ciP->httpStatusCode = parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code;
    }
  }


  // 04. Prepare HTTP headers
  if ((ciP->httpStatusCode == SccOk) || (ciP->httpStatusCode == SccNone))
  {
    ciP->httpStatusCode = SccNoContent;
  }


  // 05. Cleanup and return result
  eP->release();

  return "";
}
/* ****************************************************************************
*
* putEntityAttributeValue -
*
* PUT /v2/entities/<id>/attrs/<attrName>/value
*
* Payload In:  AttributeValue
* Payload Out: None
*
*
* 01. Fill in UpdateContextRequest with data from URI and payload
* 02. Call standard op postUpdateContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string putEntityAttributeValue
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  entityId       = compV[2];
  std::string  attributeName  = compV[4];

  // 01. Fill in UpdateContextRequest with data from URI and payload
  parseDataP->av.attribute.name = attributeName;
  parseDataP->upcr.res.fill(entityId, &parseDataP->av.attribute, "UPDATE");


  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);


  // 03. Check output from mongoBackend - any errors?
  if (parseDataP->upcrs.res.contextElementResponseVector.size() == 1)
  {
    if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code != SccOk)
    {
      ciP->httpStatusCode = parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code;
    }
  }


  // 04. Prepare HTTP headers
  if ((ciP->httpStatusCode == SccOk) || (ciP->httpStatusCode == SccNone))
  {
    ciP->httpStatusCode = SccNoContent;
  }


  // 05. Cleanup and return result
  parseDataP->upcr.res.release();

  return "";
}
/* ****************************************************************************
*
* deleteAttributeValueInstance - 
*
* DELETE /v1/contextEntities/{entity::id}/attributes/{attribute::name}/{metaID}
* DELETE /ngsi10/contextEntities/{entity::id}/attributes/{attribute::name}/{metaID}
*
* Payload In:  None
* Payload Out: StatusCode
*
* Mapped Standard Operation: UpdateContextRequest/DELETE
*
* URI params:
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*
* 01. URI parameters
* 02. Fill in UpdateContextRequest
* 03. Call postUpdateContext standard service routine
* 04. Translate UpdateContextResponse to StatusCode
* 05. Cleanup and return result
*
*/
std::string deleteAttributeValueInstance
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  StatusCode              response;
  std::string             answer;
  std::string             entityId      = compV[2];
  std::string             attributeName = compV[4];
  std::string             metaId        = compV[5];
  std::string             entityType;

  // 01. URI parameters
  entityType    = ciP->uriParam[URI_PARAM_ENTITY_TYPE];

  // 02. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(entityId, entityType, "false", attributeName, metaId, "DELETE");

  // 03. Call postUpdateContext standard service routine
  postUpdateContext(ciP, components, compV, parseDataP);


  // 04. Translate UpdateContextResponse to StatusCode
  response.fill(parseDataP->upcrs.res);


  // 05. Cleanup and return result
  TIMED_RENDER(answer = response.render("", false, false));

  response.release();
  parseDataP->upcr.res.release();

  return answer;
}
/* ****************************************************************************
*
* deleteIndividualContextEntity - 
*
* Corresponding Standard Operation: UpdateContext/DELETE
*
* DELETE /v1/contextEntities/{entityId::id}
*
* Payload In:  None
* Payload Out: StatusCode
*
* URI parameters:
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*
* 00. URI params
* 01. Fill in UpdateContextRequest from URL-data + URI params
* 02. Call postUpdateContext standard service routine
* 03. Translate UpdateContextResponse to StatusCode
* 04. If not found, put entity info in details
* 05. Cleanup and return result
*/
std::string deleteIndividualContextEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  answer;
  std::string  entityId   = compV[2];
  std::string  entityType = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  StatusCode   response;

  // 01. Fill in UpdateContextRequest fromURL-data + URI params
  parseDataP->upcr.res.fill(entityId, entityType, "false", "", "", "DELETE");

  // 02. Call postUpdateContext standard service routine
  answer = postUpdateContext(ciP, components, compV, parseDataP);

  // 03. Translate UpdateContextResponse to StatusCode
  response.fill(parseDataP->upcrs.res);

  // 04. If not found, put entity info in details
  if ((response.code == SccContextElementNotFound) && (response.details == ""))
  {
    response.details = entityId;
  }

  // 05. Cleanup and return result
  TIMED_RENDER(answer = response.render(ciP->outFormat, "", false, false));

  response.release();
  parseDataP->upcr.res.release();

  return answer;
}
Ejemplo n.º 13
0
/* ****************************************************************************
*
* postBatchUpdate -
*
* POST /v2/op/update
*
* Payload In:  BatchUpdateRequest
* Payload Out: 201 or error
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - options=keyValues
*/
std::string postBatchUpdate
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  BatchUpdate*           buP    = &parseDataP->bu.res;
  UpdateContextRequest*  upcrP  = &parseDataP->upcr.res;
  Entities               entities;
  std::string            answer;

  upcrP->fill(&buP->entities, buP->updateActionType.get());
  buP->release();  // upcrP just 'took over' the data from buP, buP is no longer needed
  parseDataP->upcr.res.present("");
  answer = postUpdateContext(ciP, components, compV, parseDataP);

  for (unsigned int ix = 0; ix < parseDataP->upcrs.res.contextElementResponseVector.size(); ++ix)
  {
    ContextElementResponse* cerP = parseDataP->upcrs.res.contextElementResponseVector[ix];

    if (cerP->statusCode.code != SccOk)
    {
      parseDataP->upcrs.res.errorCode.fill(cerP->statusCode);
    }
  }


  //
  // If an error is flagged by ciP->httpStatusCode, store it in parseDataP->upcrs.res.errorCode
  // for later processing (not sure this ever happen ...)
  //
  if (ciP->httpStatusCode != SccOk)
  {
    parseDataP->upcrs.res.errorCode.code     = ciP->httpStatusCode;
    parseDataP->upcrs.res.errorCode.details  = answer;
  }

  // If postUpdateContext gives back a parseDataP->upcrs with !200 OK in 'errorCode', transform to HTTP Status error
  if (parseDataP->upcrs.res.errorCode.code != SccOk)
  {
    OrionError   oe(parseDataP->upcrs.res.errorCode);

    ciP->httpStatusCode = parseDataP->upcrs.res.errorCode.code;

    // If 404 and details empty, assuming 'Entity not found'
    if ((parseDataP->upcrs.res.errorCode.code == SccContextElementNotFound) && (oe.details == ""))
    {
      oe.details = "Entity not found";
    }

    answer = oe.render(ciP, "");
  }
  else
  {
    //
    // NOTE
    //   For simplicity, 204 is always returned, even if entities are created
    //
    ciP->httpStatusCode = SccNoContent;
    answer = "";
  }

  // 04. Cleanup and return result
  entities.release();
  parseDataP->upcr.res.release();

  return answer;
}
Ejemplo n.º 14
0
/* ****************************************************************************
*
* postEntities - 
*
* POST /v2/entities
*
* Payload In:  Entity
* Payload Out: None
*
* URI parameters:
*   options=keyValues
*   options=upsert
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op postUpdateContext
* 03. Prepare HTTP headers
* 04. Cleanup and return result
*/
std::string postEntities
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  Entity*   eP = &parseDataP->ent.res;
  bool  upsert = ciP->uriParamOptions[OPT_UPSERT];

  if (!legalEntityLength(eP, ciP->httpHeaders.servicePath))
  {
    OrionError oe(SccBadRequest, "Too long entity id/type/servicePath combination", "BadRequest");
    eP->release();

    std::string out;
    TIMED_RENDER(out = oe.toJson());
    ciP->httpStatusCode = oe.code;

    return out;
  }

  // Set some aspects depending on upsert or not upsert
  ActionType      actionType;
  Ngsiv2Flavour   ngsiv2flavour;
  HttpStatusCode  sccCodeOnSuccess;
  if (upsert)
  {
    actionType       = ActionTypeAppend;
    ngsiv2flavour    = NGSIV2_NO_FLAVOUR;
    sccCodeOnSuccess = SccNoContent;
  }
  else
  {
    actionType       = ActionTypeAppendStrict;
    ngsiv2flavour    = NGSIV2_FLAVOUR_ONCREATE;
    sccCodeOnSuccess = SccCreated;
  }

  // 01. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(eP, actionType);

  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP, ngsiv2flavour);

  //
  // 03. Check error - 3 different ways to get an error from postUpdateContext ... :-(
  //     FIXME P4: make postUpdateContext have ONE way to return errors. See github issue #2763
  //
  std::string  answer = "";
  if (parseDataP->upcrs.res.oe.code != SccNone)
  {
    TIMED_RENDER(answer = parseDataP->upcrs.res.oe.toJson());
    ciP->httpStatusCode = parseDataP->upcrs.res.oe.code;
  }
  else if (parseDataP->upcrs.res.errorCode.code != SccOk)
  {
    ciP->httpStatusCode = parseDataP->upcrs.res.errorCode.code;
    TIMED_RENDER(answer = parseDataP->upcrs.res.errorCode.toJson());
    ciP->answer         = answer;
  }
  else
  {
    // Prepare HTTP headers
    std::string location = "/v2/entities/" + eP->id;
    if (eP->type != "" )
    {
      location += "?type=" + eP->type;
    }
    else
    {
      location += "?type=none";
    }

    ciP->httpHeader.push_back(HTTP_RESOURCE_LOCATION);
    ciP->httpHeaderValue.push_back(location);
    ciP->httpStatusCode = sccCodeOnSuccess;
  }

  // 04. Cleanup and return result
  eP->release();

  return answer;
}
/* ****************************************************************************
*
* postAttributeValueInstanceWithTypeAndId - 
*
* POST /v1/contextEntities/type/{entity::type}/id/{entity::id}/attributes/{attribute::name}/{metaID}
* POST /ngsi10/contextEntities/type/{entity::type}/id/{entity::id}/attributes/{attribute::name}/{metaID}
*
* Payload In:  UpdateContextAttributeRequest
* Payload Out: StatusCode
*
* Mapped Standard Operation: UpdateContextRequest/APPEND
*
* URI parameters
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
* 
* 00. Get values from URI path
* 01. Get values URI parameters
* 02. Check validity of URI params VS URI path components
* 03. Check validity of path components VS payload
* 04. Fill in UpdateContextRequest
* 05. Call postUpdateContext
* 06. Fill in StatusCode from UpdateContextResponse
* 07. Render result
* 08. Cleanup and return result
*/
std::string postAttributeValueInstanceWithTypeAndId
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string     entityType              = compV[3];
  std::string     entityId                = compV[5];
  std::string     attributeName           = compV[7];
  std::string     metaID                  = compV[8];
  std::string     entityTypeFromUriParam;
  StatusCode      response;
  std::string     answer;


  // 01. Get values URI parameters
  entityTypeFromUriParam  = ciP->uriParam[URI_PARAM_ENTITY_TYPE];


  // 02. Check validity of URI params VS URI path components
  if ((entityTypeFromUriParam != "") && (entityTypeFromUriParam != entityType))
  {
    LM_W(("Bad Input non-matching entity::types in URL"));
    response.fill(SccBadRequest, "non-matching entity::types in URL");
    answer = response.render(ciP->outFormat, "", false, false);

    parseDataP->upcar.res.release();
    return answer;
  }


  // 03. Check validity of path components VS payload
  Metadata* mP = parseDataP->upcar.res.metadataVector.lookupByName("ID");

  if ((mP != NULL) && (mP->value != metaID))
  {
    std::string details = "unmatching metadata ID value URI/payload: /" + metaID + "/ vs /" + mP->value + "/";
    
    response.fill(SccBadRequest, details);
    answer = response.render(ciP->outFormat, "", false, false);
    parseDataP->upcar.res.release();

    return answer;
  }


  // 04. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(&parseDataP->upcar.res, entityId, entityType, attributeName, metaID, "APPEND");


  // 05. Call postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);


  // 06. Fill in StatusCode from UpdateContextResponse
  response.fill(parseDataP->upcrs.res);


  // 07. Render result
  answer = response.render(ciP->outFormat, "", false, false);


  // 08. Cleanup and return result
  response.release();
  parseDataP->upcar.res.release();
  parseDataP->upcr.res.release();
  parseDataP->upcrs.res.release();

  return answer;
}
/* ****************************************************************************
*
* putAllEntitiesWithTypeAndId - 
*
* PUT /v1/contextEntities/type/{entity::type}/id/{entity::id}
*
* Payload In:  UpdateContextElementRequest
* Payload Out: UpdateContextElementResponse
*
* URI parameters:
*   - attributesFormat=object
*   - entity::type=TYPE (must coincide with type in URL-path)
*   - !exist=entity::type  (if set - error -- entity::type cannot be empty)
*   - exist=entity::type   (not supported - ok if present, ok if not present ...)
*
* 01. Get values from URL (entityId::type, exist, !exist)
* 02. Check validity of URI params
* 03. Fill in UpdateContextRequest
* 04. Call Standard Operation
* 05. Fill in response from UpdateContextResponse
* 06. Cleanup and return result
*/
extern std::string putAllEntitiesWithTypeAndId
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string                   entityType            = compV[3];
  std::string                   entityId              = compV[5];
  EntityTypeInfo                typeInfo              = EntityTypeEmptyOrNotEmpty;
  std::string                   typeNameFromUriParam  = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  std::string                   answer;
  UpdateContextElementResponse  response;

  // FIXME P1: AttributeDomainName skipped
  // FIXME P1: domainMetadataVector skipped


  // 01. Get values from URL (entityId::type, esist, !exist)
  if (ciP->uriParam[URI_PARAM_NOT_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeEmpty;
  }
  else if (ciP->uriParam[URI_PARAM_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeNotEmpty;
  }


  // 02. Check validity of URI params
  if (typeInfo == EntityTypeEmpty)
  {
    alarmMgr.badInput(clientIp, "entity::type cannot be empty for this request");
    response.errorCode.fill(SccBadRequest, "entity::type cannot be empty for this request");
    TIMED_RENDER(answer = response.render(ciP, AllEntitiesWithTypeAndId, ""));
    return answer;
  }
  else if ((typeNameFromUriParam != entityType) && (typeNameFromUriParam != ""))
  {
    alarmMgr.badInput(clientIp, "non-matching entity::types in URL");
    response.errorCode.fill(SccBadRequest, "non-matching entity::types in URL");
    TIMED_RENDER(answer = response.render(ciP, AllEntitiesWithTypeAndId, ""));
    return answer;
  }


  // 03. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(&parseDataP->ucer.res, entityId, entityType);


  // 04. Call Standard Operation
 postUpdateContext(ciP, components, compV, parseDataP);


  // 05. Fill in response from UpdateContextResponse
  response.fill(&parseDataP->upcrs.res);


  // 06. Cleanup and return result
  TIMED_RENDER(answer = response.render(ciP, IndividualContextEntity, ""));

  parseDataP->upcr.res.release();
  response.release();

  return answer;
}
Ejemplo n.º 17
0
/* ****************************************************************************
*
* patchEntity - 
*
* PATCH /v2/entities
*
* Payload In:  Entity
* Payload Out: None
*
* URI parameters:
*   - 
*
* 01. Fill in UpdateContextRequest
* 02. Call standard op postUpdateContext
* 03. Check output from mongoBackend - any errors?
* 04. Prepare HTTP headers
* 05. Cleanup and return result
*/
std::string patchEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string  answer = "";
  Entity*      eP     = &parseDataP->ent.res;

  eP->id = compV[2];

  // 01. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(eP, "UPDATE");
  

  // 02. Call standard op postUpdateContext
  postUpdateContext(ciP, components, compV, parseDataP);

  // 03. Check output from mongoBackend - any errors?
  if (parseDataP->upcrs.res.contextElementResponseVector.size() == 1)
  {
    if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code != SccOk)
    {
      ciP->httpStatusCode = parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code;

      if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code == SccContextElementNotFound)
      {
        OrionError orionError(SccContextElementNotFound, "No context element found");

        TIMED_RENDER(answer = orionError.render(ciP, ""));
      } 
      else if (parseDataP->upcrs.res.contextElementResponseVector[0]->statusCode.code == SccConflict)
      {
        OrionError orionError(SccConflict, "There is more than one entity that match the update. Please refine your query.");

        TIMED_RENDER(answer = orionError.render(ciP, ""));
      }
    }
  }


  // 04. Prepare HTTP headers
  if ((ciP->httpStatusCode == SccOk) || (ciP->httpStatusCode == SccNone))
  {
    ciP->httpStatusCode = SccNoContent;
  }
  else if (ciP->httpStatusCode == SccInvalidParameter)
  {
    OrionError orionError(SccContextElementNotFound, "No context element found");

    ciP->httpStatusCode = SccContextElementNotFound;

    TIMED_RENDER(answer = orionError.render(ciP, ""));
  }


  // 05. Cleanup and return result
  eP->release();

  return answer;
}
/* ****************************************************************************
*
* postIndividualContextEntityAttributeWithTypeAndId - 
*
* POST /v1/contextEntities/type/{entity::type}/id/{entity::id}/attributes/{attribute::name}
*
* Payload In:  UpdateContextAttributeRequest
* Payload Out: StatusCode
* 
* URI parameters:
*   - entity::type=XXX        (must coincide with entity::type in URL)
*   - !exist=entity::type     (if set - error -- entity::type cannot be empty)
*   - exist=entity::type      (not supported - ok if present, ok if not present ...)
*   x attributesFormat=object (cannot be supported as the response is a StatusCode)
*
* 01. Get values from URL (entityId::type, esist, !exist)
* 02. Check validity of URI params
* 03. Fill in UpdateContextRequest
* 04. Call standard operation postUpdateContext
* 05. Translate UpdateContextResponse to StatusCode
* 06. Cleanup and return result
*/
std::string postIndividualContextEntityAttributeWithTypeAndId
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string     entityType              = compV[3];
  std::string     entityId                = compV[5];
  std::string     attributeName           = compV[7];
  std::string     entityTypeFromUriParam  = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  EntityTypeInfo  typeInfo                = EntityTypeEmptyOrNotEmpty;
  std::string     answer;
  StatusCode      response;

  // 01. Get values from URL (entityId::type, esist, !exist)
  if (ciP->uriParam[URI_PARAM_NOT_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeEmpty;
  }
  else if (ciP->uriParam[URI_PARAM_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeNotEmpty;
  }


  // 02. Check validity of URI params ...
  //     And if OK;
  // 03. Fill in UpdateContextRequest
  // 04. Call standard operation postUpdateContext
  // 05. Translate UpdateContextResponse to StatusCode
  //
  if (typeInfo == EntityTypeEmpty)
  {
    response.fill(SccBadRequest, "entity::type cannot be empty for this request");
    alarmMgr.badInput(clientIp, "entity::type cannot be empty for this request");
  }
  else if ((entityTypeFromUriParam != entityType) && (entityTypeFromUriParam != ""))
  {
    response.fill(SccBadRequest, "non-matching entity::types in URL");
    alarmMgr.badInput(clientIp, "non-matching entity::types in URL");
  }
  else
  {
    // 03. Fill in UpdateContextRequest
    parseDataP->upcr.res.fill(&parseDataP->upcar.res, entityId, entityType, attributeName, "", "APPEND");

    // 04. Call standard operation postUpdateContext
    postUpdateContext(ciP, components, compV, parseDataP);

    // 05. Translate UpdateContextResponse to StatusCode
    response.fill(parseDataP->upcrs.res);
    parseDataP->upcr.res.release();
  }


  // 06. Cleanup and return result
  TIMED_RENDER(answer = response.render(ciP->outFormat, "", false, false));

  parseDataP->upcar.res.release();
  parseDataP->upcrs.res.release();

  return answer;
}
/* ****************************************************************************
*
* deleteAllEntitiesWithTypeAndId - 
*
* DELETE /v1/contextEntities/type/{entity::type}/id/{entity::id}
*
* Payload In:  None
* Payload Out: StatusCode
*
* URI parameters:
*   - entity::type=TYPE (must coincide with type in URL-path)
*   - !exist=entity::type  (if set - error -- entity::type cannot be empty)
*   - exist=entity::type   (not supported - ok if present, ok if not present ...)
*
* 01. Get values from URL (+ entityId::type, exist, !exist)
* 02. Check validity of URI params
* 03. Fill in UpdateContextRequest
* 04. Call Standard Operation
* 05. Fill in response from UpdateContextResponse
* 06. Cleanup and return result
*/
std::string deleteAllEntitiesWithTypeAndId
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  std::string     entityType            = compV[3];
  std::string     entityId              = compV[5];
  EntityTypeInfo  typeInfo              = EntityTypeEmptyOrNotEmpty;
  std::string     typeNameFromUriParam  = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  std::string     answer;
  StatusCode      response;

  // 01. Get values from URL (+ entityId::type, exist, !exist)
  if (ciP->uriParam[URI_PARAM_NOT_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeEmpty;
  }
  else if (ciP->uriParam[URI_PARAM_EXIST] == URI_PARAM_ENTITY_TYPE)
  {
    typeInfo = EntityTypeNotEmpty;
  }


  // 02. Check validity of URI params
  if (typeInfo == EntityTypeEmpty)
  {
    alarmMgr.badInput(clientIp, "entity::type cannot be empty for this request");

    response.fill(SccBadRequest, "entity::type cannot be empty for this request");

    TIMED_RENDER(answer = response.render("", false, false));

    return answer;
  }
  else if ((typeNameFromUriParam != entityType) && (typeNameFromUriParam != ""))
  {
    alarmMgr.badInput(clientIp, "non-matching entity::types in URL");

    response.fill(SccBadRequest, "non-matching entity::types in URL");

    TIMED_RENDER(answer = response.render("", false, false));

    return answer;
  }


  // 03. Fill in UpdateContextRequest
  parseDataP->upcr.res.fill(entityId, entityType, "", "", "", "DELETE");


  // 04. Call Standard Operation
  postUpdateContext(ciP, components, compV, parseDataP);


  // 05. Fill in response from UpdateContextResponse
  response.fill(parseDataP->upcrs.res);


  // 06. Cleanup and return result
  TIMED_RENDER(answer = response.render("", false, false));

  parseDataP->upcr.res.release();
  response.release();

  return answer;
}
/* ****************************************************************************
*
* postIndividualContextEntity -
*
* Corresponding Standard Operation: UpdateContext/APPEND
*
* NOTE
*   This function is used for two different URLs:
*     o /v1/contextEntities
*     o /v1/contextEntities/{entityId::id}
*
* In the longer URL (with entityId::id), the payload (AppendContextElementRequest) cannot contain any
* entityId data (id, type, isPattern).
* In the first case, the entityId data of the payload is mandatory.
* entityId::type can be empty, as always, but entityId::id MUST be filled in.
*
* POST /v1/contextEntities
* POST /ngsi10/contextEntities
* POST /v1/contextEntities/{entityId::id}
* POST /ngsi10/contextEntities/{entityId::id}
*
* Payload In:  AppendContextElementRequest
* Payload Out: AppendContextElementResponse
*
* URI parameters:
*   - attributesFormat=object
*   - entity::type=TYPE
*   - note that '!exist=entity::type' and 'exist=entity::type' are not supported by convenience operations
*     that use the standard operation UpdateContext as there is no restriction within UpdateContext.
*
* 00. Take care of URI params
* 01. Check that total input in consistent and correct
* 02. Fill in UpdateContextRequest from AppendContextElementRequest + URL-data + URI params
* 03. Call postUpdateContext standard service routine
* 04. Translate UpdateContextResponse to AppendContextElementResponse
* 05. Cleanup and return result
*/
std::string postIndividualContextEntity
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  AppendContextElementRequest*  reqP                  = &parseDataP->acer.res;
  AppendContextElementResponse  response;
  std::string                   entityIdFromPayload   = reqP->entity.id;
  std::string                   entityIdFromURL       = ((compV.size() == 3) || (compV.size() == 4))? compV[2] : "";
  std::string                   entityId;
  std::string                   entityTypeFromPayload = reqP->entity.type;
  std::string                   entityTypeFromURL     = ciP->uriParam[URI_PARAM_ENTITY_TYPE];
  std::string                   entityType;
  std::string                   answer;
  std::string                   out;


  //
  // 01. Check that total input in consistent and correct
  //

  // 01.01. entityId::id
  if ((entityIdFromPayload != "") && (entityIdFromURL != "") && (entityIdFromPayload != entityIdFromURL))
  {
    std::string error = "entityId::id differs in URL and payload";

    alarmMgr.badInput(clientIp, error);
    response.errorCode.fill(SccBadRequest, error);

    TIMED_RENDER(out = response.render(ciP, IndividualContextEntity, ""));
    return out;
  }  
  entityId = (entityIdFromPayload != "")? entityIdFromPayload : entityIdFromURL;

  // 01.02. entityId::type
  if ((entityTypeFromPayload != "") && (entityTypeFromURL != "") && (entityTypeFromPayload != entityTypeFromURL))
  {
    std::string error = "entityId::type differs in URL and payload";

    alarmMgr.badInput(clientIp, error);
    response.errorCode.fill(SccBadRequest, error);

    TIMED_RENDER(out = response.render(ciP, IndividualContextEntity, ""));
    return out;
  }
  entityType = (entityTypeFromPayload != "")? entityTypeFromPayload :entityTypeFromURL;


  // 01.03. entityId::isPattern
  if (reqP->entity.isPattern == "true")
  {
    std::string error = "entityId::isPattern set to true in contextUpdate convenience operation";

    alarmMgr.badInput(clientIp, error);
    response.errorCode.fill(SccBadRequest, error);

    TIMED_RENDER(out = response.render(ciP, IndividualContextEntity, ""));
    return out;
  }

  // 01.04. Entity::id must be present, somewhere ...
  if (entityId == "")
  {
    std::string error = "invalid request: mandatory entityId::id missing";

    alarmMgr.badInput(clientIp, error);
    response.errorCode.fill(SccBadRequest, error);

    TIMED_RENDER(out = response.render(ciP, IndividualContextEntity, ""));
    return out;
  }

  // Now, forward Entity to response
  response.entity.fill(entityId, entityType, "false");


  //
  // 02. Fill in UpdateContextRequest from AppendContextElementRequest + URL-data + URI params
  //
  parseDataP->upcr.res.fill(&parseDataP->acer.res, entityId, entityType);


  // 03. Call postUpdateContext standard service routine
  postUpdateContext(ciP, components, compV, parseDataP);


  // 04. Translate UpdateContextResponse to AppendContextElementResponse
  response.fill(&parseDataP->upcrs.res);

  // 05. Cleanup and return result
  TIMED_RENDER(answer = response.render(ciP, IndividualContextEntity, ""));

  response.release();
  parseDataP->upcr.res.release();

  return answer;
}