Skip to content

Commit

Permalink
Implemented POST /temporal/entities - to add entities to TRoE without…
Browse files Browse the repository at this point in the history
… actually creating any entity (for the current state)
  • Loading branch information
kzangeli committed Apr 20, 2021
1 parent ab6db86 commit 553b470
Show file tree
Hide file tree
Showing 13 changed files with 549 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
* Issue #280 Implemented GET /attributes, but only without details=true
* Issue #280 Slightly increased response from Batch Upsert
* Issue #280 Implemented system attributes (createdAt, modifiedAt) for sub-attributes
* Issue #280 Implemented POST /temporal/entities - to add entities to TRoE without actually creating any entity (for the current state)
25 changes: 13 additions & 12 deletions src/app/orionld/orionldRestServices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "orionld/serviceRoutines/orionldGetTemporalEntities.h"
#include "orionld/serviceRoutines/orionldGetTemporalEntity.h"
#include "orionld/serviceRoutines/orionldPostTemporalQuery.h"
#include "orionld/serviceRoutines/orionldPostTemporalEntities.h"

#include "orionld/rest/OrionLdRestService.h" // OrionLdRestServiceSimplified
#include "orionld/orionldRestServices.h" // Own Interface
Expand Down Expand Up @@ -99,18 +100,18 @@ static const int getServices = (sizeof(getServiceV) / sizeof(getServiceV[0]));
//
static OrionLdRestServiceSimplified postServiceV[] =
{
{ "/ngsi-ld/v1/entities/*/attrs", orionldPostEntity },
{ "/ngsi-ld/v1/entities", orionldPostEntities },
{ "/ngsi-ld/v1/entityOperations/create", orionldPostBatchCreate },
{ "/ngsi-ld/v1/entityOperations/upsert", orionldPostBatchUpsert },
{ "/ngsi-ld/v1/entityOperations/update", orionldPostBatchUpdate },
{ "/ngsi-ld/v1/entityOperations/delete", orionldPostBatchDelete },
{ "/ngsi-ld/v1/entityOperations/query", orionldPostQuery },
{ "/ngsi-ld/v1/subscriptions", orionldPostSubscriptions },
{ "/ngsi-ld/v1/csourceRegistrations", orionldPostRegistrations },
{ "/ngsi-ld/v1/temporal/entities/*/attrs", orionldNotImplemented },
{ "/ngsi-ld/v1/temporal/entities", orionldNotImplemented },
{ "/ngsi-ld/v1/temporal/entityOperations/query", orionldPostTemporalQuery }
{ "/ngsi-ld/v1/entities/*/attrs", orionldPostEntity },
{ "/ngsi-ld/v1/entities", orionldPostEntities },
{ "/ngsi-ld/v1/entityOperations/create", orionldPostBatchCreate },
{ "/ngsi-ld/v1/entityOperations/upsert", orionldPostBatchUpsert },
{ "/ngsi-ld/v1/entityOperations/update", orionldPostBatchUpdate },
{ "/ngsi-ld/v1/entityOperations/delete", orionldPostBatchDelete },
{ "/ngsi-ld/v1/entityOperations/query", orionldPostQuery },
{ "/ngsi-ld/v1/subscriptions", orionldPostSubscriptions },
{ "/ngsi-ld/v1/csourceRegistrations", orionldPostRegistrations },
{ "/ngsi-ld/v1/temporal/entities/*/attrs", orionldNotImplemented },
{ "/ngsi-ld/v1/temporal/entities", orionldPostTemporalEntities },
{ "/ngsi-ld/v1/temporal/entityOperations/query", orionldPostTemporalQuery }
};
static const int postServices = (sizeof(postServiceV) / sizeof(postServiceV[0]));

