/* ****************************************************************************
*
* ok_xml - 
*/
TEST(QueryContextRequest, ok_xml)
{
  ParseData       reqData;
  ConnectionInfo  ci("", "POST", "1.1");
  const char*     infile = "ngsi10.queryContextRequest.ok.valid.xml";

  utInit();

  EXPECT_EQ("OK", testDataFromFile(testBuf, sizeof(testBuf), infile)) << "Error getting test data from '" << infile << "'";

  lmTraceLevelSet(LmtDump, true);
  std::string out = xmlTreat(testBuf, &ci, &reqData, QueryContext, "queryContextRequest", NULL);
  lmTraceLevelSet(LmtDump, false);

  EXPECT_EQ("OK", out) << "this test should be OK";

  //
  // With the data obtained, render, present and release methods are exercised
  //
  QueryContextRequest*  qcrP = &reqData.qcr.res;
  const char*  outfile = "ngsi10.queryContextRequest.ok2.valid.xml";
  
  qcrP->present(""); // No output

  EXPECT_EQ("OK", testDataFromFile(expectedBuf, sizeof(expectedBuf), outfile)) << "Error getting test data from '" << outfile << "'";
  out = qcrP->render(QueryContext, XML, "");
  EXPECT_STREQ(expectedBuf, out.c_str());

  qcrP->release();

  utExit();
}
/* ****************************************************************************
*
* postBatchQuery -
*
* POST /v2/op/query
*
* Payload In:  BatchQueryRequest
* Payload Out: Entities
*
* URI parameters:
*   - limit=NUMBER
*   - offset=NUMBER
*   - options=count,keyValues
*/
std::string postBatchQuery
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  BatchQuery*           bqP  = &parseDataP->bq.res;
  QueryContextRequest*  qcrP = &parseDataP->qcr.res;
  Entities              entities;
  std::string           answer;

  qcrP->fill(bqP);
  bqP->release();  // qcrP just 'took over' the data from bqP, bqP no longer needed

  answer = postQueryContext(ciP, components, compV, parseDataP);

  if (ciP->httpStatusCode != SccOk)
  {
    parseDataP->qcr.res.release();
    return answer;
  }

  // 03. Render Entities response
  if (parseDataP->qcrs.res.contextElementResponseVector.size() == 0)
  {
    ciP->httpStatusCode = SccOk;
    answer = "[]";
  }
  else
  {
    entities.fill(&parseDataP->qcrs.res);

    TIMED_RENDER(answer = entities.render(ciP, EntitiesResponse));
  }

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

  return answer;
}
/* ****************************************************************************
*
* ok_json - 
*/
TEST(QueryContextRequest, ok_json)
{
  ParseData       parseData;
  ConnectionInfo  ci("", "POST", "1.1");
  const char*     infile  = "ngsi10.queryContextRequest_ok.valid.json";
  const char*     outfile = "ngsi10.queryContextRequest_ok.expected.valid.json";
  std::string     rendered;

  utInit();

  EXPECT_EQ("OK", testDataFromFile(testBuf, sizeof(testBuf), infile)) << "Error getting test data from '" << infile << "'";

  ci.inFormat  = JSON;
  ci.outFormat = JSON;

  lmTraceLevelSet(LmtDump, true);
  std::string out = jsonTreat(testBuf, &ci, &parseData, QueryContext, "queryContextRequest", NULL);
  lmTraceLevelSet(LmtDump, false);

  EXPECT_EQ("OK", out) << "this test should be OK";


  //
  // With the data obtained, render, present and release methods are exercised
  //
  QueryContextRequest*  qcrP = &parseData.qcr.res;
  
  qcrP->present(""); // No output

  EXPECT_EQ("OK", testDataFromFile(expectedBuf, sizeof(expectedBuf), outfile)) << "Error getting test data from '" << outfile << "'";
  rendered = qcrP->render(QueryContext, JSON, "");
  EXPECT_STREQ(expectedBuf, rendered.c_str());

  qcrP->present("");
  qcrP->release();

  utExit();
}
/* ****************************************************************************
*
* getAttributeValueInstance - 
*
* GET /ngsi10/contextEntities/{entityID}/attributes/{attributeName}/{valueID}
*/
std::string getAttributeValueInstance
(
  ConnectionInfo*            ciP,
  int                        components,
  std::vector<std::string>&  compV,
  ParseData*                 parseDataP
)
{
  QueryContextRequest      request;
  QueryContextResponse     response;
  std::string              entityId      = compV[2];
  std::string              attributeName = compV[4];
  std::string              valueID       = compV[5];
  EntityId*                eP            = new EntityId(entityId, "", "false");
  StatusCode               sc;
  ContextAttributeResponse car;

  request.entityIdVector.push_back(eP);
  request.attributeList.push_back(attributeName);

  ciP->httpStatusCode = mongoQueryContext(&request, &response, ciP->tenant, ciP->servicePathV, ciP->uriParam);

  if (response.contextElementResponseVector.size() == 0)
  {
     car.statusCode.fill(SccContextElementNotFound,
                         std::string("Entity-Attribute pair: /") + entityId + "-" + attributeName + "/");
  }
  else
  {
    ContextElementResponse* cerP = response.contextElementResponseVector.get(0);
    ContextAttributeVector cav = cerP->contextElement.contextAttributeVector;

    // FIXME P4: as long as mongoQueryContext() signature is based on NGSI standard operations and that
    // standard queryContext doesn't allow specify metadata for attributes (note that it uses xs:string,
    // not full fledge attribute types), we cannot pass the ID to mongoBackend so we need to do the for loop
    // to grep the right attribute among all the ones returned by mongoQueryContext. However, this involves
    // a suboptimal query at mongoBackend, which could be improved passing it the ID as a new parameter to
    // mongoQueryContext() (although breaking the design principle about mongo*() functions follow the NGSI
    // standard). To think about it.
    for (unsigned int i = 0; i < cav.size(); i++)
    {
      if (cav.get(i)->getId() == valueID)
      {
        car.contextAttributeVector.push_back(cav.get(i));
      }
    }

    if (cav.size() > 0 && car.contextAttributeVector.size() == 0)
    {
      car.statusCode.fill(SccContextElementNotFound,
                          std::string("Attribute-ValueID pair: /") + attributeName + "-" + valueID + "/");
    }
    else
    {
      car.statusCode.fill(&cerP->statusCode);
    }
  }

  request.release();

  return car.render(ciP, AttributeValueInstance, "");
}