Skip to content

Commit

Permalink
feat(core): add support for NGSI-LD Null in Partial Attribute Update …
Browse files Browse the repository at this point in the history
…operation
  • Loading branch information
bobeal committed Dec 15, 2024
1 parent 58da24f commit 6354b4c
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 44 deletions.
1 change: 0 additions & 1 deletion search-service/config/detekt/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<ID>ClassNaming:V0_29_JsonLd_migrationTests.kt$V0_29_JsonLd_migrationTests</ID>
<ID>ClassNaming:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration : BaseJavaMigration</ID>
<ID>ComplexCondition:EntitiesQueryUtils.kt$geoQuery == null &amp;&amp; q.isNullOrEmpty() &amp;&amp; typeSelection.isNullOrEmpty() &amp;&amp; attrs.isEmpty()</ID>
<ID>ComplexCondition:EntityQueryService.kt$EntityQueryService$it &amp;&amp; !inverse || !it &amp;&amp; inverse</ID>
<ID>Filename:V0_29__JsonLd_migration.kt$db.migration.V0_29__JsonLd_migration.kt</ID>
<ID>LongMethod:AttributeInstanceService.kt$AttributeInstanceService$@Transactional suspend fun create(attributeInstance: AttributeInstance): Either&lt;APIException, Unit&gt;</ID>
<ID>LongMethod:EnabledAuthorizationServiceTests.kt$EnabledAuthorizationServiceTests$@Test fun `it should return serialized access control entities with other rigths if user is owner`()</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,34 +518,6 @@ class EntityAttributeService(
}
}

suspend fun hasNotDeletedAttribute(
id: URI,
attributeName: String,
datasetId: URI? = null
): Either<APIException, Boolean> {
val selectQuery =
"""
SELECT count(entity_id) as count
FROM temporal_entity_attribute
WHERE entity_id = :entity_id
AND deleted_at is null
${datasetId.toDatasetIdFilter()}
AND attribute_name = :attribute_name
""".trimIndent()

return databaseClient
.sql(selectQuery)
.bind("entity_id", id)
.bind("attribute_name", attributeName)
.let {
if (datasetId != null) it.bind("dataset_id", datasetId)
else it
}
.oneToResult {
it["count"] as Long == 1L
}
}

private fun rowToAttribute(row: Map<String, Any>) =
Attribute(
id = toUuid(row["id"]),
Expand Down Expand Up @@ -745,17 +717,33 @@ class EntityAttributeService(
): Either<APIException, UpdateResult> = either {
val attributeName = expandedAttribute.first
val attributeValues = expandedAttribute.second[0]
logger.debug(
"Updating attribute {} of entity {} with values: {}",
attributeName,
entityId,
attributeValues
)
logger.debug("Partial updating attribute {} in entity {}", attributeName, entityId)

val datasetId = attributeValues.getDatasetId()
val exists = hasNotDeletedAttribute(entityId, attributeName, datasetId).bind()
val currentAttribute = getForEntityAndAttribute(entityId, attributeName, datasetId).fold({ null }, { it })
val updateAttributeResult =
if (exists) {
if (currentAttribute == null) {
UpdateAttributeResult(
attributeName,
datasetId,
UpdateOperationResult.FAILED,
"Unknown attribute $attributeName with datasetId $datasetId in entity $entityId"
)
} else if (hasNgsiLdNullValue(currentAttribute, attributeValues)) {
deleteAttribute(
entityId,
attributeName,
datasetId,
false,
modifiedAt
).map {
UpdateAttributeResult(
attributeName,
datasetId,
UpdateOperationResult.DELETED
)
}.bind()
} else {
// first update payload in temporal entity attribute
val attribute = getForEntityAndAttribute(entityId, attributeName, datasetId).bind()
attributeValues[JSONLD_TYPE]?.let {
Expand Down Expand Up @@ -784,13 +772,6 @@ class EntityAttributeService(
datasetId,
UpdateOperationResult.UPDATED
)
} else {
UpdateAttributeResult(
attributeName,
datasetId,
UpdateOperationResult.FAILED,
"Unknown attribute $attributeName with datasetId $datasetId in entity $entityId"
)
}

updateResultFromDetailedResult(listOf(updateAttributeResult))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,50 @@ class EntityAttributeServiceTests : WithTimescaleContainer, WithKafkaContainer {
}
}

@Test
fun `it should delete an attribute in partial attribute update operation if its value is NGSI-LD null`() = runTest {
val rawEntity = loadSampleData()

coEvery { attributeInstanceService.create(any()) } returns Unit.right()
coEvery {
attributeInstanceService.addDeletedAttributeInstance(any(), any(), any(), any())
} returns Unit.right()

entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS).shouldSucceed()

val createdAt = ngsiLdDateTime()
val propertyToDelete = loadSampleData("fragments/beehive_mergeAttribute_null_fragment.json")
val expandedAttribute = expandAttribute(INCOMING_PROPERTY, propertyToDelete, APIC_COMPOUND_CONTEXTS)
entityAttributeService.partialUpdateAttribute(
beehiveTestCId,
expandedAttribute,
createdAt,
null
).shouldSucceedWith { updateResult ->
val updatedDetails = updateResult.updated
assertEquals(1, updatedDetails.size)
assertEquals(1, updatedDetails.filter { it.updateOperationResult == UpdateOperationResult.DELETED }.size)
}

coVerify(exactly = 1) {
attributeInstanceService.addDeletedAttributeInstance(
any(),
NGSILD_NULL,
createdAt,
expandAttribute(
INCOMING_PROPERTY,
"""
{
"type": "Property",
"value": "urn:ngsi-ld:null"
}
""".trimIndent(),
NGSILD_TEST_CORE_CONTEXTS
).second[0]
)
}
}

@Test
fun `it should replace an entity attribute`() = runTest {
val rawEntity = loadSampleData()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"type": "Property",
"value": "urn:ngsi-ld:null"
}

0 comments on commit 6354b4c

Please sign in to comment.