Expand Down
4 changes: 4 additions & 0 deletions src/lib/orionld/common/orionldState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C"
#include "orionld/types/OrionldGeoIndex.h" // OrionldGeoIndex
#include "orionld/db/dbConfiguration.h" // DB_DRIVER_MONGOC
#include "orionld/context/orionldCoreContext.h" // orionldCoreContext
#include "orionld/troe/troe.h" // TroeMode
#include "orionld/common/QNode.h" // QNode
#include "orionld/common/performance.h" // REQUEST_PERFORMANCE
#include "orionld/common/orionldState.h" // Own interface
Expand Down Expand Up @@ -145,6 +146,9 @@ void orionldStateInit(void)
orionldState.uriParams.limit = 20;

// orionldState.delayedKjFreeVecSize = sizeof(orionldState.delayedKjFreeVec) / sizeof(orionldState.delayedKjFreeVec[0]);

// TRoE
orionldState.troeOpMode = TROE_ENTITY_CREATE;
}


Expand Down
3 changes: 2 additions & 1 deletion src/lib/orionld/common/orionldState.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ extern "C"
#include "orionld/types/OrionldGeoIndex.h" // OrionldGeoIndex
#include "orionld/types/OrionldGeoJsonType.h" // OrionldGeoJsonType
#include "orionld/types/OrionldPrefixCache.h" // OrionldPrefixCache
#include "orionld/troe/troe.h" // TroeMode
#include "orionld/context/OrionldContext.h" // OrionldContext


Expand Down Expand Up @@ -203,7 +204,6 @@ typedef struct OrionldConnectionState
int geoAttrs;
char* geoType;
KjNode* geoCoordsP;
bool entityCreated; // If an entity is created, if complex context, it must be stored
char* entityId;
OrionldUriParamOptions uriParamOptions;
OrionldUriParams uriParams;
Expand Down Expand Up @@ -288,6 +288,7 @@ typedef struct OrionldConnectionState
KjNode* troeIgnoreV[20];
unsigned int troeIgnoreIx;
KjNode* batchEntities;
TroeMode troeOpMode;

