Skip to content

Commit

Permalink
Merge pull request #1541 from FIWARE/q/vocab
Browse files Browse the repository at this point in the history
Expansion of RHS in 'q' according to new URL param 'expandValues'
  • Loading branch information
kzangeli committed Jan 20, 2024
2 parents 90e14a8 + d79b1dc commit 71c9582
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 3 deletions.
2 changes: 1 addition & 1 deletion CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ Fixed Issue:
* #1535 No matching with 'q' when matching subscriptions for deletion of an entity

New Features:
* Support for VocabularyProperty (highly untested and 'q' expansions for vocab-properties is not yet implemented)
* Support for VocabularyProperty
* Support for the new URL parameter "format" for output formats (normalized, concise, simplified)
4 changes: 4 additions & 0 deletions src/lib/orionld/common/orionldState.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extern "C"
#include "orionld/types/Verb.h" // Verb
#include "orionld/types/OrionldRenderFormat.h" // OrionldRenderFormat
#include "orionld/types/OrionldMimeType.h" // MimeType
#include "orionld/types/QNode.h" // QNode
#include "orionld/types/ApiVersion.h" // ApiVersion
#include "orionld/common/performance.h" // REQUEST_PERFORMANCE
#include "orionld/kjTree/kjTreeLog.h" // Because it is so often used but then removed again ...
Expand Down Expand Up @@ -129,6 +130,7 @@ typedef struct OrionldUriParams
int limit;
bool count;
char* q;
char* expandValues;
char* qCopy;
char* mq;
char* geometry;
Expand Down Expand Up @@ -263,6 +265,7 @@ typedef struct OrionldStateIn
StringArray idList;
StringArray typeList;
StringArray attrList;
StringArray expandValuesList;

// Entity Map
EntityMap* entityMap;
Expand Down Expand Up @@ -343,6 +346,7 @@ typedef struct OrionldConnectionState
OrionldContext* contextP;
ApiVersion apiVersion;
int requestNo;
QNode* qVariable; // Aux for qLex - to know whether a string should be expanded (VocabularyProperty)

