diff --git a/search-service/config/detekt/baseline.xml b/search-service/config/detekt/baseline.xml index 1d0cf50cc..f61b1ab2c 100644 --- a/search-service/config/detekt/baseline.xml +++ b/search-service/config/detekt/baseline.xml @@ -27,8 +27,6 @@ LongParameterList:EntityAttributeService.kt$EntityAttributeService$( entityUri: URI, ngsiLdAttributes: List<NgsiLdAttribute>, expandedAttributes: ExpandedAttributes, disallowOverwrite: Boolean, createdAt: ZonedDateTime, sub: Sub? ) LongParameterList:TemporalEntityHandler.kt$TemporalEntityHandler$( @RequestHeader httpHeaders: HttpHeaders, @PathVariable entityId: URI, @PathVariable attrId: String, @PathVariable instanceId: URI, @RequestBody requestBody: Mono<String>, @AllowedParameters(notImplemented = [QP.LOCAL, QP.VIA]) @RequestParam queryParams: MultiValueMap<String, String> ) LongParameterList:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration$( entityId: URI, attributeName: ExpandedTerm, datasetId: URI?, attributePayload: ExpandedAttributeInstance, ngsiLdAttributeInstance: NgsiLdAttributeInstance, defaultCreatedAt: ZonedDateTime ) - MaxLineLength:DistributedEntityConsumptionServiceTests.kt$DistributedEntityConsumptionServiceTests$fun - MaximumLineLength:DistributedEntityConsumptionServiceTests.kt$DistributedEntityConsumptionServiceTests$ NestedBlockDepth:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration$override fun migrate(context: Context) SwallowedException:TemporalQueryUtils.kt$e: IllegalArgumentException diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/web/EntityHandler.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/web/EntityHandler.kt index 658ff07b0..3e3a3c8ef 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/web/EntityHandler.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/web/EntityHandler.kt @@ -84,7 +84,7 @@ class EntityHandler( suspend fun create( @RequestHeader httpHeaders: HttpHeaders, @RequestBody requestBody: Mono, - @AllowedParameters(implemented = [], notImplemented = [QueryParameter.LOCAL, QueryParameter.VIA]) + @AllowedParameters(implemented = [QueryParameter.LOCAL], notImplemented = [QueryParameter.VIA]) @RequestParam queryParams: MultiValueMap ): ResponseEntity<*> = either { val sub = getSubFromSecurityContext() @@ -94,8 +94,11 @@ class EntityHandler( val expandedEntity = expandJsonLdEntity(body, contexts) expandedEntity.toNgsiLdEntity().bind() - val (distributionStatuses, remainingEntity) = distributedEntityProvisionService - .distributeCreateEntity(expandedEntity, contexts) + val (distributionStatuses, remainingEntity) = + if (queryParams.getFirst(QP.LOCAL.key)?.toBoolean() != true) { + distributedEntityProvisionService + .distributeCreateEntity(expandedEntity, contexts) + } else emptyList() to expandedEntity val allStatuses = if (remainingEntity != null) { val localStatus: DistributionStatus = either { @@ -226,9 +229,9 @@ class EntityHandler( implemented = [ QP.OPTIONS, QP.FORMAT, QP.COUNT, QP.OFFSET, QP.LIMIT, QP.ID, QP.TYPE, QP.ID_PATTERN, QP.ATTRS, QP.Q, QP.GEOMETRY, QP.GEOREL, QP.COORDINATES, QP.GEOPROPERTY, QP.GEOMETRY_PROPERTY, - QP.LANG, QP.SCOPEQ, QP.CONTAINED_BY, QP.JOIN, QP.JOIN_LEVEL, QP.DATASET_ID, + QP.LANG, QP.SCOPEQ, QP.CONTAINED_BY, QP.JOIN, QP.JOIN_LEVEL, QP.DATASET_ID, QP.LOCAL ], - notImplemented = [QP.PICK, QP.OMIT, QP.EXPAND_VALUES, QP.CSF, QP.ENTITY_MAP, QP.LOCAL, QP.VIA] + notImplemented = [QP.PICK, QP.OMIT, QP.EXPAND_VALUES, QP.CSF, QP.ENTITY_MAP, QP.VIA] ) @RequestParam queryParams: MultiValueMap ): ResponseEntity<*> = either { @@ -240,35 +243,38 @@ class EntityHandler( val entitiesQuery = composeEntitiesQueryFromGet(applicationProperties.pagination, queryParams, contexts).bind() .validateMinimalQueryEntitiesParameters().bind() - val (entities, localCount) = entityQueryService.queryEntities(entitiesQuery, sub.getOrNull()).bind() + val (localExpandedEntities, localCount) = + entityQueryService.queryEntities(entitiesQuery, sub.getOrNull()).bind() - val filteredEntities = entities.filterAttributes(entitiesQuery.attrs, entitiesQuery.datasetId) + val filteredEntities = localExpandedEntities.filterAttributes(entitiesQuery.attrs, entitiesQuery.datasetId) val localEntities = compactEntities(filteredEntities, contexts).let { linkedEntityService.processLinkedEntities(it, entitiesQuery, sub.getOrNull()).bind() } - val (queryWarnings, remoteEntitiesWithCSR, remoteCounts) = - distributedEntityConsumptionService.distributeQueryEntitiesOperation( - entitiesQuery, - httpHeaders, - queryParams - ) - - val maxCount = (remoteCounts + localCount).maxBy { it ?: 0 } ?: 0 - - val (warnings, mergedEntities) = ContextSourceUtils.mergeEntitiesLists( - localEntities, - remoteEntitiesWithCSR - ).toPair().let { (mergeWarnings, mergedEntities) -> - val warnings = mergeWarnings?.let { queryWarnings + it } ?: queryWarnings - warnings to (mergedEntities ?: emptyList()) - } + val (warnings, entities, count) = + if (queryParams.getFirst(QP.LOCAL.key)?.toBoolean() != true) { + val (queryWarnings, remoteEntitiesWithCSR, remoteCounts) = + distributedEntityConsumptionService.distributeQueryEntitiesOperation( + entitiesQuery, + httpHeaders, + queryParams + ) + val maxCount = (remoteCounts + localCount).maxBy { it ?: 0 } ?: 0 + val (warnings, mergedEntities) = ContextSourceUtils.mergeEntitiesLists( + localEntities, + remoteEntitiesWithCSR + ).toPair().let { (mergeWarnings, mergedEntities) -> + val warnings = mergeWarnings?.let { queryWarnings + it } ?: queryWarnings + warnings to (mergedEntities ?: emptyList()) + } + Triple(warnings, mergedEntities, maxCount) + } else Triple(emptyList(), localEntities, localCount) buildQueryResponse( - mergedEntities.toFinalRepresentation(ngsiLdDataRepresentation), - maxCount, + entities.toFinalRepresentation(ngsiLdDataRepresentation), + count, "/ngsi-ld/v1/entities", entitiesQuery.paginationQuery, queryParams, @@ -290,9 +296,9 @@ class EntityHandler( @AllowedParameters( implemented = [ QP.OPTIONS, QP.FORMAT, QP.TYPE, QP.ATTRS, QP.GEOMETRY_PROPERTY, - QP.LANG, QP.CONTAINED_BY, QP.JOIN, QP.JOIN_LEVEL, QP.DATASET_ID, + QP.LANG, QP.CONTAINED_BY, QP.JOIN, QP.JOIN_LEVEL, QP.DATASET_ID, QP.LOCAL ], - notImplemented = [QP.PICK, QP.OMIT, QP.ENTITY_MAP, QP.LOCAL, QP.VIA] + notImplemented = [QP.PICK, QP.OMIT, QP.ENTITY_MAP, QP.VIA] ) @RequestParam queryParams: MultiValueMap ): ResponseEntity<*> = either { @@ -316,26 +322,30 @@ class EntityHandler( compactEntity(filteredExpandedEntity, contexts) } - val (warnings, remoteEntitiesWithCSR) = distributedEntityConsumptionService.distributeRetrieveEntityOperation( - entityId, - httpHeaders, - queryParams - ).let { (warnings, it) -> warnings.toMutableList() to it } - - val (mergeWarnings, mergedEntity) = ContextSourceUtils.mergeEntities( - localEntity.getOrNull(), - remoteEntitiesWithCSR - ).toPair() - - mergeWarnings?.let { warnings.addAll(it) } - - if (mergedEntity == null) { + val (entity, warnings) = + if (queryParams.getFirst(QP.LOCAL.key)?.toBoolean() != true) { + val (warnings, remoteEntitiesWithCSR) = distributedEntityConsumptionService + .distributeRetrieveEntityOperation( + entityId, + httpHeaders, + queryParams + ).let { (warnings, it) -> warnings.toMutableList() to it } + val (mergeWarnings, mergedEntity) = ContextSourceUtils.mergeEntities( + localEntity.getOrNull(), + remoteEntitiesWithCSR + ).toPair() + + mergeWarnings?.let { warnings.addAll(it) } + mergedEntity to warnings.toList() + } else localEntity.getOrNull() to emptyList() + + if (entity == null) { val localError = localEntity.leftOrNull() return localError!!.toErrorResponse().addWarnings(warnings) } val mergedEntityWithLinkedEntities = - linkedEntityService.processLinkedEntities(mergedEntity, entitiesQuery, sub.getOrNull()).bind() + linkedEntityService.processLinkedEntities(entity, entitiesQuery, sub.getOrNull()).bind() prepareGetSuccessResponseHeaders(mediaType, contexts) .let { diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/web/EntityHandlerTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/web/EntityHandlerTests.kt index ee7e5d912..48ca5499b 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/web/EntityHandlerTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/web/EntityHandlerTests.kt @@ -336,7 +336,7 @@ class EntityHandlerTests { """ { "type": "https://uri.etsi.org/ngsi-ld/errors/InvalidRequest", - "title": "The ['invalid'] parameters are not allowed on this endpoint. This endpoint does not accept any query parameters. ", + "title": "The ['invalid'] parameters are not allowed on this endpoint. Accepted query parameters are 'local'. ", "detail": "$DEFAULT_DETAIL" } """.trimIndent() @@ -348,7 +348,7 @@ class EntityHandlerTests { val jsonLdFile = ClassPathResource("/ngsild/aquac/breedingService.jsonld") webClient.post() - .uri("/ngsi-ld/v1/entities?local=true") + .uri("/ngsi-ld/v1/entities?Via=true") .bodyValue(jsonLdFile) .exchange() .expectStatus().isEqualTo(501) @@ -356,7 +356,7 @@ class EntityHandlerTests { """ { "type": "https://uri.etsi.org/ngsi-ld/errors/NotImplemented", - "title": "The ['local'] parameters have not been implemented yet. This endpoint does not accept any query parameters. ", + "title": "The ['Via'] parameters have not been implemented yet. Accepted query parameters are 'local'. ", "detail": "$DEFAULT_DETAIL" } """.trimIndent()