//
// GeoJSON - help vars for the case:
Expand Down
11 changes: 11 additions & 0 deletions src/lib/orionld/rest/orionldServiceInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ extern "C"
#include "orionld/serviceRoutines/orionldDeleteSubscription.h" // orionldDeleteSubscription
#include "orionld/serviceRoutines/orionldGetEntityTypes.h" // orionldGetEntityTypes
#include "orionld/serviceRoutines/orionldGetEntityAttributes.h" // orionldGetEntityAttributes
#include "orionld/serviceRoutines/orionldPostTemporalEntities.h" // orionldPostTemporalEntities
#include "orionld/troe/troePostEntities.h" // troePostEntities
#include "orionld/troe/troePostBatchDelete.h" // troePostBatchDelete
#include "orionld/troe/troeDeleteAttribute.h" // troeDeleteAttribute
Expand Down Expand Up @@ -403,6 +404,14 @@ static void restServicePrepare(OrionLdRestService* serviceP, OrionLdRestServiceS

serviceP->options |= ORIONLD_SERVICE_OPTION_NO_V2_URI_PARAMS;
}
else if (serviceP->serviceRoutine == orionldPostTemporalEntities)
{
serviceP->options = 0; // Tenant will be created if necessary

serviceP->options |= ORIONLD_SERVICE_OPTION_PREFETCH_ID_AND_TYPE;
serviceP->options |= ORIONLD_SERVICE_OPTION_NO_V2_URI_PARAMS;
serviceP->options |= ORIONLD_SERVICE_OPTION_CREATE_CONTEXT;
}
else if (serviceP->serviceRoutine == orionldGetVersion)
{
serviceP->options = 0; // Tenant is Ignored
Expand Down Expand Up @@ -431,6 +440,8 @@ static void restServicePrepare(OrionLdRestService* serviceP, OrionLdRestServiceS
{
if (serviceP->serviceRoutine == orionldPostEntities)
serviceP->troeRoutine = troePostEntities;
else if (serviceP->serviceRoutine == orionldPostTemporalEntities)
serviceP->troeRoutine = NULL; // TRoE processing is taken care of INSIDE the service routine
else if (serviceP->serviceRoutine == orionldPostBatchDelete)
serviceP->troeRoutine = troePostBatchDelete;
else if (serviceP->serviceRoutine == orionldPostEntity)
Expand Down
1 change: 1 addition & 0 deletions src/lib/orionld/serviceRoutines/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ SET (SOURCES
orionldGetTemporalEntity.cpp
orionldPostTemporalQuery.cpp
orionldGetEntityAttributes.cpp
orionldPostTemporalEntities.cpp
)

# Include directories
Expand Down
3 changes: 1 addition & 2 deletions src/lib/orionld/serviceRoutines/orionldPostEntities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,7 @@ bool orionldPostEntities(ConnectionInfo* ciP)
return false;
}

orionldState.httpStatusCode = SccCreated;
orionldState.entityCreated = true;
orionldState.httpStatusCode = 201;

httpHeaderLocationAdd(ciP, "/ngsi-ld/v1/entities/", entityId);

Expand Down
154 changes: 154 additions & 0 deletions src/lib/orionld/serviceRoutines/orionldPostTemporalEntities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
*
* Copyright 2021 FIWARE Foundation e.V.
*
* This file is part of Orion-LD Context Broker.
*
* Orion-LD Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion-LD Context Broker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* orionld at fiware dot org
*
* Author: Ken Zangelin
*/
extern "C"
{
#include "kjson/kjRender.h" // kjFastRender
}

#include "logMsg/logMsg.h" // LM_*
#include "logMsg/traceLevels.h" // Lmt*

#include "rest/ConnectionInfo.h" // ConnectionInfo
#include "rest/httpHeaderAdd.h" // httpHeaderLocationAdd

#include "orionld/common/orionldState.h" // orionldState
#include "orionld/common/orionldErrorResponse.h" // orionldErrorResponseCreate
#include "orionld/common/CHECK.h" // OBJECT_CHECK
#include "orionld/common/numberToDate.h" // numberToDate
#include "orionld/rest/OrionLdRestService.h" // OrionLdRestService
#include "orionld/payloadCheck/pcheckEntity.h" // pcheckEntity
#include "orionld/payloadCheck/pcheckUri.h" // pcheckUri
#include "orionld/troe/troePostEntities.h" // troePostEntities
#include "orionld/mongoBackend/mongoEntityExists.h" // mongoEntityExists
#include "orionld/serviceRoutines/orionldPostTemporalEntities.h" // Own Interface



// ----------------------------------------------------------------------------
//
// orionldPostTemporalEntities -
//
// The Payload Body for "POST /temporal/entities" looks like this:
//
// {
// "@context": "https://...",
// "id": "urn:ngsi-ld:entities:E1",
// "type": "T",
// "attr1": [
// {
// "type": "Property",
// "value": 14,
// "observedAt": "2021-04-20T08:31:00",
// "sub-R1": { "type": "Relationship", "object": "urn:xxx" },
// "sub-P1": { "type": "Property", "value": 14 },
// ...
// },
// {
// ...
// }
// ],
// "attr2": [
// {
// "type": "Relationship",
// "object": "urn:xxx",
// "observedAt": "2021-04-20T08:31:00",
// "sub-R1": { "type": "Relationship", "object": "urn:xxx" },
// "sub-P1": { "type": "Property", "value": 14 },
// ...
// },
// {
// ...
// }
// ]
// }
//
// This request adds entries in the TRoE database for the entity urn:ngsi-ld:entities:E1 and all of its attrs and their sub-attrs
//
bool orionldPostTemporalEntities(ConnectionInfo* ciP)
{
OBJECT_CHECK(orionldState.requestTree, "toplevel");

char* detail;
KjNode* locationP = NULL;
KjNode* observationSpaceP = NULL;
KjNode* operationSpaceP = NULL;
KjNode* createdAtP = NULL;
KjNode* modifiedAtP = NULL;

if (pcheckEntity(orionldState.requestTree->value.firstChildP, &locationP, &observationSpaceP, &operationSpaceP, &createdAtP, &modifiedAtP, false) == false)
return false;

char* entityId = orionldState.payloadIdNode->value.s;
char* entityType = orionldState.payloadTypeNode->value.s;


//
// Entity ID and TYPE
//
if (pcheckUri(entityId, true, &detail) == false)
{
orionldErrorResponseCreate(OrionldBadRequestData, "Invalid Entity id", "The id specified cannot be resolved to a URL or URN"); // FIXME: Include 'detail' and name (entityId)
return false;
}

if (pcheckUri(entityType, false, &detail) == false)
{
orionldErrorResponseCreate(OrionldBadRequestData, "Invalid Entity Type", detail); // FIXME: Include 'detail' and name (entityId)
return false;
}


// Does the entity already exist?
// FIXME: This check should really be made in the TRoE database but, seems valid enough to do the
// search in mongo instead
//
int httpStatusCode = 201;

if (mongoEntityExists(entityId, orionldState.tenant) == true)
httpStatusCode = 204;

//
// Nothing is sent to mongo, only TRoE is updated
// And, the TRoE function is invoked by orionldMhdConnectionTreat
//
numberToDate(orionldState.requestTime, orionldState.requestTimeString, sizeof(orionldState.requestTimeString));
orionldState.troeOpMode = TROE_ENTITY_REPLACE;
bool troeOk = troePostEntities(ciP);

if (troeOk == true)
{
if (httpStatusCode == 201)
httpHeaderLocationAdd(ciP, "/ngsi-ld/v1/temporal/entities/", entityId);

orionldState.httpStatusCode = httpStatusCode;
return true;
}

LM_E(("troePostEntities failed (%s: %s)", orionldState.pd.title, orionldState.pd.detail));
orionldErrorResponseCreate(orionldState.pd.type, orionldState.pd.title, orionldState.pd.detail);
orionldState.httpStatusCode = orionldState.pd.type;

return false;
}
40 changes: 40 additions & 0 deletions src/lib/orionld/serviceRoutines/orionldPostTemporalEntities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef SRC_LIB_ORIONLD_SERVICEROUTINES_ORIONLDPOSTTEMPORALENTITIES_H_
#define SRC_LIB_ORIONLD_SERVICEROUTINES_ORIONLDPOSTTEMPORALENTITIES_H_

/*
*
* Copyright 2021 FIWARE Foundation e.V.
*
* This file is part of Orion-LD Context Broker.
*
* Orion-LD Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion-LD Context Broker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion-LD Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* orionld at fiware dot org
*
* Author: Ken Zangelin
*/
#include "logMsg/logMsg.h"

#include "rest/ConnectionInfo.h"



// ----------------------------------------------------------------------------
//
// orionldPostTemporalEntities -
//
extern bool orionldPostTemporalEntities(ConnectionInfo* ciP);

#endif // SRC_LIB_ORIONLD_SERVICEROUTINES_ORIONLDPOSTTEMPORALENTITIES_H_
2 changes: 1 addition & 1 deletion src/lib/orionld/troe/pgEntityTreat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ bool pgEntityTreat(PGconn* connectionP, KjNode* entityP, char* id, char* type, T
(strcmp(attrP->name, "createdAt") == 0) ||
(strcmp(attrP->name, "modifiedAt") == 0))
{
// If present, all these "attributes" are ignmoredd
// If present, all these "attributes" are ignored
}
else
LM_E(("Internal Error (The attribute '%s' is neither an Object nor an Array)", attrP->name));
Expand Down

0 comments on commit 553b470

Please sign in to comment.