KjNode* geoAttr[10]; // Preallocated array of GeoProperties
KjNode** geoAttrV; // Array of GeoProperty attributes
Expand Down
5 changes: 5 additions & 0 deletions src/lib/orionld/mhd/mhdConnectionInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,11 @@ MHD_Result orionldUriArgumentGet(void* cbDataP, MHD_ValueKind kind, const char*
orionldState.uriParams.options = (char*) value;
orionldState.uriParams.mask |= ORIONLD_URIPARAM_OPTIONS;
}
else if (strcmp(key, "expandValues") == 0)
{
orionldState.uriParams.expandValues = (char*) value;
orionldState.uriParams.mask |= ORIONLD_URIPARAM_EXPAND_VALUES;
}
else if (strcmp(key, "format") == 0)
{
orionldState.uriParams.format = (char*) value;
Expand Down
37 changes: 37 additions & 0 deletions src/lib/orionld/mhd/mhdConnectionTreat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,42 @@ static bool pCheckUrlPathAttributeName(void)



// -----------------------------------------------------------------------------
//
// pCheckExpandValuesParam -
//
static bool pCheckExpandValuesParam(void)
{
if (orionldState.uriParams.expandValues == NULL)
return true;

int items = commaCount(orionldState.uriParams.expandValues) + 1;
char* arraysDup = kaStrdup(&orionldState.kalloc, orionldState.uriParams.expandValues); // To not destroy the original value

orionldState.in.expandValuesList.items = items;
orionldState.in.expandValuesList.array = (char**) kaAlloc(&orionldState.kalloc, sizeof(char*) * items);

if (orionldState.in.expandValuesList.array == NULL)
{
LM_E(("Out of memory (allocating an /expandValues/ array of %d char pointers)", items));
orionldError(OrionldInternalError, "Out of memory", "allocating the array for /expandValues/ URI param", 500);
return false;
}

int splitItems = kStringSplit(arraysDup, ',', orionldState.in.expandValuesList.array, items);

if (splitItems != items)
{
LM_E(("kStringSplit didn't find exactly %d items (it found %d)", items, splitItems));
orionldError(OrionldInternalError, "Internal Error", "kStringSplit does not agree with commaCount", 500);
return false;
}

return true;
}



// -----------------------------------------------------------------------------
//
// uriParamExpansion -
Expand All @@ -845,6 +881,7 @@ static bool uriParamExpansion(void)
if (pCheckUriParamGeometryProperty() == false) return false;
if (pCheckPayloadEntityType() == false) return false;
if (pCheckUrlPathAttributeName() == false) return false;
if (pCheckExpandValuesParam() == false) return false; // This one isn't expanded, it's just a StringArray of attribute names for VocabularyProperty

// Can't do anything about 'q' - needs to be parsed first - expansion done in 'orionld/q/qParse.cpp'

Expand Down
26 changes: 25 additions & 1 deletion src/lib/orionld/q/qLex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "orionld/types/QNode.h" // QNode
#include "orionld/common/orionldState.h" // orionldState
#include "orionld/common/dateTime.h" // dateTimeFromString
#include "orionld/context/orionldContextItemExpand.h" // orionldContextItemExpand
#include "orionld/q/qNode.h" // qNode
#include "orionld/q/qNodeType.h" // qNodeType
#include "orionld/q/qLexCheck.h" // qLexCheck
Expand All @@ -44,7 +45,24 @@ static QNode* qStringPush(QNode* prev, char* stringValue)
{
QNode* qNodeP = qNode(QNodeStringValue);

LM_T(LmtQ, ("Pushing a String: '%s'", stringValue));
LM_T(LmtQ, ("Pushing a String: '%s'", stringValue));
if (orionldState.qVariable != NULL)
{
LM_T(LmtQ, ("For Variable: '%s'", orionldState.qVariable->value.s));
if (orionldState.uriParams.expandValues != NULL)
{
LM_T(LmtQ, ("And, expandValues is: '%s'", orionldState.uriParams.expandValues));
for (int ix = 0; ix < orionldState.in.expandValuesList.items; ix++)
{
LM_T(LmtQ, ("expandValuesList[%d]: '%s'", ix, orionldState.in.expandValuesList.array[ix]));
if (strcmp(orionldState.qVariable->value.s, orionldState.in.expandValuesList.array[ix]) == 0)
{
LM_T(LmtQ, ("The string '%s' needs to be expanded", stringValue));
stringValue = orionldContextItemExpand(orionldState.contextP, stringValue, true, NULL);
}
}
}
}

if (orionldState.useMalloc == false)
qNodeP->value.s = stringValue;
Expand Down Expand Up @@ -179,6 +197,12 @@ static QNode* qTermPush(QNode* prev, char* term, bool* lastTermIsTimestampP, cha

QNode* qNodeP = qNode(type);

if (type == QNodeVariable)
{
orionldState.qVariable = qNodeP;
LM_T(LmtQ, ("'%s' IS a VARIABLE", term));
}

if (dateTime == true)
{
LM_T(LmtQ, ("'%s' might be a DateTime", term));
Expand Down
3 changes: 2 additions & 1 deletion src/lib/orionld/q/qParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C"
#include "orionld/common/orionldState.h" // orionldState
#include "orionld/context/orionldAttributeExpand.h" // orionldAttributeExpand
#include "orionld/context/orionldSubAttributeExpand.h" // orionldSubAttributeExpand
#include "orionld/context/orionldContextItemExpand.h" // orionldContextItemExpand
#include "orionld/q/qVariableFix.h" // qVariableFix
#include "orionld/q/qClone.h" // qClone
#include "orionld/q/qNodeType.h" // qNodeType
Expand Down Expand Up @@ -188,7 +189,7 @@ QNode* qParse(QNode* qLexList, QNode* endNodeP, bool forDb, bool qToDbModel, cha
case QNodeTrueValue:
case QNodeFalseValue:
case QNodeRegexpValue:
if (compOpP == NULL) // Still no operatore - this is on the Left-Hand side - saved for later
if (compOpP == NULL) // Still no operator - this is on the Left-Hand side - saved for later
{
leftP = qLexP;
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/orionld/service/orionldServiceInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ static void restServicePrepare(OrionLdRestService* serviceP, OrionLdRestServiceS
serviceP->uriParams |= ORIONLD_URIPARAM_IDPATTERN;
serviceP->uriParams |= ORIONLD_URIPARAM_ATTRS;
serviceP->uriParams |= ORIONLD_URIPARAM_Q;
serviceP->uriParams |= ORIONLD_URIPARAM_EXPAND_VALUES;
serviceP->uriParams |= ORIONLD_URIPARAM_CSF;
serviceP->uriParams |= ORIONLD_URIPARAM_GEOREL;
serviceP->uriParams |= ORIONLD_URIPARAM_GEOMETRY;
Expand Down
1 change: 1 addition & 0 deletions src/lib/orionld/types/OrionLdRestService.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ typedef struct OrionLdRestServiceSimplifiedVector
#define ORIONLD_URIPARAM_ONLYIDS (UINT64_C(1) << 38)
#define ORIONLD_URIPARAM_ENTITYMAP (UINT64_C(1) << 39)
#define ORIONLD_URIPARAM_FORMAT (UINT64_C(1) << 40)
#define ORIONLD_URIPARAM_EXPAND_VALUES (UINT64_C(1) << 41)



Expand Down
77 changes: 77 additions & 0 deletions test/functionalTest/cases/0000_ngsild/ngsild_vocab-property.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ accumulatorStart --pretty-print
# 06. Dump/Reset accumulator, see urn:E1+V1 and urn:E2+V2
#
# 07. GET urn:E2 in simplified format
# 08. Query entities with q=V1==abc => see nothing
# 09. Query entities with q=V1==abc&expandValues=V1,V2 => see urn:E1
# 10. Query entities with q=V2==id&expandValues=V1,V2 => see urn:E2
#

echo '01. Create a subscription on entity type T'
Expand Down Expand Up @@ -134,6 +137,27 @@ echo
echo


echo "08. Query entities with q=V1==abc => see nothing"
echo "================================================"
orionCurl --url /ngsi-ld/v1/entities?q=V1==%22abc%22
echo
echo


echo "09. Query entities with q=V1==abc&expandValues=V1,V2 => see urn:E1"
echo "=================================================================="
orionCurl --url '/ngsi-ld/v1/entities?q=V1==%22abc%22&expandValues=V1,V2'
echo
echo


echo "10. Query entities with q=V2==id&expandValues=V1,V2 => see urn:E2"
echo "================================================================="
orionCurl --url '/ngsi-ld/v1/entities?q=V2==%22id%22&expandValues=V1,V2'
echo
echo


--REGEXPECT--
01. Create a subscription on entity type T
==========================================
Expand Down Expand Up @@ -343,6 +367,59 @@ Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-contextREGEX(.*)
}


08. Query entities with q=V1==abc => see nothing
================================================
HTTP/1.1 200 OK
Content-Length: 2
Content-Type: application/json
Date: REGEX(.*)

[]


09. Query entities with q=V1==abc&expandValues=V1,V2 => see urn:E1
==================================================================
HTTP/1.1 200 OK
Content-Length: 77
Content-Type: application/json
Date: REGEX(.*)
Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-contextREGEX(.*)

[
{
"V1": {
"type": "VocabularyProperty",
"vocab": "abc"
},
"id": "urn:E1",
"type": "T"
}
]


10. Query entities with q=V2==id&expandValues=V1,V2 => see urn:E2
=================================================================
HTTP/1.1 200 OK
Content-Length: 86
Content-Type: application/json
Date: REGEX(.*)
Link: <https://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-contextREGEX(.*)

[
{
"V2": {
"type": "VocabularyProperty",
"vocab": [
"vocab",
"id"
]
},
"id": "urn:E2",
"type": "T"
}
]


--TEARDOWN--
brokerStop CB
accumulatorStop
Expand Down

0 comments on commit 71c9582

Please sign in to comment.