diff --git a/search-service/config/detekt/baseline.xml b/search-service/config/detekt/baseline.xml index cfdb28675..a8fcbc64e 100644 --- a/search-service/config/detekt/baseline.xml +++ b/search-service/config/detekt/baseline.xml @@ -16,8 +16,8 @@ LongMethod:TemporalQueryServiceTests.kt$TemporalQueryServiceTests$@Test fun `it should return an empty list for an attribute if it has no temporal values`() LongMethod:TemporalScopeBuilderTests.kt$TemporalScopeBuilderTests$@Test fun `it should build an aggregated temporal representation of scopes`() LongMethod:V0_29__JsonLd_migration.kt$V0_29__JsonLd_migration$override fun migrate(context: Context) - LongParameterList:AttributeInstance.kt$AttributeInstance.Companion$( attribute: UUID, instanceId: URI = generateRandomInstanceId(), timeAndProperty: Pair<ZonedDateTime, TemporalProperty>, value: Triple<String?, Double?, WKTCoordinates?>, payload: ExpandedAttributeInstance, sub: String? ) - LongParameterList:AttributeInstance.kt$AttributeInstance.Companion$( attribute: UUID, instanceId: URI = generateRandomInstanceId(), timeProperty: TemporalProperty? = TemporalProperty.OBSERVED_AT, modifiedAt: ZonedDateTime? = null, attributeMetadata: AttributeMetadata, payload: ExpandedAttributeInstance, time: ZonedDateTime, sub: String? = null ) + LongParameterList:AttributeInstance.kt$AttributeInstance.Companion$( attributeUuid: UUID, instanceId: URI = generateRandomInstanceId(), timeAndProperty: Pair<ZonedDateTime, TemporalProperty>, value: Triple<String?, Double?, WKTCoordinates?>, payload: ExpandedAttributeInstance, sub: String? ) + LongParameterList:AttributeInstance.kt$AttributeInstance.Companion$( attributeUuid: UUID, instanceId: URI = generateRandomInstanceId(), timeProperty: TemporalProperty? = TemporalProperty.OBSERVED_AT, modifiedAt: ZonedDateTime? = null, attributeMetadata: AttributeMetadata, payload: ExpandedAttributeInstance, time: ZonedDateTime, sub: String? = null ) LongParameterList:EntityAttributeService.kt$EntityAttributeService$( attribute: Attribute, attributeName: ExpandedTerm, attributeMetadata: AttributeMetadata, mergedAt: ZonedDateTime, observedAt: ZonedDateTime?, attributePayload: ExpandedAttributeInstance, sub: Sub? ) LongParameterList:EntityAttributeService.kt$EntityAttributeService$( attribute: Attribute, ngsiLdAttribute: NgsiLdAttribute, attributeMetadata: AttributeMetadata, createdAt: ZonedDateTime, attributePayload: ExpandedAttributeInstance, sub: Sub? ) LongParameterList:EntityAttributeService.kt$EntityAttributeService$( entityId: URI, attributeName: ExpandedTerm, attributeMetadata: AttributeMetadata, createdAt: ZonedDateTime, attributePayload: ExpandedAttributeInstance, sub: Sub? ) diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityAttributeService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityAttributeService.kt index 58b25b17c..e4e7f02e7 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityAttributeService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityAttributeService.kt @@ -10,9 +10,14 @@ import arrow.fx.coroutines.parMap import com.egm.stellio.search.common.util.* import com.egm.stellio.search.entity.model.* import com.egm.stellio.search.entity.model.Attribute +import com.egm.stellio.search.entity.util.guessAttributeValueType +import com.egm.stellio.search.entity.util.mergePatch +import com.egm.stellio.search.entity.util.partialUpdatePatch +import com.egm.stellio.search.entity.util.prepareAttributes +import com.egm.stellio.search.entity.util.toAttributeMetadata +import com.egm.stellio.search.entity.util.toExpandedAttributeInstance import com.egm.stellio.search.temporal.model.AttributeInstance import com.egm.stellio.search.temporal.service.AttributeInstanceService -import com.egm.stellio.search.temporal.util.* import com.egm.stellio.shared.model.* import com.egm.stellio.shared.util.* import com.egm.stellio.shared.util.AttributeType @@ -121,7 +126,7 @@ class EntityAttributeService( * To be removed at some point later. */ @Transactional - suspend fun createEntityAttributes( + suspend fun createAttributes( payload: String, contexts: List, sub: String? = null @@ -131,12 +136,12 @@ class EntityAttributeService( val ngsiLdEntity = expandedEntity.toNgsiLdEntity().bind() ngsiLdEntity.prepareAttributes() .map { - createEntityAttributes(ngsiLdEntity, expandedEntity, it, createdAt, sub).bind() + createAttributes(ngsiLdEntity, expandedEntity, it, createdAt, sub).bind() }.bind() } @Transactional - suspend fun createEntityAttributes( + suspend fun createAttributes( ngsiLdEntity: NgsiLdEntity, expandedEntity: ExpandedEntity, attributesMetadata: List>, @@ -190,7 +195,7 @@ class EntityAttributeService( create(attribute).bind() val attributeInstance = AttributeInstance( - attribute = attribute.id, + attributeUuid = attribute.id, timeProperty = AttributeInstance.TemporalProperty.CREATED_AT, time = createdAt, attributeMetadata = attributeMetadata, @@ -201,7 +206,7 @@ class EntityAttributeService( if (attributeMetadata.observedAt != null) { val attributeObservedAtInstance = AttributeInstance( - attribute = attribute.id, + attributeUuid = attribute.id, time = attributeMetadata.observedAt, attributeMetadata = attributeMetadata, payload = attributePayload @@ -233,7 +238,7 @@ class EntityAttributeService( ).bind() val attributeInstance = AttributeInstance( - attribute = attribute.id, + attributeUuid = attribute.id, timeProperty = AttributeInstance.TemporalProperty.MODIFIED_AT, time = createdAt, attributeMetadata = attributeMetadata, @@ -244,7 +249,7 @@ class EntityAttributeService( if (attributeMetadata.observedAt != null) { val attributeObservedAtInstance = AttributeInstance( - attribute = attribute.id, + attributeUuid = attribute.id, time = attributeMetadata.observedAt, attributeMetadata = attributeMetadata, payload = attributePayload @@ -286,7 +291,7 @@ class EntityAttributeService( } @Transactional - suspend fun deleteTemporalAttributesOfEntity(entityId: URI): Either { + suspend fun deleteAttributes(entityId: URI): Either { val uuids = databaseClient.sql( """ DELETE FROM temporal_entity_attribute @@ -305,7 +310,7 @@ class EntityAttributeService( } @Transactional - suspend fun deleteTemporalAttribute( + suspend fun deleteAttribute( entityId: URI, attributeName: String, datasetId: URI?, @@ -315,15 +320,15 @@ class EntityAttributeService( logger.debug("Deleting attribute {} from entity {} (all: {})", attributeName, entityId, deleteAll) if (deleteAll) { attributeInstanceService.deleteAllInstancesOfAttribute(entityId, attributeName).bind() - deleteTemporalAttributeAllInstancesReferences(entityId, attributeName).bind() + deleteAllInstances(entityId, attributeName).bind() } else { attributeInstanceService.deleteInstancesOfAttribute(entityId, attributeName, datasetId).bind() - deleteTemporalAttributeReferences(entityId, attributeName, datasetId).bind() + deleteSpecificInstance(entityId, attributeName, datasetId).bind() } } @Transactional - suspend fun deleteTemporalAttributeReferences( + suspend fun deleteSpecificInstance( entityId: URI, attributeName: String, datasetId: URI? @@ -345,7 +350,7 @@ class EntityAttributeService( .execute() @Transactional - suspend fun deleteTemporalAttributeAllInstancesReferences( + suspend fun deleteAllInstances( entityId: URI, attributeName: String ): Either = @@ -360,7 +365,7 @@ class EntityAttributeService( .bind("attribute_name", attributeName) .execute() - suspend fun getForTemporalEntities( + suspend fun getForEntities( entitiesIds: List, entitiesQuery: EntitiesQuery ): List { @@ -540,7 +545,7 @@ class EntityAttributeService( } @Transactional - suspend fun appendEntityAttributes( + suspend fun appendAttributes( entityUri: URI, ngsiLdAttributes: List, expandedAttributes: ExpandedAttributes, @@ -605,7 +610,7 @@ class EntityAttributeService( }.fold({ it.left() }, { updateResultFromDetailedResult(it).right() }) @Transactional - suspend fun updateEntityAttributes( + suspend fun updateAttributes( entityUri: URI, ngsiLdAttributes: List, expandedAttributes: ExpandedAttributes, @@ -660,7 +665,7 @@ class EntityAttributeService( }.fold({ it.left() }, { updateResultFromDetailedResult(it).right() }) @Transactional - suspend fun partialUpdateEntityAttribute( + suspend fun partialUpdateAttribute( entityId: URI, expandedAttribute: ExpandedAttribute, modifiedAt: ZonedDateTime, @@ -721,7 +726,7 @@ class EntityAttributeService( } @Transactional - suspend fun upsertEntityAttributes( + suspend fun upsertAttributes( entityUri: URI, ngsiLdAttribute: NgsiLdAttribute, expandedAttributes: ExpandedAttributes, @@ -764,7 +769,7 @@ class EntityAttributeService( } @Transactional - suspend fun mergeEntityAttributes( + suspend fun mergeAttributes( entityUri: URI, ngsiLdAttributes: List, expandedAttributes: ExpandedAttributes, @@ -822,7 +827,7 @@ class EntityAttributeService( }.fold({ it.left() }, { updateResultFromDetailedResult(it).right() }) @Transactional - suspend fun replaceEntityAttribute( + suspend fun replaceAttribute( entityId: URI, ngsiLdAttribute: NgsiLdAttribute, expandedAttribute: ExpandedAttribute, @@ -924,7 +929,7 @@ class EntityAttributeService( Pair(modifiedAt, AttributeInstance.TemporalProperty.MODIFIED_AT) return AttributeInstance( - attribute = attribute.id, + attributeUuid = attribute.id, timeAndProperty = timeAndProperty, value = value, payload = expandedAttributeInstance, diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityOperationService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityOperationService.kt index 1e2bdc2b7..9e02b26f7 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityOperationService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityOperationService.kt @@ -234,7 +234,7 @@ class EntityOperationService( sub: Sub? ): Either = either { val (jsonLdEntity, ngsiLdEntity) = entity - entityAttributeService.deleteTemporalAttributesOfEntity(ngsiLdEntity.id).bind() + entityAttributeService.deleteAttributes(ngsiLdEntity.id).bind() entityService.appendAttributes( ngsiLdEntity.id, jsonLdEntity.getModifiableMembers(), diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityService.kt index fdebc1681..91516ee86 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/service/EntityService.kt @@ -9,8 +9,8 @@ import com.egm.stellio.search.common.util.* import com.egm.stellio.search.entity.model.* import com.egm.stellio.search.entity.model.Attribute import com.egm.stellio.search.entity.model.OperationType.* +import com.egm.stellio.search.entity.util.prepareAttributes import com.egm.stellio.search.scope.ScopeService -import com.egm.stellio.search.temporal.util.prepareAttributes import com.egm.stellio.shared.model.* import com.egm.stellio.shared.util.* import com.egm.stellio.shared.util.AuthContextModel.SpecificAccessPolicy @@ -47,7 +47,7 @@ class EntityService( logger.debug("Creating entity {}", ngsiLdEntity.id) createEntityPayload(ngsiLdEntity, expandedEntity, createdAt, sub = sub).bind() - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( ngsiLdEntity, expandedEntity, attributesMetadata, @@ -96,7 +96,7 @@ class EntityService( val mergedAt = ngsiLdDateTime() val coreUpdateResult = updateCoreAttributes(entityId, coreAttrs, mergedAt, MERGE_ENTITY).bind() - val attrsUpdateResult = entityAttributeService.mergeEntityAttributes( + val attrsUpdateResult = entityAttributeService.mergeAttributes( entityId, otherAttrs.toMap().toNgsiLdAttributes().bind(), expandedAttributes, @@ -125,10 +125,10 @@ class EntityService( val attributesMetadata = ngsiLdEntity.prepareAttributes().bind() logger.debug("Replacing entity {}", ngsiLdEntity.id) - entityAttributeService.deleteTemporalAttributesOfEntity(entityId) + entityAttributeService.deleteAttributes(entityId) replaceEntityPayload(ngsiLdEntity, expandedEntity, replacedAt, sub).bind() - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( ngsiLdEntity, expandedEntity, attributesMetadata, @@ -481,7 +481,7 @@ class EntityService( if (disallowOverwrite) APPEND_ATTRIBUTES else APPEND_ATTRIBUTES_OVERWRITE_ALLOWED val coreUpdateResult = updateCoreAttributes(entityUri, coreAttrs, createdAt, operationType).bind() - val attrsUpdateResult = entityAttributeService.appendEntityAttributes( + val attrsUpdateResult = entityAttributeService.appendAttributes( entityUri, otherAttrs.toMap().toNgsiLdAttributes().bind(), expandedAttributes, @@ -510,7 +510,7 @@ class EntityService( val createdAt = ngsiLdDateTime() val coreUpdateResult = updateCoreAttributes(entityUri, coreAttrs, createdAt, UPDATE_ATTRIBUTES).bind() - val attrsUpdateResult = entityAttributeService.updateEntityAttributes( + val attrsUpdateResult = entityAttributeService.updateAttributes( entityUri, otherAttrs.toMap().toNgsiLdAttributes().bind(), expandedAttributes, @@ -534,7 +534,7 @@ class EntityService( sub: Sub? ): Either = either { val modifiedAt = ngsiLdDateTime() - val updateResult = entityAttributeService.partialUpdateEntityAttribute( + val updateResult = entityAttributeService.partialUpdateAttribute( entityId, expandedAttribute, modifiedAt, @@ -560,7 +560,7 @@ class EntityService( val jsonLdAttribute = mapOf(attributeName to listOf(expandedAttributeInstance)) val ngsiLdAttribute = jsonLdAttribute.toNgsiLdAttributes().bind()[0] - entityAttributeService.upsertEntityAttributes( + entityAttributeService.upsertAttributes( entityId, ngsiLdAttribute, jsonLdAttribute, @@ -585,7 +585,7 @@ class EntityService( val ngsiLdAttribute = listOf(expandedAttribute).toMap().toNgsiLdAttributes().bind()[0] val replacedAt = ngsiLdDateTime() - val updateResult = entityAttributeService.replaceEntityAttribute( + val updateResult = entityAttributeService.replaceAttribute( entityId, ngsiLdAttribute, expandedAttribute, @@ -675,7 +675,7 @@ class EntityService( } .bind() - entityAttributeService.deleteTemporalAttributesOfEntity(entityId).bind() + entityAttributeService.deleteAttributes(entityId).bind() scopeService.deleteHistory(entityId).bind() entity } @@ -695,7 +695,7 @@ class EntityService( attributeName, datasetId ).bind() - entityAttributeService.deleteTemporalAttribute( + entityAttributeService.deleteAttribute( entityId, attributeName, datasetId, diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/AttributeInstanceUtils.kt b/search-service/src/main/kotlin/com/egm/stellio/search/entity/util/AttributeUtils.kt similarity index 55% rename from search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/AttributeInstanceUtils.kt rename to search-service/src/main/kotlin/com/egm/stellio/search/entity/util/AttributeUtils.kt index d0262c2db..32d2c2c35 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/util/AttributeInstanceUtils.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/entity/util/AttributeUtils.kt @@ -1,4 +1,4 @@ -package com.egm.stellio.search.temporal.util +package com.egm.stellio.search.entity.util import arrow.core.Either import arrow.core.left @@ -7,17 +7,23 @@ import arrow.core.right import com.egm.stellio.search.common.util.deserializeAsMap import com.egm.stellio.search.common.util.valueToDoubleOrNull import com.egm.stellio.search.entity.model.Attribute -import com.egm.stellio.search.entity.model.Attribute.AttributeValueType import com.egm.stellio.search.entity.model.AttributeMetadata -import com.egm.stellio.shared.model.* -import com.egm.stellio.shared.util.JsonLdUtils.JSONLD_LANGUAGE -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_JSONPROPERTY_VALUE -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_LANGUAGEPROPERTY_VALUE -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_PROPERTY_VALUE -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_VOCABPROPERTY_VALUE -import com.egm.stellio.shared.util.JsonLdUtils.logger +import com.egm.stellio.shared.model.APIException +import com.egm.stellio.shared.model.BadRequestDataException +import com.egm.stellio.shared.model.ExpandedAttributeInstance +import com.egm.stellio.shared.model.NgsiLdAttributeInstance +import com.egm.stellio.shared.model.NgsiLdEntity +import com.egm.stellio.shared.model.NgsiLdGeoPropertyInstance +import com.egm.stellio.shared.model.NgsiLdJsonPropertyInstance +import com.egm.stellio.shared.model.NgsiLdLanguagePropertyInstance +import com.egm.stellio.shared.model.NgsiLdPropertyInstance +import com.egm.stellio.shared.model.NgsiLdRelationshipInstance +import com.egm.stellio.shared.model.NgsiLdVocabPropertyInstance +import com.egm.stellio.shared.model.WKTCoordinates +import com.egm.stellio.shared.model.getPropertyValue +import com.egm.stellio.shared.util.JsonLdUtils +import com.egm.stellio.shared.util.JsonUtils import com.egm.stellio.shared.util.JsonUtils.deserializeAsMap -import com.egm.stellio.shared.util.JsonUtils.serializeObject import com.savvasdalkitsis.jsonmerger.JsonMerger import io.r2dbc.postgresql.codec.Json import java.time.LocalDate @@ -46,36 +52,36 @@ fun NgsiLdAttributeInstance.toAttributeMetadata(): Either Triple( Attribute.AttributeType.Relationship, - AttributeValueType.URI, + Attribute.AttributeValueType.URI, Triple(this.objectId.toString(), null, null) ) is NgsiLdGeoPropertyInstance -> Triple( Attribute.AttributeType.GeoProperty, - AttributeValueType.GEOMETRY, + Attribute.AttributeValueType.GEOMETRY, Triple(null, null, this.coordinates) ) is NgsiLdJsonPropertyInstance -> Triple( Attribute.AttributeType.JsonProperty, - AttributeValueType.JSON, - Triple(serializeObject(this.json), null, null) + Attribute.AttributeValueType.JSON, + Triple(JsonUtils.serializeObject(this.json), null, null) ) is NgsiLdLanguagePropertyInstance -> Triple( Attribute.AttributeType.LanguageProperty, - AttributeValueType.ARRAY, - Triple(serializeObject(this.languageMap), null, null) + Attribute.AttributeValueType.ARRAY, + Triple(JsonUtils.serializeObject(this.languageMap), null, null) ) is NgsiLdVocabPropertyInstance -> Triple( Attribute.AttributeType.VocabProperty, - AttributeValueType.ARRAY, - Triple(serializeObject(this.vocab), null, null) + Attribute.AttributeValueType.ARRAY, + Triple(JsonUtils.serializeObject(this.vocab), null, null) ) } if (attributeValue == Triple(null, null, null)) { - logger.warn("Unable to get a value from attribute: $this") + JsonLdUtils.logger.warn("Unable to get a value from attribute: $this") return BadRequestDataException("Unable to get a value from attribute: $this").left() } @@ -93,36 +99,36 @@ fun NgsiLdAttributeInstance.toAttributeMetadata(): Either guessPropertyValueType(expandedAttributeInstance.getPropertyValue()!!).first - Attribute.AttributeType.Relationship -> AttributeValueType.URI - Attribute.AttributeType.GeoProperty -> AttributeValueType.GEOMETRY - Attribute.AttributeType.JsonProperty -> AttributeValueType.JSON - Attribute.AttributeType.LanguageProperty -> AttributeValueType.ARRAY - Attribute.AttributeType.VocabProperty -> AttributeValueType.ARRAY + Attribute.AttributeType.Relationship -> Attribute.AttributeValueType.URI + Attribute.AttributeType.GeoProperty -> Attribute.AttributeValueType.GEOMETRY + Attribute.AttributeType.JsonProperty -> Attribute.AttributeValueType.JSON + Attribute.AttributeType.LanguageProperty -> Attribute.AttributeValueType.ARRAY + Attribute.AttributeType.VocabProperty -> Attribute.AttributeValueType.ARRAY } fun guessPropertyValueType( ngsiLdPropertyInstance: NgsiLdPropertyInstance -): Pair> = +): Pair> = guessPropertyValueType(ngsiLdPropertyInstance.value) fun guessPropertyValueType( value: Any -): Pair> = +): Pair> = when (value) { - is Double -> Pair(AttributeValueType.NUMBER, Triple(null, valueToDoubleOrNull(value), null)) - is Int -> Pair(AttributeValueType.NUMBER, Triple(null, valueToDoubleOrNull(value), null)) - is Map<*, *> -> Pair(AttributeValueType.OBJECT, Triple(serializeObject(value), null, null)) - is List<*> -> Pair(AttributeValueType.ARRAY, Triple(serializeObject(value), null, null)) - is String -> Pair(AttributeValueType.STRING, Triple(value, null, null)) - is Boolean -> Pair(AttributeValueType.BOOLEAN, Triple(value.toString(), null, null)) - is LocalDate -> Pair(AttributeValueType.DATE, Triple(value.toString(), null, null)) - is ZonedDateTime -> Pair(AttributeValueType.DATETIME, Triple(value.toString(), null, null)) - is LocalTime -> Pair(AttributeValueType.TIME, Triple(value.toString(), null, null)) - else -> Pair(AttributeValueType.STRING, Triple(value.toString(), null, null)) + is Double -> Pair(Attribute.AttributeValueType.NUMBER, Triple(null, valueToDoubleOrNull(value), null)) + is Int -> Pair(Attribute.AttributeValueType.NUMBER, Triple(null, valueToDoubleOrNull(value), null)) + is Map<*, *> -> Pair(Attribute.AttributeValueType.OBJECT, Triple(JsonUtils.serializeObject(value), null, null)) + is List<*> -> Pair(Attribute.AttributeValueType.ARRAY, Triple(JsonUtils.serializeObject(value), null, null)) + is String -> Pair(Attribute.AttributeValueType.STRING, Triple(value, null, null)) + is Boolean -> Pair(Attribute.AttributeValueType.BOOLEAN, Triple(value.toString(), null, null)) + is LocalDate -> Pair(Attribute.AttributeValueType.DATE, Triple(value.toString(), null, null)) + is ZonedDateTime -> Pair(Attribute.AttributeValueType.DATETIME, Triple(value.toString(), null, null)) + is LocalTime -> Pair(Attribute.AttributeValueType.TIME, Triple(value.toString(), null, null)) + else -> Pair(Attribute.AttributeValueType.STRING, Triple(value.toString(), null, null)) } fun Json.toExpandedAttributeInstance(): ExpandedAttributeInstance = @@ -133,7 +139,7 @@ fun partialUpdatePatch( update: ExpandedAttributeInstance ): Pair { val target = source.plus(update) - return Pair(serializeObject(target), target) + return Pair(JsonUtils.serializeObject(target), target) } fun mergePatch( @@ -145,7 +151,11 @@ fun mergePatch( if (!source.containsKey(attrName)) { target[attrName] = attrValue } else if ( - listOf(NGSILD_JSONPROPERTY_VALUE, NGSILD_VOCABPROPERTY_VALUE, NGSILD_PROPERTY_VALUE).contains(attrName) + listOf( + JsonLdUtils.NGSILD_JSONPROPERTY_VALUE, + JsonLdUtils.NGSILD_VOCABPROPERTY_VALUE, + JsonLdUtils.NGSILD_PROPERTY_VALUE + ).contains(attrName) ) { if (attrValue.size > 1) { // a Property holding an array of value or a JsonPropery holding an array of JSON objects @@ -154,18 +164,18 @@ fun mergePatch( } else { target[attrName] = listOf( JsonMerger().merge( - serializeObject(source[attrName]!![0]), - serializeObject(attrValue[0]) + JsonUtils.serializeObject(source[attrName]!![0]), + JsonUtils.serializeObject(attrValue[0]) ).deserializeAsMap() ) } - } else if (listOf(NGSILD_LANGUAGEPROPERTY_VALUE).contains(attrName)) { + } else if (listOf(JsonLdUtils.NGSILD_LANGUAGEPROPERTY_VALUE).contains(attrName)) { val sourceLangEntries = source[attrName] as List> val targetLangEntries = sourceLangEntries.toMutableList() (attrValue as List>).forEach { langEntry -> // remove any previously existing entry for this language targetLangEntries.removeIf { - it[JSONLD_LANGUAGE] == langEntry[JSONLD_LANGUAGE] + it[JsonLdUtils.JSONLD_LANGUAGE] == langEntry[JsonLdUtils.JSONLD_LANGUAGE] } targetLangEntries.add(langEntry) } @@ -176,5 +186,5 @@ fun mergePatch( } } - return Pair(serializeObject(target), target) + return Pair(JsonUtils.serializeObject(target), target) } diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstance.kt b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstance.kt index 5cb428abd..d8ab30296 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstance.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstance.kt @@ -15,7 +15,7 @@ import java.time.ZonedDateTime import java.util.UUID data class AttributeInstance private constructor( - val attribute: UUID, + val attributeUuid: UUID, val instanceId: URI, val timeProperty: TemporalProperty? = TemporalProperty.OBSERVED_AT, val time: ZonedDateTime, @@ -28,7 +28,7 @@ data class AttributeInstance private constructor( companion object { operator fun invoke( - attribute: UUID, + attributeUuid: UUID, instanceId: URI = generateRandomInstanceId(), timeProperty: TemporalProperty? = TemporalProperty.OBSERVED_AT, modifiedAt: ZonedDateTime? = null, @@ -37,7 +37,7 @@ data class AttributeInstance private constructor( time: ZonedDateTime, sub: String? = null ): AttributeInstance = AttributeInstance( - attribute = attribute, + attributeUuid = attributeUuid, instanceId = instanceId, timeProperty = timeProperty, time = time, @@ -49,14 +49,14 @@ data class AttributeInstance private constructor( ) operator fun invoke( - attribute: UUID, + attributeUuid: UUID, instanceId: URI = generateRandomInstanceId(), timeAndProperty: Pair, value: Triple, payload: ExpandedAttributeInstance, sub: String? ): AttributeInstance = AttributeInstance( - attribute = attribute, + attributeUuid = attributeUuid, instanceId = instanceId, timeProperty = timeAndProperty.second, time = timeAndProperty.first, diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstanceResult.kt b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstanceResult.kt index 01cc64188..ad417fbff 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstanceResult.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/model/AttributeInstanceResult.kt @@ -3,7 +3,7 @@ package com.egm.stellio.search.temporal.model import java.time.ZonedDateTime import java.util.UUID -sealed class AttributeInstanceResult(open val attribute: UUID) : Comparable { +sealed class AttributeInstanceResult(open val attributeUuid: UUID) : Comparable { abstract fun getComparableTime(): ZonedDateTime override fun compareTo(other: AttributeInstanceResult): Int = @@ -11,27 +11,27 @@ sealed class AttributeInstanceResult(open val attribute: UUID) : Comparable -) : AttributeInstanceResult(attribute) { +) : AttributeInstanceResult(attributeUuid) { override fun getComparableTime(): ZonedDateTime = values.first().startDateTime data class AggregateResult( 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 8666f024c..36c28be7f 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 @@ -8,12 +8,12 @@ import arrow.fx.coroutines.parMap import com.egm.stellio.search.common.util.* import com.egm.stellio.search.entity.model.Attribute import com.egm.stellio.search.entity.model.AttributeMetadata +import com.egm.stellio.search.entity.util.toAttributeMetadata import com.egm.stellio.search.temporal.model.* import com.egm.stellio.search.temporal.model.AggregatedAttributeInstanceResult.AggregateResult 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.search.temporal.util.toAttributeMetadata import com.egm.stellio.shared.model.* import com.egm.stellio.shared.util.INCONSISTENT_VALUES_IN_AGGREGATION_MESSAGE import com.egm.stellio.shared.util.attributeOrInstanceNotFoundMessage @@ -90,7 +90,7 @@ class AttributeInstanceService( it.bind("geo_value", attributeInstance.geoValue.value) else it } - .bind("attribute", attributeInstance.attribute) + .bind("attribute", attributeInstance.attributeUuid) .bind("instance_id", attributeInstance.instanceId) .bind("payload", attributeInstance.payload) .let { @@ -109,7 +109,7 @@ class AttributeInstanceService( attributeValues: Map> ): Either { val attributeInstance = AttributeInstance( - attribute = attributeUuid, + attributeUuid = attributeUuid, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, payload = attributeValues @@ -294,19 +294,19 @@ class AttributeInstanceService( AggregateResult(it, value, startDateTime, endDateTime) } AggregatedAttributeInstanceResult( - attribute = toUuid(row["temporal_entity_attribute"]), + attributeUuid = toUuid(row["temporal_entity_attribute"]), values = values ) } else if (temporalEntitiesQuery.withTemporalValues) SimplifiedAttributeInstanceResult( - attribute = toUuid(row["temporal_entity_attribute"]), + attributeUuid = toUuid(row["temporal_entity_attribute"]), // the type of the value of a property may have changed in the history (e.g., from number to string) // in this case, just display an empty value (something happened, but we can't display it) value = row["value"] ?: "", time = toZonedDateTime(row["start"]) ) else FullAttributeInstanceResult( - attribute = toUuid(row["temporal_entity_attribute"]), + attributeUuid = toUuid(row["temporal_entity_attribute"]), payload = toJsonString(row["payload"]), time = toZonedDateTime(row["start"]), timeproperty = temporalEntitiesQuery.temporalQuery.timeproperty.propertyName, @@ -328,7 +328,7 @@ class AttributeInstanceService( deleteInstance(entityId, attributeName, instanceId).bind() create( AttributeInstance( - attribute = attributeUUID, + attributeUuid = attributeUUID, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, modifiedAt = ngsiLdDateTime(), diff --git a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryService.kt b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryService.kt index 5202c3e1e..a984fb2d6 100644 --- a/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryService.kt +++ b/search-service/src/main/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryService.kt @@ -119,7 +119,7 @@ class TemporalQueryService( if (entitiesIds.isEmpty()) return@either Triple, Int, Range?>(emptyList(), count, null) - val attributes = entityAttributeService.getForTemporalEntities( + val attributes = entityAttributeService.getForEntities( entitiesIds, temporalEntitiesQuery.entitiesQuery ) @@ -201,7 +201,7 @@ class TemporalQueryService( .groupBy { attributeInstanceResult -> // group them by temporal entity attribute attributes.find { attribute -> - attribute.id == attributeInstanceResult.attribute + attribute.id == attributeInstanceResult.attributeUuid }!! } .mapValues { it.value.sorted() } 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 6a537f11c..724a72820 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 @@ -9,6 +9,8 @@ import com.egm.stellio.search.entity.util.validateMinimalQueryEntitiesParameters import com.egm.stellio.search.temporal.model.AttributeInstance import com.egm.stellio.search.temporal.model.TemporalEntitiesQuery import com.egm.stellio.search.temporal.model.TemporalQuery +import com.egm.stellio.search.temporal.model.TemporalQuery.Aggregate +import com.egm.stellio.search.temporal.model.TemporalQuery.Timerel import com.egm.stellio.shared.config.ApplicationProperties import com.egm.stellio.shared.model.APIException import com.egm.stellio.shared.model.BadRequestDataException @@ -141,15 +143,15 @@ fun buildTemporalQuery( return BadRequestDataException(it).left() } - if (timerel == TemporalQuery.Timerel.BETWEEN && endTimeAtParam == null) + if (timerel == Timerel.BETWEEN && endTimeAtParam == null) return BadRequestDataException("'endTimeAt' request parameter is mandatory if 'timerel' is 'between'").left() if (withAggregatedValues && aggrMethodsParam == null) return BadRequestDataException("'aggrMethods' is mandatory if 'aggregatedValues' option is specified").left() val aggregate = aggrMethodsParam?.split(",")?.map { - if (TemporalQuery.Aggregate.isSupportedAggregate(it)) - TemporalQuery.Aggregate.forMethod(it)!! + if (Aggregate.isSupportedAggregate(it)) + Aggregate.forMethod(it)!! else return BadRequestDataException( "'$it' is not a recognized aggregation method for 'aggrMethods' parameter" @@ -177,13 +179,13 @@ fun buildTimerelAndTime( timerelParam: String?, timeAtParam: String?, inQueryEntities: Boolean -): Either> = +): Either> = // when querying a specific temporal entity, timeAt and timerel are optional if (timerelParam == null && timeAtParam == null && !inQueryEntities) { Pair(null, null).right() } else if (timerelParam != null && timeAtParam != null) { val timeRelResult = try { - TemporalQuery.Timerel.valueOf(timerelParam.uppercase()).right() + Timerel.valueOf(timerelParam.uppercase()).right() } catch (e: IllegalArgumentException) { "'timerel' is not valid, it should be one of 'before', 'between', or 'after'".left() } diff --git a/search-service/src/main/kotlin/db/migration/V0_29__JsonLd_migration.kt b/search-service/src/main/kotlin/db/migration/V0_29__JsonLd_migration.kt index c4f859604..afb02cf85 100644 --- a/search-service/src/main/kotlin/db/migration/V0_29__JsonLd_migration.kt +++ b/search-service/src/main/kotlin/db/migration/V0_29__JsonLd_migration.kt @@ -2,9 +2,9 @@ package db.migration import arrow.core.Either import com.egm.stellio.search.entity.model.Attribute +import com.egm.stellio.search.entity.util.guessPropertyValueType +import com.egm.stellio.search.entity.util.toAttributeMetadata import com.egm.stellio.search.temporal.model.AttributeInstance -import com.egm.stellio.search.temporal.util.guessPropertyValueType -import com.egm.stellio.search.temporal.util.toAttributeMetadata import com.egm.stellio.shared.model.* import com.egm.stellio.shared.util.AuthContextModel import com.egm.stellio.shared.util.AuthContextModel.AUTH_PROP_SAP diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/authorization/web/AnonymousUserHandlerTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/authorization/web/AnonymousUserHandlerTests.kt index 0e6ab6a91..5cbf00059 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/authorization/web/AnonymousUserHandlerTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/authorization/web/AnonymousUserHandlerTests.kt @@ -2,12 +2,10 @@ package com.egm.stellio.search.authorization.web import com.egm.stellio.search.authorization.service.AuthorizationService import com.egm.stellio.search.common.config.SearchProperties -import com.egm.stellio.search.entity.service.EntityAttributeService import com.egm.stellio.search.entity.service.EntityEventService import com.egm.stellio.search.entity.service.EntityQueryService import com.egm.stellio.search.entity.service.EntityService import com.egm.stellio.search.entity.web.EntityHandler -import com.egm.stellio.search.temporal.service.TemporalQueryService import com.egm.stellio.shared.config.ApplicationProperties import com.egm.stellio.shared.util.AQUAC_HEADER_LINK import com.ninjasquad.springmockk.MockkBean @@ -32,12 +30,6 @@ class AnonymousUserHandlerTests { @MockkBean private lateinit var entityService: EntityService - @MockkBean - private lateinit var entityAttributeService: EntityAttributeService - - @MockkBean - private lateinit var queryService: TemporalQueryService - @MockkBean(relaxed = true) private lateinit var authorizationService: AuthorizationService diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/AttributeServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityAttributeServiceTests.kt similarity index 92% rename from search-service/src/test/kotlin/com/egm/stellio/search/entity/service/AttributeServiceTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityAttributeServiceTests.kt index f81a93edd..df19ae787 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/AttributeServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityAttributeServiceTests.kt @@ -40,7 +40,7 @@ import java.time.ZonedDateTime @SpringBootTest @ActiveProfiles("test") -class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { +class EntityAttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { @Autowired @SpykBean @@ -93,7 +93,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) val attributes = entityAttributeService.getForEntity( @@ -117,7 +117,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( rawEntity, APIC_COMPOUND_CONTEXTS, "0123456789-1234-5678-987654321" @@ -169,7 +169,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( rawEntity, APIC_COMPOUND_CONTEXTS ).shouldSucceed() @@ -225,7 +225,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { } throws RuntimeException("Unexpected DB error!") assertThrows("it should have thrown a RuntimeException") { - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( rawEntity, APIC_COMPOUND_CONTEXTS ).shouldSucceed() @@ -245,7 +245,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val attribute = entityAttributeService.getForEntityAndAttribute( @@ -293,7 +293,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val attribute = entityAttributeService.getForEntityAndAttribute( @@ -357,14 +357,14 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val createdAt = ngsiLdDateTime() val attributesToMerge = loadSampleData("fragments/beehive_mergeAttributes.json") val expandedAttributes = JsonLdUtils.expandAttributes(attributesToMerge, APIC_COMPOUND_CONTEXTS) val ngsiLdAttributes = expandedAttributes.toMap().toNgsiLdAttributes().shouldSucceedAndResult() - entityAttributeService.mergeEntityAttributes( + entityAttributeService.mergeAttributes( beehiveTestCId, ngsiLdAttributes, expandedAttributes, @@ -423,7 +423,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val createdAt = ngsiLdDateTime() @@ -431,7 +431,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { val propertyToMerge = loadSampleData("fragments/beehive_mergeAttribute_without_observedAt.json") val expandedAttributes = JsonLdUtils.expandAttributes(propertyToMerge, APIC_COMPOUND_CONTEXTS) val ngsiLdAttributes = expandedAttributes.toMap().toNgsiLdAttributes().shouldSucceedAndResult() - entityAttributeService.mergeEntityAttributes( + entityAttributeService.mergeAttributes( beehiveTestCId, ngsiLdAttributes, expandedAttributes, @@ -462,7 +462,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val replacedAt = ngsiLdDateTime() @@ -470,7 +470,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { val expandedAttribute = expandAttribute(propertyToReplace, APIC_COMPOUND_CONTEXTS) val ngsiLdAttribute = expandedAttribute.toNgsiLdAttribute().shouldSucceedAndResult() - entityAttributeService.replaceEntityAttribute( + entityAttributeService.replaceAttribute( beehiveTestCId, ngsiLdAttribute, expandedAttribute, @@ -496,7 +496,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val replacedAt = ngsiLdDateTime() @@ -504,7 +504,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { val expandedAttribute = expandAttribute(propertyToReplace, APIC_COMPOUND_CONTEXTS) val ngsiLdAttribute = expandedAttribute.toNgsiLdAttribute().shouldSucceedAndResult() - entityAttributeService.replaceEntityAttribute( + entityAttributeService.replaceAttribute( beehiveTestCId, ngsiLdAttribute, expandedAttribute, @@ -524,7 +524,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) entityAttributeService.getForEntityAndAttribute( beehiveTestCId, @@ -538,7 +538,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) entityAttributeService.getForEntityAndAttribute( beehiveTestCId, @@ -553,7 +553,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) entityAttributeService.getForEntityAndAttribute( beehiveTestCId, @@ -571,9 +571,9 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() coEvery { attributeInstanceService.deleteInstancesOfAttribute(any(), any(), any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) - entityAttributeService.deleteTemporalAttribute( + entityAttributeService.deleteAttribute( beehiveTestDId, INCOMING_PROPERTY, null @@ -594,9 +594,9 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() coEvery { attributeInstanceService.deleteAllInstancesOfAttribute(any(), any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) - entityAttributeService.deleteTemporalAttribute( + entityAttributeService.deleteAttribute( beehiveTestCId, INCOMING_PROPERTY, null, @@ -617,7 +617,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) entityAttributeService.checkEntityAndAttributeExistence(beehiveTestCId, INCOMING_PROPERTY) .shouldSucceed() @@ -629,7 +629,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) val result = entityAttributeService.checkEntityAndAttributeExistence(beehiveTestCId, "speed") @@ -656,7 +656,7 @@ class AttributeServiceTests : WithTimescaleContainer, WithKafkaContainer { coEvery { attributeInstanceService.create(any()) } returns Unit.right() - entityAttributeService.createEntityAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) + entityAttributeService.createAttributes(rawEntity, APIC_COMPOUND_CONTEXTS) .shouldSucceed() val attributes = diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityOperationServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityOperationServiceTests.kt index 55ae266eb..a26191bd2 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityOperationServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityOperationServiceTests.kt @@ -308,7 +308,7 @@ class EntityOperationServiceTests { @Test fun `batch replace should ask to replace entities`() = runTest { coEvery { - entityAttributeService.deleteTemporalAttributesOfEntity(any()) + entityAttributeService.deleteAttributes(any()) } returns Unit.right() coEvery { entityService.appendAttributes(any(), any(), any(), any()) @@ -329,8 +329,8 @@ class EntityOperationServiceTests { ) assertTrue(batchOperationResult.errors.isEmpty()) - coVerify { entityAttributeService.deleteTemporalAttributesOfEntity(firstEntityURI) } - coVerify { entityAttributeService.deleteTemporalAttributesOfEntity(secondEntityURI) } + coVerify { entityAttributeService.deleteAttributes(firstEntityURI) } + coVerify { entityAttributeService.deleteAttributes(secondEntityURI) } coVerify { entityService.appendAttributes(eq(firstEntityURI), any(), false, sub) } diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueryTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueriesTests.kt similarity index 99% rename from search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueryTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueriesTests.kt index ee7049908..3c191294e 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueryTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceQueriesTests.kt @@ -25,7 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.test.context.SpringBootTest import org.springframework.data.r2dbc.core.R2dbcEntityTemplate -import org.springframework.data.r2dbc.core.update import org.springframework.data.relational.core.query.Criteria import org.springframework.data.relational.core.query.Query import org.springframework.data.relational.core.query.Update @@ -35,7 +34,7 @@ import java.net.URI @SpringBootTest @ActiveProfiles("test") @EnableConfigurationProperties(SearchProperties::class) -class EntityServiceQueryTests : WithTimescaleContainer, WithKafkaContainer { +class EntityServiceQueriesTests : WithTimescaleContainer, WithKafkaContainer { @Autowired private lateinit var entityService: EntityService diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceTests.kt index a381cea35..67feaf6ae 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/service/EntityServiceTests.kt @@ -142,7 +142,7 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { @Test fun `it should only create an entity payload for a minimal entity`() = runTest { coEvery { - entityAttributeService.createEntityAttributes(any(), any(), any(), any(), any()) + entityAttributeService.createAttributes(any(), any(), any(), any(), any()) } returns Unit.right() val (expandedEntity, ngsiLdEntity) = @@ -161,7 +161,7 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { } coVerify { - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( any(), any(), emptyList(), @@ -193,10 +193,10 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { @Test fun `it should merge an entity`() = runTest { coEvery { - entityAttributeService.createEntityAttributes(any(), any(), any(), any(), any()) + entityAttributeService.createAttributes(any(), any(), any(), any(), any()) } returns Unit.right() coEvery { - entityAttributeService.mergeEntityAttributes(any(), any(), any(), any(), any(), any()) + entityAttributeService.mergeAttributes(any(), any(), any(), any(), any(), any()) } returns UpdateResult( listOf(UpdatedDetails(INCOMING_PROPERTY, null, UpdateOperationResult.APPENDED)), emptyList() @@ -229,14 +229,14 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { } coVerify { - entityAttributeService.createEntityAttributes( + entityAttributeService.createAttributes( any(), any(), emptyList(), any(), eq("0123456789-1234-5678-987654321") ) - entityAttributeService.mergeEntityAttributes( + entityAttributeService.mergeAttributes( eq(beehiveTestCId), any(), any(), @@ -255,10 +255,10 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { @Test fun `it should merge an entity with new types`() = runTest { coEvery { - entityAttributeService.createEntityAttributes(any(), any(), any(), any(), any()) + entityAttributeService.createAttributes(any(), any(), any(), any(), any()) } returns Unit.right() coEvery { - entityAttributeService.mergeEntityAttributes(any(), any(), any(), any(), any(), any()) + entityAttributeService.mergeAttributes(any(), any(), any(), any(), any(), any()) } returns UpdateResult( listOf(UpdatedDetails(INCOMING_PROPERTY, null, UpdateOperationResult.APPENDED)), emptyList() @@ -297,16 +297,16 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { @Test fun `it should merge an entity with new types and scopes`() = runTest { coEvery { - entityAttributeService.createEntityAttributes(any(), any(), any(), any(), any()) + entityAttributeService.createAttributes(any(), any(), any(), any(), any()) } returns Unit.right() coEvery { - entityAttributeService.mergeEntityAttributes(any(), any(), any(), any(), any(), any()) + entityAttributeService.mergeAttributes(any(), any(), any(), any(), any(), any()) } returns UpdateResult( listOf(UpdatedDetails(INCOMING_PROPERTY, null, UpdateOperationResult.APPENDED)), emptyList() ).right() coEvery { - entityAttributeService.partialUpdateEntityAttribute(any(), any(), any(), any()) + entityAttributeService.partialUpdateAttribute(any(), any(), any(), any()) } returns EMPTY_UPDATE_RESULT.right() coEvery { entityAttributeService.getForEntity(any(), any(), any()) @@ -352,9 +352,9 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { fun `it should replace an entity`() = runTest { val beehiveURI = "urn:ngsi-ld:BeeHive:TESTC".toUri() coEvery { - entityAttributeService.createEntityAttributes(any(), any(), any(), any(), any()) + entityAttributeService.createAttributes(any(), any(), any(), any(), any()) } returns Unit.right() - coEvery { entityAttributeService.deleteTemporalAttributesOfEntity(any()) } returns Unit.right() + coEvery { entityAttributeService.deleteAttributes(any()) } returns Unit.right() val (expandedEntity, ngsiLdEntity) = loadAndPrepareSampleData("beehive_minimal.jsonld").shouldSucceedAndResult() @@ -381,8 +381,8 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { } coVerify { - entityAttributeService.deleteTemporalAttributesOfEntity(beehiveURI) - entityAttributeService.createEntityAttributes( + entityAttributeService.deleteAttributes(beehiveURI) + entityAttributeService.createAttributes( any(), any(), emptyList(), @@ -396,7 +396,7 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { fun `it should replace an attribute`() = runTest { coEvery { entityAttributeService.getForEntity(any(), any(), any()) } returns emptyList() coEvery { - entityAttributeService.replaceEntityAttribute(any(), any(), any(), any(), any()) + entityAttributeService.replaceAttribute(any(), any(), any(), any(), any()) } returns UpdateResult( updated = listOf(UpdatedDetails(INCOMING_PROPERTY, null, UpdateOperationResult.REPLACED)), notUpdated = emptyList() @@ -657,7 +657,7 @@ class EntityServiceTests : WithTimescaleContainer, WithKafkaContainer { @Test fun `it should delete an entity payload`() = runTest { - coEvery { entityAttributeService.deleteTemporalAttributesOfEntity(any()) } returns Unit.right() + coEvery { entityAttributeService.deleteAttributes(any()) } returns Unit.right() loadMinimalEntity(entity01Uri, setOf(BEEHIVE_TYPE)) .sampleDataToNgsiLdEntity() diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/AttributeInstanceUtilsTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/AttributeUtilsTests.kt similarity index 97% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/AttributeInstanceUtilsTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/entity/util/AttributeUtilsTests.kt index 6e23af8b3..b9d039538 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/AttributeInstanceUtilsTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/AttributeUtilsTests.kt @@ -1,7 +1,6 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.entity.util import com.egm.stellio.search.entity.model.Attribute -import com.egm.stellio.search.temporal.util.guessAttributeValueType import com.egm.stellio.shared.util.JsonLdUtils.expandAttribute import com.egm.stellio.shared.util.NGSILD_TEST_CORE_CONTEXTS import com.egm.stellio.shared.util.ngsiLdDateTime @@ -13,7 +12,7 @@ import java.net.URI import java.time.LocalTime @ActiveProfiles("test") -class AttributeInstanceUtilsTests { +class AttributeUtilsTests { @Test fun `it should guess the value type of a string property`() = runTest { 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 new file mode 100644 index 000000000..3e05edf96 --- /dev/null +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/EntitiesQueryUtilsTests.kt @@ -0,0 +1,257 @@ +package com.egm.stellio.search.entity.util + +import arrow.core.Either +import arrow.core.raise.either +import com.egm.stellio.search.common.model.Query +import com.egm.stellio.search.common.model.Query.Companion.invoke +import com.egm.stellio.search.entity.model.EntitiesQuery +import com.egm.stellio.search.support.buildDefaultPagination +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.GeoQuery +import com.egm.stellio.shared.util.APIARY_TYPE +import com.egm.stellio.shared.util.APIC_COMPOUND_CONTEXTS +import com.egm.stellio.shared.util.BEEHIVE_TYPE +import com.egm.stellio.shared.util.GEO_QUERY_GEOREL_EQUALS +import com.egm.stellio.shared.util.INCOMING_PROPERTY +import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_DEFAULT_VOCAB +import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_OBSERVATION_SPACE_PROPERTY +import com.egm.stellio.shared.util.NGSILD_TEST_CORE_CONTEXTS +import com.egm.stellio.shared.util.OUTGOING_PROPERTY +import com.egm.stellio.shared.util.shouldFailWith +import com.egm.stellio.shared.util.shouldSucceedAndResult +import com.egm.stellio.shared.util.shouldSucceedWith +import com.egm.stellio.shared.util.toUri +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.springframework.test.context.ActiveProfiles +import org.springframework.util.LinkedMultiValueMap +import org.springframework.util.MultiValueMap +import java.net.URI + +@ActiveProfiles("test") +class EntitiesQueryUtilsTests { + + @Test + fun `it should parse query parameters`() = runTest { + val requestParams = gimmeEntitiesQueryParams() + val entitiesQuery = composeEntitiesQuery( + buildDefaultPagination(1, 20), + requestParams, + APIC_COMPOUND_CONTEXTS + ).shouldSucceedAndResult() + + assertEquals("$BEEHIVE_TYPE,$APIARY_TYPE", entitiesQuery.typeSelection) + assertEquals(setOf(INCOMING_PROPERTY, OUTGOING_PROPERTY), entitiesQuery.attrs) + assertEquals( + setOf("urn:ngsi-ld:BeeHive:TESTC".toUri(), "urn:ngsi-ld:BeeHive:TESTB".toUri()), + entitiesQuery.ids + ) + assertEquals(".*BeeHive.*", entitiesQuery.idPattern) + assertEquals("brandName!=Mercedes", entitiesQuery.q) + assertEquals(setOf("urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"), entitiesQuery.datasetId) + assertEquals(true, entitiesQuery.paginationQuery.count) + assertEquals(1, entitiesQuery.paginationQuery.offset) + assertEquals(10, entitiesQuery.paginationQuery.limit) + } + + @Test + fun `it should decode q in query parameters`() = runTest { + val requestParams = LinkedMultiValueMap() + requestParams.add("q", "speed%3E50%3BfoodName%3D%3Ddietary+fibres") + val entitiesQuery = composeEntitiesQuery( + buildDefaultPagination(30, 100), + requestParams, + NGSILD_TEST_CORE_CONTEXTS + ).shouldSucceedAndResult() + + assertEquals("speed>50;foodName==dietary fibres", entitiesQuery.q) + } + + @Test + fun `it should set default values in query parameters`() = runTest { + val requestParams = LinkedMultiValueMap() + val entitiesQuery = composeEntitiesQuery( + buildDefaultPagination(30, 100), + requestParams, + NGSILD_TEST_CORE_CONTEXTS + ).shouldSucceedAndResult() + + assertEquals(null, entitiesQuery.typeSelection) + assertEquals(emptySet(), entitiesQuery.attrs) + assertEquals(emptySet(), entitiesQuery.ids) + assertEquals(null, entitiesQuery.idPattern) + assertEquals(null, entitiesQuery.q) + assertEquals(emptySet(), entitiesQuery.datasetId) + assertEquals(false, entitiesQuery.paginationQuery.count) + assertEquals(0, entitiesQuery.paginationQuery.offset) + assertEquals(30, entitiesQuery.paginationQuery.limit) + } + + private fun gimmeEntitiesQueryParams(): LinkedMultiValueMap { + val requestParams = LinkedMultiValueMap() + requestParams.add("type", "BeeHive,Apiary") + requestParams.add("attrs", "incoming,outgoing") + requestParams.add("id", "urn:ngsi-ld:BeeHive:TESTC,urn:ngsi-ld:BeeHive:TESTB") + requestParams.add("idPattern", ".*BeeHive.*") + requestParams.add("q", "brandName!=Mercedes") + requestParams.add("datasetId", "urn:ngsi-ld:Dataset:Test1,urn:ngsi-ld:Dataset:Test2") + requestParams.add("count", "true") + requestParams.add("offset", "1") + requestParams.add("limit", "10") + requestParams.add("options", "keyValues") + return requestParams + } + + @Test + fun `it should parse a valid complete query`() = runTest { + val query = """ + { + "type": "Query", + "entities": [{ + "id": "urn:ngsi-ld:BeeHive:TESTC", + "idPattern": "urn:ngsi-ld:BeeHive:*", + "type": "BeeHive" + }], + "attrs": ["attr1", "attr2"], + "q": "temperature>32", + "geoQ": { + "geometry": "Point", + "coordinates": [1.0, 1.0], + "georel": "equals", + "geoproperty": "observationSpace" + }, + "temporalQ": { + "timerel": "between", + "timeAt": "2023-10-01T12:34:56Z", + "endTimeAt": "2023-10-02T12:34:56Z", + "lastN": 10, + "timeproperty": "observedAt" + }, + "scopeQ": "/Nantes", + "datasetId": ["urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"] + } + """.trimIndent() + + composeEntitiesQueryFromPostRequest( + buildDefaultPagination(30, 100), + query, + LinkedMultiValueMap(), + APIC_COMPOUND_CONTEXTS + ).shouldSucceedWith { + assertEquals(setOf("urn:ngsi-ld:BeeHive:TESTC".toUri()), it.ids) + assertEquals("urn:ngsi-ld:BeeHive:*", it.idPattern) + assertEquals(BEEHIVE_TYPE, it.typeSelection) + assertEquals(setOf("${NGSILD_DEFAULT_VOCAB}attr1", "${NGSILD_DEFAULT_VOCAB}attr2"), it.attrs) + assertEquals("temperature>32", it.q) + assertEquals(GeoQuery.GeometryType.POINT, it.geoQuery?.geometry) + assertEquals("[1.0, 1.0]", it.geoQuery?.coordinates) + assertEquals(GEO_QUERY_GEOREL_EQUALS, it.geoQuery?.georel) + assertEquals(NGSILD_OBSERVATION_SPACE_PROPERTY, it.geoQuery?.geoproperty) + assertEquals("/Nantes", it.scopeQ) + assertEquals(setOf("urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"), it.datasetId) + } + } + + @Test + fun `it should parse a valid simple query`() = runTest { + val query = """ + { + "type": "Query", + "entities": [{ + "type": "BeeHive" + }], + "attrs": ["attr1"], + "q": "temperature>32" + } + """.trimIndent() + + composeEntitiesQueryFromPostRequest( + buildDefaultPagination(30, 100), + query, + LinkedMultiValueMap(), + APIC_COMPOUND_CONTEXTS + ).shouldSucceedWith { + assertEquals(BEEHIVE_TYPE, it.typeSelection) + assertEquals(setOf("${NGSILD_DEFAULT_VOCAB}attr1"), it.attrs) + assertEquals("temperature>32", it.q) + } + } + + @Test + fun `it should not validate a query if the type is not correct`() { + val query = """ + { + "type": "NotAQuery", + "attrs": ["attr1", "attr2"] + } + """.trimIndent() + + composeEntitiesQueryFromPostRequest( + buildDefaultPagination(30, 100), + query, + LinkedMultiValueMap(), + APIC_COMPOUND_CONTEXTS + ).shouldFailWith { + it is BadRequestDataException && + it.message == "The type parameter should be equals to 'Query'" + } + } + + @Test + fun `it should not validate a query if the payload could not be parsed because the JSON is invalid`() { + val query = """ + { + "type": "Query",, + "attrs": ["attr1", "attr2"] + } + """.trimIndent() + + composeEntitiesQueryFromPostRequest( + buildDefaultPagination(30, 100), + query, + LinkedMultiValueMap(), + APIC_COMPOUND_CONTEXTS + ).shouldFailWith { + it is BadRequestDataException && + it.message.startsWith("The supplied query could not be parsed") + } + } + + @Test + fun `it should not validate a query if the payload contains unexpected parameters`() { + val query = """ + { + "type": "Query", + "property": "anUnexpectedProperty" + } + """.trimIndent() + + composeEntitiesQueryFromPostRequest( + buildDefaultPagination(30, 100), + query, + LinkedMultiValueMap(), + APIC_COMPOUND_CONTEXTS + ).shouldFailWith { + it is BadRequestDataException && + it.message.startsWith("The supplied query could not be parsed") + } + } + + private fun composeEntitiesQueryFromPostRequest( + defaultPagination: ApplicationProperties.Pagination, + requestBody: String, + requestParams: MultiValueMap, + contexts: List + ): Either = either { + val query = Query(requestBody).bind() + composeEntitiesQueryFromPostRequest( + defaultPagination, + query, + requestParams, + contexts + ).bind() + } +} diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/PatchAttributeTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/PatchAttributeTests.kt similarity index 97% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/PatchAttributeTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/entity/util/PatchAttributeTests.kt index 56b3fc425..df243327c 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/PatchAttributeTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/entity/util/PatchAttributeTests.kt @@ -1,7 +1,5 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.entity.util -import com.egm.stellio.search.temporal.util.mergePatch -import com.egm.stellio.search.temporal.util.partialUpdatePatch import com.egm.stellio.shared.util.JsonLdUtils.expandAttribute import com.egm.stellio.shared.util.JsonUtils.serializeObject import com.egm.stellio.shared.util.NGSILD_TEST_CORE_CONTEXTS @@ -321,7 +319,7 @@ class PatchAttributeTests { } @ParameterizedTest - @MethodSource("com.egm.stellio.search.util.PatchAttributeTests#partialUpdatePatchProvider") + @MethodSource("com.egm.stellio.search.entity.util.PatchAttributeTests#partialUpdatePatchProvider") fun `it should apply a partial update patch behavior to attribute instance`( source: String, target: String, @@ -339,7 +337,7 @@ class PatchAttributeTests { } @ParameterizedTest - @MethodSource("com.egm.stellio.search.util.PatchAttributeTests#mergePatchProvider") + @MethodSource("com.egm.stellio.search.entity.util.PatchAttributeTests#mergePatchProvider") fun `it should apply a merge patch behavior to attribute instance`( source: String, target: String, diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/scope/ScopeServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/scope/ScopeServiceTests.kt index d028999ab..f73ff9afd 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/scope/ScopeServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/scope/ScopeServiceTests.kt @@ -4,13 +4,13 @@ import com.egm.stellio.search.entity.model.EntitiesQuery import com.egm.stellio.search.entity.model.Entity import com.egm.stellio.search.entity.model.OperationType import com.egm.stellio.search.entity.service.EntityService +import com.egm.stellio.search.entity.util.toExpandedAttributeInstance import com.egm.stellio.search.support.WithKafkaContainer import com.egm.stellio.search.support.WithTimescaleContainer import com.egm.stellio.search.support.buildDefaultTestTemporalQuery 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.toExpandedAttributeInstance import com.egm.stellio.shared.model.PaginationQuery import com.egm.stellio.shared.model.getScopes import com.egm.stellio.shared.util.* diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/support/BusinessObjectsFactory.kt b/search-service/src/test/kotlin/com/egm/stellio/search/support/BusinessObjectsFactory.kt index 5c534fc9f..cee889584 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/support/BusinessObjectsFactory.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/support/BusinessObjectsFactory.kt @@ -54,7 +54,7 @@ fun gimmeNumericPropertyAttributeInstance( .getSingleEntry() return AttributeInstance( - attribute = attributeUuid, + attributeUuid = attributeUuid, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, timeProperty = timeProperty, @@ -80,7 +80,7 @@ fun gimmeJsonPropertyAttributeInstance( .getSingleEntry() return AttributeInstance( - attribute = attributeUuid, + attributeUuid = attributeUuid, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, timeProperty = timeProperty, @@ -106,7 +106,7 @@ fun gimmeLanguagePropertyAttributeInstance( .getSingleEntry() return AttributeInstance( - attribute = attributeUuid, + attributeUuid = attributeUuid, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, timeProperty = timeProperty, @@ -132,7 +132,7 @@ fun gimmeVocabPropertyAttributeInstance( .getSingleEntry() return AttributeInstance( - attribute = attributeUuid, + attributeUuid = attributeUuid, time = attributeMetadata.observedAt!!, attributeMetadata = attributeMetadata, timeProperty = timeProperty, diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceServiceTests.kt index 53f2ee170..e54ad4a4d 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/AttributeInstanceServiceTests.kt @@ -164,7 +164,7 @@ class AttributeInstanceServiceTests : WithTimescaleContainer, WithKafkaContainer .shouldSucceedWith { assertThat(it) .singleElement() - .hasFieldOrPropertyWithValue("attribute", incomingAttribute.id) + .hasFieldOrPropertyWithValue("attributeUuid", incomingAttribute.id) } } @@ -298,7 +298,7 @@ class AttributeInstanceServiceTests : WithTimescaleContainer, WithKafkaContainer observedAt = observedAt ) val attributeInstance = AttributeInstance( - attribute = attribute2.id, + attributeUuid = attribute2.id, time = observedAt, attributeMetadata = attributeMetadata, payload = buildExpandedPropertyValue(attributeMetadata.value!!) @@ -315,7 +315,7 @@ class AttributeInstanceServiceTests : WithTimescaleContainer, WithKafkaContainer assertThat(results) .hasSize(10) .allMatch { - it.attribute == attribute2.id && + it.attributeUuid == attribute2.id && (it as SimplifiedAttributeInstanceResult).value == "some value" } } @@ -431,7 +431,7 @@ class AttributeInstanceServiceTests : WithTimescaleContainer, WithKafkaContainer assertThat(results) .hasSize(10) .allMatch { - it.attribute == incomingAttribute.id + it.attributeUuid == incomingAttribute.id } } } diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalPaginationServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalPaginationServiceTests.kt index 202e137ac..b53affd98 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalPaginationServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalPaginationServiceTests.kt @@ -52,7 +52,7 @@ class TemporalPaginationServiceTests { ) private fun getInstance(time: ZonedDateTime): AttributeInstanceResult { - return SimplifiedAttributeInstanceResult(value = 1, time = time, attribute = UUID.randomUUID()) + return SimplifiedAttributeInstanceResult(value = 1, time = time, attributeUuid = UUID.randomUUID()) } private val attributesWithInstances: AttributesWithInstances = mapOf( @@ -91,7 +91,7 @@ class TemporalPaginationServiceTests { private val aggregationInstances = listOf( AggregatedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), values = listOf( AggregatedAttributeInstanceResult.AggregateResult( TemporalQuery.Aggregate.SUM, @@ -108,7 +108,7 @@ class TemporalPaginationServiceTests { ) ), AggregatedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), values = listOf( AggregatedAttributeInstanceResult.AggregateResult( TemporalQuery.Aggregate.SUM, diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryServiceTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryServiceTests.kt index 4b972edb4..292117a55 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryServiceTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/service/TemporalQueryServiceTests.kt @@ -224,7 +224,7 @@ class TemporalQueryServiceTests { coEvery { entityService.queryEntities(any(), any()) } returns listOf(entityUri) coEvery { - entityAttributeService.getForTemporalEntities(any(), any()) + entityAttributeService.getForEntities(any(), any()) } returns listOf(attribute) coEvery { entityService.queryEntitiesCount(any(), any()) } returns 1.right() coEvery { scopeService.retrieveHistory(any(), any()) } returns emptyList().right() @@ -234,7 +234,7 @@ class TemporalQueryServiceTests { } returns listOf( SimplifiedAttributeInstanceResult( - attribute = attribute.id, + attributeUuid = attribute.id, value = 2.0, time = ngsiLdDateTime() ) @@ -258,7 +258,7 @@ class TemporalQueryServiceTests { ) { null } coVerify { - entityAttributeService.getForTemporalEntities( + entityAttributeService.getForEntities( listOf(entityUri), EntitiesQuery( typeSelection = "$BEEHIVE_TYPE,$APIARY_TYPE", @@ -299,7 +299,7 @@ class TemporalQueryServiceTests { coEvery { entityService.queryEntities(any(), any()) } returns listOf(entityUri) coEvery { - entityAttributeService.getForTemporalEntities(any(), any()) + entityAttributeService.getForEntities(any(), any()) } returns listOf(attribute) coEvery { scopeService.retrieveHistory(any(), any()) } returns emptyList().right() coEvery { diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntitiesParameterizedSource.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntitiesParameterizedSource.kt similarity index 95% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntitiesParameterizedSource.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntitiesParameterizedSource.kt index 4ac7b59c3..2c74de4b7 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntitiesParameterizedSource.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntitiesParameterizedSource.kt @@ -1,4 +1,4 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.temporal.util import com.egm.stellio.search.entity.model.Attribute import com.egm.stellio.search.entity.model.Entity @@ -43,7 +43,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 20, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -67,7 +67,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 25, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -95,7 +95,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 20, ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -126,7 +126,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 25, ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -161,7 +161,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 20, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -175,7 +175,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "urn:ngsi-ld:Beekeeper:1234", time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -199,7 +199,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 25, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -213,7 +213,7 @@ class TemporalEntitiesParameterizedSource { payload = EMPTY_JSON_PAYLOAD ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "urn:ngsi-ld:Beekeeper:5678", time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityBuilderTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityBuilderTests.kt similarity index 94% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityBuilderTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityBuilderTests.kt index c21c748c8..921738a43 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityBuilderTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityBuilderTests.kt @@ -1,4 +1,4 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.temporal.util import com.egm.stellio.search.entity.model.Attribute import com.egm.stellio.search.entity.model.Entity @@ -8,8 +8,6 @@ import com.egm.stellio.search.support.buildDefaultQueryParams import com.egm.stellio.search.support.buildDefaultTestTemporalQuery import com.egm.stellio.search.temporal.model.* import com.egm.stellio.search.temporal.model.AggregatedAttributeInstanceResult.AggregateResult -import com.egm.stellio.search.temporal.util.AttributesWithInstances -import com.egm.stellio.search.temporal.util.TemporalEntityBuilder import com.egm.stellio.shared.util.* import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_CREATED_AT_PROPERTY import com.egm.stellio.shared.util.JsonUtils.serializeObject @@ -62,7 +60,7 @@ class TemporalEntityBuilderTests { } @ParameterizedTest - @MethodSource("com.egm.stellio.search.util.TemporalEntityParameterizedSource#rawResultsProvider") + @MethodSource("com.egm.stellio.search.temporal.util.TemporalEntityParameterizedSource#rawResultsProvider") fun `it should correctly build a temporal entity`( scopeHistory: List, attributeAndResultsMap: AttributesWithInstances, @@ -95,7 +93,7 @@ class TemporalEntityBuilderTests { } @ParameterizedTest - @MethodSource("com.egm.stellio.search.util.TemporalEntitiesParameterizedSource#rawResultsProvider") + @MethodSource("com.egm.stellio.search.temporal.util.TemporalEntitiesParameterizedSource#rawResultsProvider") fun `it should correctly build temporal entities`( entityTemporalResults: List, withTemporalValues: Boolean, @@ -132,7 +130,7 @@ class TemporalEntityBuilderTests { val attributeAndResultsMap = mapOf( attribute to listOf( AggregatedAttributeInstanceResult( - attribute = attribute.id, + attributeUuid = attribute.id, listOf( AggregateResult( TemporalQuery.Aggregate.SUM, @@ -149,7 +147,7 @@ class TemporalEntityBuilderTests { ) ), AggregatedAttributeInstanceResult( - attribute = attribute.id, + attributeUuid = attribute.id, listOf( AggregateResult( TemporalQuery.Aggregate.SUM, diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityParameterizedSource.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityParameterizedSource.kt similarity index 93% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityParameterizedSource.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityParameterizedSource.kt index 9aa1497a5..b5d31e06a 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/TemporalEntityParameterizedSource.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalEntityParameterizedSource.kt @@ -1,4 +1,4 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.temporal.util import com.egm.stellio.search.entity.model.Attribute import com.egm.stellio.search.scope.FullScopeInstanceResult @@ -37,7 +37,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 550.0, ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -49,7 +49,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 650.0, ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -81,7 +81,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "urn:ngsi-ld:Entity:1234", ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -94,7 +94,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "urn:ngsi-ld:Entity:5678", ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -127,7 +127,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 550.0, ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -139,7 +139,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 650.0, ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -161,7 +161,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 487.0, ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -173,7 +173,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( 698.0, ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -205,7 +205,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_123", ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -217,7 +217,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_124", ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -249,7 +249,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_123", ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -261,7 +261,7 @@ class TemporalEntityParameterizedSource { sub = "sub1" ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_124", ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -292,7 +292,7 @@ class TemporalEntityParameterizedSource { ) to listOf( FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_123", ZonedDateTime.parse("2020-03-25T08:29:17.965206Z"), @@ -304,7 +304,7 @@ class TemporalEntityParameterizedSource { sub = null ), FullAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), payload = buildAttributeInstancePayload( "Beehive_incoming_124", ZonedDateTime.parse("2020-03-25T08:33:17.965206Z"), @@ -337,12 +337,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 550.0, time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 650.0, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -369,12 +369,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 550.0, time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 650.0, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -389,12 +389,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 487.0, time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = 698.0, time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -419,12 +419,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "Beehive_incoming_123", time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "Beehive_incoming_124", time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -448,12 +448,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "Beehive_incoming_123", time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "Beehive_incoming_124", time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -481,12 +481,12 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "urn:ngsi-ld:Entity:1234", time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = "urn:ngsi-ld:Entity:5678", time = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z") ) @@ -554,14 +554,14 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ { "id": "123", "stringValue": "value", "nullValue": null } """, time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ { "id": "456", "stringValue": "anotherValue" } """, @@ -589,7 +589,7 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ [{ "@value": "One beautiful beehive", @@ -603,7 +603,7 @@ class TemporalEntityParameterizedSource { time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ [{ "@value": "My beautiful beehive", @@ -638,7 +638,7 @@ class TemporalEntityParameterizedSource { ) to listOf( SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ [{ "@id": "https://uri.etsi.org/ngsi-ld/default-context/stellio" @@ -650,7 +650,7 @@ class TemporalEntityParameterizedSource { time = ZonedDateTime.parse("2020-03-25T08:29:17.965206Z") ), SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = """ [{ "@id": "https://uri.etsi.org/ngsi-ld/default-context/stellio" diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/util/EntitiesQueryUtilsTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtilsTests.kt similarity index 58% rename from search-service/src/test/kotlin/com/egm/stellio/search/util/EntitiesQueryUtilsTests.kt rename to search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtilsTests.kt index 15e4a27c4..76e68a8cf 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/util/EntitiesQueryUtilsTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/util/TemporalQueryUtilsTests.kt @@ -1,257 +1,35 @@ -package com.egm.stellio.search.util +package com.egm.stellio.search.temporal.util -import arrow.core.Either -import arrow.core.raise.either -import com.egm.stellio.search.common.model.Query -import com.egm.stellio.search.entity.model.EntitiesQuery -import com.egm.stellio.search.entity.util.composeEntitiesQuery import com.egm.stellio.search.support.buildDefaultPagination import com.egm.stellio.search.support.buildDefaultTestTemporalQuery import com.egm.stellio.search.temporal.model.AttributeInstance import com.egm.stellio.search.temporal.model.TemporalQuery -import com.egm.stellio.search.temporal.util.buildTemporalQuery -import com.egm.stellio.search.temporal.util.composeTemporalEntitiesQuery 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.GeoQuery -import com.egm.stellio.shared.util.* -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_DEFAULT_VOCAB -import com.egm.stellio.shared.util.JsonLdUtils.NGSILD_OBSERVATION_SPACE_PROPERTY +import com.egm.stellio.shared.util.APIARY_TYPE +import com.egm.stellio.shared.util.APIC_COMPOUND_CONTEXTS +import com.egm.stellio.shared.util.BEEHIVE_TYPE +import com.egm.stellio.shared.util.INCOMING_PROPERTY +import com.egm.stellio.shared.util.OUTGOING_PROPERTY +import com.egm.stellio.shared.util.shouldFail +import com.egm.stellio.shared.util.shouldSucceedAndResult +import com.egm.stellio.shared.util.toUri import io.mockk.every import io.mockk.mockkClass import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertInstanceOf +import org.junit.jupiter.api.Assertions.assertIterableEquals +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.springframework.test.context.ActiveProfiles import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap -import java.net.URI import java.time.ZonedDateTime @ActiveProfiles("test") -class EntitiesQueryUtilsTests { - - @Test - fun `it should parse query parameters`() = runTest { - val requestParams = gimmeEntitiesQueryParams() - val entitiesQuery = composeEntitiesQuery( - buildDefaultPagination(1, 20), - requestParams, - APIC_COMPOUND_CONTEXTS - ).shouldSucceedAndResult() - - assertEquals("$BEEHIVE_TYPE,$APIARY_TYPE", entitiesQuery.typeSelection) - assertEquals(setOf(INCOMING_PROPERTY, OUTGOING_PROPERTY), entitiesQuery.attrs) - assertEquals( - setOf("urn:ngsi-ld:BeeHive:TESTC".toUri(), "urn:ngsi-ld:BeeHive:TESTB".toUri()), - entitiesQuery.ids - ) - assertEquals(".*BeeHive.*", entitiesQuery.idPattern) - assertEquals("brandName!=Mercedes", entitiesQuery.q) - assertEquals(setOf("urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"), entitiesQuery.datasetId) - assertEquals(true, entitiesQuery.paginationQuery.count) - assertEquals(1, entitiesQuery.paginationQuery.offset) - assertEquals(10, entitiesQuery.paginationQuery.limit) - } - - @Test - fun `it should decode q in query parameters`() = runTest { - val requestParams = LinkedMultiValueMap() - requestParams.add("q", "speed%3E50%3BfoodName%3D%3Ddietary+fibres") - val entitiesQuery = composeEntitiesQuery( - buildDefaultPagination(30, 100), - requestParams, - NGSILD_TEST_CORE_CONTEXTS - ).shouldSucceedAndResult() - - assertEquals("speed>50;foodName==dietary fibres", entitiesQuery.q) - } - - @Test - fun `it should set default values in query parameters`() = runTest { - val requestParams = LinkedMultiValueMap() - val entitiesQuery = composeEntitiesQuery( - buildDefaultPagination(30, 100), - requestParams, - NGSILD_TEST_CORE_CONTEXTS - ).shouldSucceedAndResult() - - assertEquals(null, entitiesQuery.typeSelection) - assertEquals(emptySet(), entitiesQuery.attrs) - assertEquals(emptySet(), entitiesQuery.ids) - assertEquals(null, entitiesQuery.idPattern) - assertEquals(null, entitiesQuery.q) - assertEquals(emptySet(), entitiesQuery.datasetId) - assertEquals(false, entitiesQuery.paginationQuery.count) - assertEquals(0, entitiesQuery.paginationQuery.offset) - assertEquals(30, entitiesQuery.paginationQuery.limit) - } - - private fun gimmeEntitiesQueryParams(): LinkedMultiValueMap { - val requestParams = LinkedMultiValueMap() - requestParams.add("type", "BeeHive,Apiary") - requestParams.add("attrs", "incoming,outgoing") - requestParams.add("id", "urn:ngsi-ld:BeeHive:TESTC,urn:ngsi-ld:BeeHive:TESTB") - requestParams.add("idPattern", ".*BeeHive.*") - requestParams.add("q", "brandName!=Mercedes") - requestParams.add("datasetId", "urn:ngsi-ld:Dataset:Test1,urn:ngsi-ld:Dataset:Test2") - requestParams.add("count", "true") - requestParams.add("offset", "1") - requestParams.add("limit", "10") - requestParams.add("options", "keyValues") - return requestParams - } - - @Test - fun `it should parse a valid complete query`() = runTest { - val query = """ - { - "type": "Query", - "entities": [{ - "id": "urn:ngsi-ld:BeeHive:TESTC", - "idPattern": "urn:ngsi-ld:BeeHive:*", - "type": "BeeHive" - }], - "attrs": ["attr1", "attr2"], - "q": "temperature>32", - "geoQ": { - "geometry": "Point", - "coordinates": [1.0, 1.0], - "georel": "equals", - "geoproperty": "observationSpace" - }, - "temporalQ": { - "timerel": "between", - "timeAt": "2023-10-01T12:34:56Z", - "endTimeAt": "2023-10-02T12:34:56Z", - "lastN": 10, - "timeproperty": "observedAt" - }, - "scopeQ": "/Nantes", - "datasetId": ["urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"] - } - """.trimIndent() - - composeEntitiesQueryFromPostRequest( - buildDefaultPagination(30, 100), - query, - LinkedMultiValueMap(), - APIC_COMPOUND_CONTEXTS - ).shouldSucceedWith { - assertEquals(setOf("urn:ngsi-ld:BeeHive:TESTC".toUri()), it.ids) - assertEquals("urn:ngsi-ld:BeeHive:*", it.idPattern) - assertEquals(BEEHIVE_TYPE, it.typeSelection) - assertEquals(setOf("${NGSILD_DEFAULT_VOCAB}attr1", "${NGSILD_DEFAULT_VOCAB}attr2"), it.attrs) - assertEquals("temperature>32", it.q) - assertEquals(GeoQuery.GeometryType.POINT, it.geoQuery?.geometry) - assertEquals("[1.0, 1.0]", it.geoQuery?.coordinates) - assertEquals(GEO_QUERY_GEOREL_EQUALS, it.geoQuery?.georel) - assertEquals(NGSILD_OBSERVATION_SPACE_PROPERTY, it.geoQuery?.geoproperty) - assertEquals("/Nantes", it.scopeQ) - assertEquals(setOf("urn:ngsi-ld:Dataset:Test1", "urn:ngsi-ld:Dataset:Test2"), it.datasetId) - } - } - - @Test - fun `it should parse a valid simple query`() = runTest { - val query = """ - { - "type": "Query", - "entities": [{ - "type": "BeeHive" - }], - "attrs": ["attr1"], - "q": "temperature>32" - } - """.trimIndent() - - composeEntitiesQueryFromPostRequest( - buildDefaultPagination(30, 100), - query, - LinkedMultiValueMap(), - APIC_COMPOUND_CONTEXTS - ).shouldSucceedWith { - assertEquals(BEEHIVE_TYPE, it.typeSelection) - assertEquals(setOf("${NGSILD_DEFAULT_VOCAB}attr1"), it.attrs) - assertEquals("temperature>32", it.q) - } - } - - @Test - fun `it should not validate a query if the type is not correct`() { - val query = """ - { - "type": "NotAQuery", - "attrs": ["attr1", "attr2"] - } - """.trimIndent() - - composeEntitiesQueryFromPostRequest( - buildDefaultPagination(30, 100), - query, - LinkedMultiValueMap(), - APIC_COMPOUND_CONTEXTS - ).shouldFailWith { - it is BadRequestDataException && - it.message == "The type parameter should be equals to 'Query'" - } - } - - @Test - fun `it should not validate a query if the payload could not be parsed because the JSON is invalid`() { - val query = """ - { - "type": "Query",, - "attrs": ["attr1", "attr2"] - } - """.trimIndent() - - composeEntitiesQueryFromPostRequest( - buildDefaultPagination(30, 100), - query, - LinkedMultiValueMap(), - APIC_COMPOUND_CONTEXTS - ).shouldFailWith { - it is BadRequestDataException && - it.message.startsWith("The supplied query could not be parsed") - } - } - - @Test - fun `it should not validate a query if the payload contains unexpected parameters`() { - val query = """ - { - "type": "Query", - "property": "anUnexpectedProperty" - } - """.trimIndent() - - composeEntitiesQueryFromPostRequest( - buildDefaultPagination(30, 100), - query, - LinkedMultiValueMap(), - APIC_COMPOUND_CONTEXTS - ).shouldFailWith { - it is BadRequestDataException && - it.message.startsWith("The supplied query could not be parsed") - } - } - - private fun composeEntitiesQueryFromPostRequest( - defaultPagination: ApplicationProperties.Pagination, - requestBody: String, - requestParams: MultiValueMap, - contexts: List - ): Either = either { - val query = Query(requestBody).bind() - com.egm.stellio.search.entity.util.composeEntitiesQueryFromPostRequest( - defaultPagination, - query, - requestParams, - contexts - ).bind() - } +class TemporalQueryUtilsTests { @Test fun `it should not validate the temporal query if type or attrs are not present`() = runTest { diff --git a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/web/TemporalEntityHandlerTests.kt b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/web/TemporalEntityHandlerTests.kt index e9f4b2852..40eb21511 100644 --- a/search-service/src/test/kotlin/com/egm/stellio/search/temporal/web/TemporalEntityHandlerTests.kt +++ b/search-service/src/test/kotlin/com/egm/stellio/search/temporal/web/TemporalEntityHandlerTests.kt @@ -681,7 +681,7 @@ class TemporalEntityHandlerTests : TemporalEntityHandlerTestCommon() { val attInstanceResults = attributes.flatMap { values.map { SimplifiedAttributeInstanceResult( - attribute = UUID.randomUUID(), + attributeUuid = UUID.randomUUID(), value = it.first, time = ZonedDateTime.parse(it.second) )