diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityQueryService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityQueryService.kt index 4eb51996c..7c756b569 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityQueryService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityQueryService.kt @@ -21,7 +21,6 @@ import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.AlreadyExistsException import com.egm.stellio.shared.model.ExpandedEntity import com.egm.stellio.shared.model.ResourceNotFoundException -import com.egm.stellio.shared.model.parameter.GeoQuery import com.egm.stellio.shared.util.Sub import com.egm.stellio.shared.util.buildQQuery import com.egm.stellio.shared.util.buildScopeQQuery @@ -131,7 +130,7 @@ class EntityQueryService( } ?: sqlFilter }.let { sqlFilter -> entitiesQuery.geoQuery?.let { geoQuery -> - sqlFilter.wrapToAndClause(GeoQuery.buildSqlFilter(geoQuery)) + sqlFilter.wrapToAndClause(geoQuery.buildSqlFilter()) } ?: sqlFilter } diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/LinkedEntityService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/LinkedEntityService.kt index a0feb4e3c..3ef6e2747 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/LinkedEntityService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/LinkedEntityService.kt @@ -7,8 +7,8 @@ import com.egm.stellio.search.entity.model.EntitiesQuery import com.egm.stellio.search.entity.model.EntitiesQueryFromGet import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.CompactedEntity -import com.egm.stellio.shared.model.JoinType import com.egm.stellio.shared.model.LinkedEntityQuery +import com.egm.stellio.shared.model.LinkedEntityQuery.Companion.JoinType import com.egm.stellio.shared.model.PaginationQuery import com.egm.stellio.shared.model.getRelationshipsObjects import com.egm.stellio.shared.model.inlineLinkedEntities 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 775cdb425..d0227a47d 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 @@ -356,8 +356,8 @@ class EntityHandler( @RequestBody requestBody: Mono, @RequestParam @AllowedParameters( - implemented = [QP.OPTIONS], // todo type no implemented? - notImplemented = [QP.TYPE, QP.LOCAL, QP.VIA] + implemented = [QP.OPTIONS], + notImplemented = [QP.TYPE, QP.LOCAL, QP.VIA] // type is for dist-ops ) params: MultiValueMap ): ResponseEntity<*> = either { diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/scope/ScopeService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/scope/ScopeService.kt index 500ce6db3..2968f7cc6 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/scope/ScopeService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/scope/ScopeService.kt @@ -25,6 +25,7 @@ import com.egm.stellio.search.entity.model.updateResultFromDetailedResult import com.egm.stellio.search.temporal.model.AttributeInstance.TemporalProperty import com.egm.stellio.search.temporal.model.TemporalEntitiesQuery import com.egm.stellio.search.temporal.model.TemporalQuery +import com.egm.stellio.search.temporal.util.WHOLE_TIME_RANGE_DURATION import com.egm.stellio.search.temporal.util.composeAggregationSelectClause import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.ExpandedAttributeInstances @@ -36,7 +37,6 @@ import com.egm.stellio.shared.util.JsonLdUtils import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_SCOPE_PROPERTY import com.egm.stellio.shared.util.JsonUtils.serializeObject import com.egm.stellio.shared.util.Sub -import com.egm.stellio.shared.util.WHOLE_TIME_RANGE_DURATION import io.r2dbc.postgresql.codec.Json import org.springframework.r2dbc.core.DatabaseClient import org.springframework.r2dbc.core.bind diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceService.kt index 15afb8c85..9f1fa6f32 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceService.kt @@ -26,6 +26,7 @@ import com.egm.stellio.search.temporal.model.SimplifiedAttributeInstanceResult import com.egm.stellio.search.temporal.model.TemporalEntitiesQuery import com.egm.stellio.search.temporal.model.TemporalQuery import com.egm.stellio.search.temporal.model.TemporalQuery.Timerel +import com.egm.stellio.search.temporal.util.WHOLE_TIME_RANGE_DURATION import com.egm.stellio.search.temporal.util.composeAggregationSelectClause import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.ExpandedAttributeInstances @@ -34,7 +35,6 @@ import com.egm.stellio.shared.model.OperationNotSupportedException import com.egm.stellio.shared.model.ResourceNotFoundException import com.egm.stellio.shared.model.toNgsiLdAttribute import com.egm.stellio.shared.util.INCONSISTENT_VALUES_IN_AGGREGATION_MESSAGE -import com.egm.stellio.shared.util.WHOLE_TIME_RANGE_DURATION import com.egm.stellio.shared.util.attributeOrInstanceNotFoundMessage import com.egm.stellio.shared.util.ngsiLdDateTime import org.springframework.r2dbc.core.DatabaseClient diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtils.kt b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtils.kt index 8187c3564..83ae63dc8 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtils.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtils.kt @@ -22,7 +22,6 @@ import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.BadRequestDataException import com.egm.stellio.shared.model.parameter.QueryParameter import com.egm.stellio.shared.util.OptionsParamValue -import com.egm.stellio.shared.util.WHOLE_TIME_RANGE_DURATION import com.egm.stellio.shared.util.hasValueInOptionsParam import com.egm.stellio.shared.util.parseTimeParameter import org.springframework.util.MultiValueMap @@ -30,6 +29,8 @@ import org.springframework.util.MultiValueMapAdapter import java.time.ZonedDateTime import java.util.Optional +const val WHOLE_TIME_RANGE_DURATION = "PT0S" + fun composeTemporalEntitiesQueryFromGet( defaultPagination: ApplicationProperties.Pagination, requestParams: MultiValueMap, diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/LinkedEntityServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/LinkedEntityServiceTests.kt index 961c50bbf..105e6162d 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/LinkedEntityServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/LinkedEntityServiceTests.kt @@ -4,8 +4,8 @@ import arrow.core.right import com.egm.stellio.search.entity.model.EntitiesQueryFromGet import com.egm.stellio.shared.model.CompactedEntity import com.egm.stellio.shared.model.ExpandedEntity -import com.egm.stellio.shared.model.JoinType import com.egm.stellio.shared.model.LinkedEntityQuery +import com.egm.stellio.shared.model.LinkedEntityQuery.Companion.JoinType import com.egm.stellio.shared.model.PaginationQuery import com.egm.stellio.shared.util.JsonUtils.deserializeAsMap import com.egm.stellio.shared.util.JsonUtils.serializeObject diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/EntitiesQueryUtilsTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/EntitiesQueryUtilsTests.kt index bc062cacc..8a65ef256 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/EntitiesQueryUtilsTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/EntitiesQueryUtilsTests.kt @@ -9,7 +9,7 @@ import com.egm.stellio.shared.config.ApplicationProperties import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.BadRequestDataException import com.egm.stellio.shared.model.EntitySelector -import com.egm.stellio.shared.model.JoinType +import com.egm.stellio.shared.model.LinkedEntityQuery.Companion.JoinType import com.egm.stellio.shared.model.parameter.GeoQuery import com.egm.stellio.shared.model.parameter.Georel import com.egm.stellio.shared.util.APIARY_TYPE diff --git a/shared/src/main/kotlin/com/egm/stellio/shared/model/LinkedEntityQuery.kt b/shared/src/main/kotlin/com/egm/stellio/shared/model/LinkedEntityQuery.kt index 3a5213811..3dbac87f9 100644 --- a/shared/src/main/kotlin/com/egm/stellio/shared/model/LinkedEntityQuery.kt +++ b/shared/src/main/kotlin/com/egm/stellio/shared/model/LinkedEntityQuery.kt @@ -16,6 +16,17 @@ data class LinkedEntityQuery( companion object { const val DEFAULT_JOIN_LEVEL = 1 + enum class JoinType(val type: String) { + FLAT("flat"), + INLINE("inline"), + NONE("@none"); + + companion object { + fun forType(type: String): JoinType? = + entries.find { it.type == type } + } + } + fun parseLinkedEntityQueryParameters( join: String?, joinLevel: String?, @@ -48,14 +59,3 @@ data class LinkedEntityQuery( "'$param' is not a recognized value for 'joinLevel' parameter (only positive integers are allowed)" } } - -enum class JoinType(val type: String) { - FLAT("flat"), - INLINE("inline"), - NONE("@none"); - - companion object { - fun forType(type: String): JoinType? = - entries.find { it.type == type } - } -} diff --git a/shared/src/main/kotlin/com/egm/stellio/shared/model/parameter/GeoQuery.kt b/shared/src/main/kotlin/com/egm/stellio/shared/model/parameter/GeoQuery.kt index 54fa0274a..7b05d7fb2 100644 --- a/shared/src/main/kotlin/com/egm/stellio/shared/model/parameter/GeoQuery.kt +++ b/shared/src/main/kotlin/com/egm/stellio/shared/model/parameter/GeoQuery.kt @@ -43,6 +43,38 @@ data class GeoQuery( } } + fun buildSqlFilter(target: ExpandedEntity? = null): String { + val targetWKTCoordinates = + """ + (select jsonb_path_query_first(#{TARGET}#, '$."$geoproperty"."$NGSILD_GEOPROPERTY_VALUE"[0]')->>'$JSONLD_VALUE') + """.trimIndent() + val georelQuery = Georel.prepareQuery(georel) + + return ( + if (georelQuery.first == Georel.NEAR_DISTANCE_MODIFIER) + """ + public.ST_Distance( + cast('SRID=4326;${wktCoordinates.value}' as public.geography), + cast('SRID=4326;' || $targetWKTCoordinates as public.geography), + false + ) ${georelQuery.second} ${georelQuery.third} + """.trimIndent() + else + """ + public.ST_${georelQuery.first}( + public.ST_GeomFromText('${wktCoordinates.value}'), + public.ST_GeomFromText($targetWKTCoordinates) + ) + """.trimIndent() + ) + .let { + if (target == null) + it.replace("#{TARGET}#", "entity_payload.payload") + else + it.replace("#{TARGET}#", "'" + JsonUtils.serializeObject(target.members) + "'") + } + } + companion object { fun parseGeoQueryParameters( @@ -83,37 +115,5 @@ data class GeoQuery( geoproperty = geoproperty ) } - - fun buildSqlFilter(geoQuery: GeoQuery, target: ExpandedEntity? = null): String { - val targetWKTCoordinates = - """ - (select jsonb_path_query_first(#{TARGET}#, '$."${geoQuery.geoproperty}"."$NGSILD_GEOPROPERTY_VALUE"[0]')->>'$JSONLD_VALUE') - """.trimIndent() - val georelQuery = Georel.prepareQuery(geoQuery.georel) - - return ( - if (georelQuery.first == Georel.NEAR_DISTANCE_MODIFIER) - """ - public.ST_Distance( - cast('SRID=4326;${geoQuery.wktCoordinates.value}' as public.geography), - cast('SRID=4326;' || $targetWKTCoordinates as public.geography), - false - ) ${georelQuery.second} ${georelQuery.third} - """.trimIndent() - else - """ - public.ST_${georelQuery.first}( - public.ST_GeomFromText('${geoQuery.wktCoordinates.value}'), - public.ST_GeomFromText($targetWKTCoordinates) - ) - """.trimIndent() - ) - .let { - if (target == null) - it.replace("#{TARGET}#", "entity_payload.payload") - else - it.replace("#{TARGET}#", "'" + JsonUtils.serializeObject(target.members) + "'") - } - } } } diff --git a/shared/src/main/kotlin/com/egm/stellio/shared/util/ApiUtils.kt b/shared/src/main/kotlin/com/egm/stellio/shared/util/ApiUtils.kt index efce5dec3..287f1d119 100644 --- a/shared/src/main/kotlin/com/egm/stellio/shared/util/ApiUtils.kt +++ b/shared/src/main/kotlin/com/egm/stellio/shared/util/ApiUtils.kt @@ -36,8 +36,6 @@ val GEO_JSON_MEDIA_TYPE = MediaType.valueOf(GEO_JSON_CONTENT_TYPE) val linkHeaderRegex: Regex = """<(.*)>;rel="http://www.w3.org/ns/json-ld#context";type="application/ld\+json"""".toRegex() -const val WHOLE_TIME_RANGE_DURATION = "PT0S" - /** * As per 6.3.5, If the request verb is GET or DELETE, then the associated JSON-LD "@context" shall be obtained from a * Link header as mandated by JSON-LD, section 6.2.extract @context from Link header. diff --git a/shared/src/test/kotlin/com/egm/stellio/shared/util/GeoQueryUtilsTests.kt b/shared/src/test/kotlin/com/egm/stellio/shared/util/GeoQueryUtilsTests.kt index 2d4ec280b..b5a1b3b39 100644 --- a/shared/src/test/kotlin/com/egm/stellio/shared/util/GeoQueryUtilsTests.kt +++ b/shared/src/test/kotlin/com/egm/stellio/shared/util/GeoQueryUtilsTests.kt @@ -140,7 +140,7 @@ class GeoQueryUtilsTests { ) val expandedEntity = gimmeSimpleEntityWithGeoProperty("location", 24.30623, 60.07966) - val queryStatement = GeoQuery.buildSqlFilter(geoQuery, expandedEntity) + val queryStatement = geoQuery.buildSqlFilter(expandedEntity) assertEqualsIgnoringNoise( """ @@ -164,7 +164,7 @@ class GeoQueryUtilsTests { ) val expandedEntity = gimmeSimpleEntityWithGeoProperty("location", 60.07966, 24.30623) - val queryStatement = GeoQuery.buildSqlFilter(geoQuery, expandedEntity) + val queryStatement = geoQuery.buildSqlFilter(expandedEntity) assertEqualsIgnoringNoise( """ @@ -188,7 +188,7 @@ class GeoQueryUtilsTests { ) val expandedEntity = gimmeSimpleEntityWithGeoProperty("location", 60.30623, 30.07966) - val queryStatement = GeoQuery.buildSqlFilter(geoQuery, expandedEntity) + val queryStatement = geoQuery.buildSqlFilter(expandedEntity) assertEqualsIgnoringNoise( """ diff --git a/subscription-service/src/main/kotlin/com/egm/stellio/subscription/service/SubscriptionService.kt b/subscription-service/src/main/kotlin/com/egm/stellio/subscription/service/SubscriptionService.kt index c7608250c..b44ce26cb 100644 --- a/subscription-service/src/main/kotlin/com/egm/stellio/subscription/service/SubscriptionService.kt +++ b/subscription-service/src/main/kotlin/com/egm/stellio/subscription/service/SubscriptionService.kt @@ -672,16 +672,13 @@ class SubscriptionService( expandedEntity: ExpandedEntity ): String? = geoQ?.let { - GeoQuery.buildSqlFilter( - GeoQuery( - georel = geoQ.georel, - geometry = GeoQuery.GeometryType.forType(geoQ.geometry)!!, - coordinates = geoQ.coordinates, - geoproperty = geoQ.geoproperty, - wktCoordinates = WKTCoordinates(geoQ.pgisGeometry!!) - ), - expandedEntity - ) + GeoQuery( + georel = geoQ.georel, + geometry = GeoQuery.GeometryType.forType(geoQ.geometry)!!, + coordinates = geoQ.coordinates, + geoproperty = geoQ.geoproperty, + wktCoordinates = WKTCoordinates(geoQ.pgisGeometry!!) + ).buildSqlFilter(expandedEntity) } suspend fun updateSubscriptionNotification(