Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
bobeal committed Oct 6, 2020
2 parents 7730a27 + 9aefd9d commit 2c1568d
Show file tree
Hide file tree
Showing 16 changed files with 50 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import java.net.URI
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Optional
import java.util.UUID

Expand Down Expand Up @@ -482,7 +483,7 @@ class EntityServiceTests {
it.name == "temperature" &&
it.value == 250 &&
it.unitCode == "kg" &&
it.observedAt.toString() == "2019-12-18T10:45:44.248755Z"
it.observedAt?.format(DateTimeFormatter.ISO_DATE_TIME) == "2019-12-18T10:45:44.248755Z"
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ObservationListenerTests {
assertEquals(20.7, observation.value)
assertEquals("CEL", observation.unitCode)
assertEquals("urn:sosa:Sensor:10e2073a01080065".toUri(), observation.observedBy)
assertEquals("2019-10-18T07:31:39.770Z", observation.observedAt.toString())
assertEquals("2019-10-18T07:31:39.77Z", observation.observedAt.format(DateTimeFormatter.ISO_DATE_TIME))
assertEquals(24.30623, observation.longitude)
assertEquals(60.07966, observation.latitude)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.springframework.transaction.annotation.Transactional
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.net.URI
import java.time.format.DateTimeFormatter
import java.util.UUID

@Service
Expand Down Expand Up @@ -265,13 +266,13 @@ class TemporalEntityAttributeService(
attributeInstanceResults.map {
if (it.value is Double)
TemporalValue(
it.value as Double,
it.observedAt.toString()
it.value,
it.observedAt.format(DateTimeFormatter.ISO_DATE_TIME)
)
else
RawValue(
it.value,
it.observedAt.toString()
it.observedAt.format(DateTimeFormatter.ISO_DATE_TIME)
)
}
instanceToEnrich[NGSILD_PROPERTY_VALUES] = listOf(mapOf("@list" to valuesMap))
Expand All @@ -289,7 +290,7 @@ class TemporalEntityAttributeService(
NGSILD_PROPERTY_VALUE to it.value,
NGSILD_OBSERVED_AT_PROPERTY to mapOf(
JSONLD_TYPE to NGSILD_DATE_TIME_TYPE,
JSONLD_VALUE_KW to it.observedAt.toString()
JSONLD_VALUE_KW to it.observedAt.format(DateTimeFormatter.ISO_DATE_TIME)
)
)
// a null datasetId should not be added to the valuesMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import reactor.test.StepVerifier
import java.time.Instant
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.UUID
import kotlin.random.Random

Expand Down Expand Up @@ -83,7 +84,7 @@ class AttributeInstanceServiceTests : TimescaleBasedTests() {
it.size == 1 &&
it[0].attributeName == "incoming" &&
it[0].value == 12.4 &&
ZonedDateTime.parse(it[0].observedAt.toString()).toInstant()
ZonedDateTime.parse(it[0].observedAt.format(DateTimeFormatter.ISO_DATE_TIME)).toInstant()
.atZone(ZoneOffset.UTC) == observationDateTime &&
(it[0].instanceId.toString()).startsWith("urn:ngsi-ld:Instance:")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class TemporalEntityAttributeServiceTests : TimescaleBasedTests() {
AttributeInstanceResult(
attributeName = "https://ontology.eglobalmark.com/apic#incoming",
value = 650.0,
observedAt = ZonedDateTime.parse("2020-03-25T08:33:17.965206Z")
observedAt = ZonedDateTime.parse("2020-03-25T08:33:00Z")
)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"type" : "Relationship",
"object" : "urn:ngsi-ld:Sensor:IncomingSensor"
},
"values" : [ [550.0,"2020-03-25T08:29:17.965206Z"], [650.0,"2020-03-25T08:33:17.965206Z"] ],
"values" : [ [550.0,"2020-03-25T08:29:17.965206Z"], [650.0,"2020-03-25T08:33:00Z"] ],
"observedAt" : "2020-01-24T13:01:22.066Z"
},
"connectsTo" : {
Expand Down
32 changes: 0 additions & 32 deletions shared/src/main/kotlin/com/egm/stellio/shared/util/ApiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ package com.egm.stellio.shared.util

import com.egm.stellio.shared.model.BadRequestDataException
import com.egm.stellio.shared.util.JsonLdUtils.extractContextFromInput
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import java.time.ZonedDateTime
Expand All @@ -15,36 +10,9 @@ import java.util.*

object ApiUtils {

private val mapper: ObjectMapper =
jacksonObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.findAndRegisterModules()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)

fun addContextToParsedObject(parsedObject: Map<String, Any>, contexts: List<String>): Map<String, Any> {
return parsedObject.plus(Pair("@context", contexts))
}

/**
* As per 6.3.5, extract @context from request payload. In the absence of such context, then BadRequestDataException
* shall be raised
*
* TODO still used in subscription service but it should be removed in favor of #extractContextFromInput
*/
fun getContextOrThrowError(input: String): List<String> {
val rawParsedData = mapper.readTree(input) as ObjectNode
val context = rawParsedData.get("@context")
?: throw BadRequestDataException("JSON-LD @context not found in request payload body")

return try {
mapper.readValue(
context.toString(),
mapper.typeFactory.constructCollectionType(List::class.java, String::class.java)
)
} catch (e: Exception) {
throw BadRequestDataException(e.message ?: "Unable to parse the provided context")
}
}
}

fun String.parseTimeParameter(errorMsg: String): ZonedDateTime =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
import java.time.ZonedDateTime

data class NotificationParams(
var attributes: List<String>,
var attributes: List<String>?,
val format: FormatType = FormatType.NORMALIZED,
val endpoint: Endpoint,
var status: StatusType?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ data class Subscription(
this.entities.forEach {
it.type = JsonLdUtils.expandJsonLdKey(it.type, context)!!
}
this.notification.attributes = this.notification.attributes.map {
this.notification.attributes = this.notification.attributes?.map {
JsonLdUtils.expandJsonLdKey(it, context)!!
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono
import java.net.URI
import java.time.format.DateTimeFormatter

@Service
class NotificationService(
Expand Down Expand Up @@ -90,7 +91,8 @@ class NotificationService(
}

private fun buildNotifData(entity: JsonLdEntity, params: NotificationParams): List<Map<String, Any>> {
val filteredEntity = JsonLdUtils.filterCompactedEntityOnAttributes(entity.compact(), params.attributes.toSet())
val filteredEntity =
JsonLdUtils.filterCompactedEntityOnAttributes(entity.compact(), params.attributes?.toSet() ?: emptySet())
val processedEntity = if (params.format == NotificationParams.FormatType.KEY_VALUES)
filteredEntity.toKeyValues()
else
Expand All @@ -117,7 +119,7 @@ class NotificationService(
mapOf(
"id_alert" to notification.id.toString(),
"id_subscription" to subscription.id.toString(),
"timestamp" to notification.notifiedAt.toString(),
"timestamp" to notification.notifiedAt.format(DateTimeFormatter.ISO_DATE_TIME),
"id_beehive" to entityId.toString()
),
fcmDeviceToken
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class SubscriptionService(
.bind("description", subscription.description)
.bind("watched_attributes", subscription.watchedAttributes?.joinToString(separator = ","))
.bind("q", subscription.q)
.bind("notif_attributes", subscription.notification.attributes.joinToString(separator = ","))
.bind("notif_attributes", subscription.notification.attributes?.joinToString(separator = ","))
.bind("notif_format", subscription.notification.format.name)
.bind("endpoint_uri", subscription.notification.endpoint.uri)
.bind("endpoint_accept", subscription.notification.endpoint.accept.name)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.egm.stellio.subscription.utils

import com.egm.stellio.shared.model.BadRequestDataException
import com.egm.stellio.shared.util.ApiUtils.getContextOrThrowError
import com.egm.stellio.shared.util.JsonLdUtils
import com.egm.stellio.subscription.model.EndpointInfo
import com.egm.stellio.subscription.model.EntityInfo
Expand All @@ -26,7 +25,7 @@ object ParsingUtils {
}
}

fun parseSubscriptionUpdate(input: String): Pair<Map<String, Any>, List<String>> {
fun parseSubscriptionUpdate(input: String, context: List<String>): Pair<Map<String, Any>, List<String>> {
val mapper = jacksonObjectMapper()
val parsedSubscription: Map<String, List<Any>> = mapper.readValue(
input,
Expand All @@ -35,7 +34,7 @@ object ParsingUtils {
)
)

return Pair(parsedSubscription, getContextOrThrowError(input))
return Pair(parsedSubscription, context)
}

fun parseEntityInfo(input: Map<String, Any>, contexts: List<String>?): EntityInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import com.egm.stellio.shared.model.AccessDeniedException
import com.egm.stellio.shared.model.AlreadyExistsException
import com.egm.stellio.shared.model.BadRequestDataResponse
import com.egm.stellio.shared.model.ResourceNotFoundException
import com.egm.stellio.shared.util.ApiUtils.getContextOrThrowError
import com.egm.stellio.shared.util.JSON_LD_CONTENT_TYPE
import com.egm.stellio.shared.util.JSON_MERGE_PATCH_CONTENT_TYPE
import com.egm.stellio.shared.util.PagingUtils.SUBSCRIPTION_QUERY_PAGING_LIMIT
import com.egm.stellio.shared.util.PagingUtils.getSubscriptionsPagingLinks
import com.egm.stellio.shared.util.checkAndGetContext
import com.egm.stellio.shared.util.toUri
import com.egm.stellio.shared.web.extractSubjectOrEmpty
import com.egm.stellio.subscription.model.Subscription
Expand All @@ -17,6 +17,7 @@ import com.egm.stellio.subscription.service.SubscriptionService
import com.egm.stellio.subscription.utils.ParsingUtils.parseSubscription
import com.egm.stellio.subscription.utils.ParsingUtils.parseSubscriptionUpdate
import org.slf4j.LoggerFactory
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
Expand All @@ -26,6 +27,7 @@ import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
Expand All @@ -46,11 +48,10 @@ class SubscriptionHandler(
* Implements 6.10.3.1 - Create Subscription
*/
@PostMapping(consumes = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE])
fun create(@RequestBody body: Mono<String>): Mono<ResponseEntity<*>> {
fun create(@RequestHeader httpHeaders: HttpHeaders, @RequestBody body: Mono<String>): Mono<ResponseEntity<*>> {
return body
.map {
val context = getContextOrThrowError(it)
parseSubscription(it, context)
parseSubscription(it, checkAndGetContext(httpHeaders, it))
}
.flatMap {
checkSubscriptionNotExists(it)
Expand Down Expand Up @@ -142,7 +143,11 @@ class SubscriptionHandler(
"/{subscriptionId}",
consumes = [MediaType.APPLICATION_JSON_VALUE, JSON_LD_CONTENT_TYPE, JSON_MERGE_PATCH_CONTENT_TYPE]
)
fun update(@PathVariable subscriptionId: String, @RequestBody body: Mono<String>): Mono<ResponseEntity<*>> {
fun update(
@PathVariable subscriptionId: String,
@RequestHeader httpHeaders: HttpHeaders,
@RequestBody body: Mono<String>
): Mono<ResponseEntity<*>> {
val subscriptionIdUri = subscriptionId.toUri()
return checkSubscriptionExists(subscriptionIdUri)
.flatMap {
Expand All @@ -155,7 +160,7 @@ class SubscriptionHandler(
body
}
.flatMap {
val parsedInput = parseSubscriptionUpdate(it)
val parsedInput = parseSubscriptionUpdate(it, checkAndGetContext(httpHeaders, it))
subscriptionService.update(subscriptionIdUri, parsedInput)
}
.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.hamcrest.core.Is
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
import org.springframework.context.annotation.Import
Expand All @@ -34,6 +35,9 @@ import reactor.core.publisher.Mono
@WithMockCustomUser(name = "Mock User", username = "mock-user")
class SubscriptionHandlerTests {

@Value("\${application.jsonld.apic_context}")
val apicContext: String? = null

@Autowired
private lateinit var webClient: WebTestClient

Expand Down Expand Up @@ -188,6 +192,7 @@ class SubscriptionHandlerTests {
fun `create subscription should return a 400 if JSON-LD payload is not correct`() {
val jsonLdFile = ClassPathResource("/ngsild/subscription_incorrect_payload.json")

@Suppress("MaxLineLength")
webClient.post()
.uri("/ngsi-ld/v1/subscriptions")
.bodyValue(jsonLdFile)
Expand All @@ -198,7 +203,7 @@ class SubscriptionHandlerTests {
{
"type":"https://uri.etsi.org/ngsi-ld/errors/BadRequestData",
"title":"The request includes input data which does not meet the requirements of the operation",
"detail":"JSON-LD @context not found in request payload body"
"detail":"Request payload must contain @context term for a request having an application/ld+json content type"
}
""".trimIndent()
)
Expand Down Expand Up @@ -360,7 +365,10 @@ class SubscriptionHandlerTests {
fun `update subscription should return a 204 if JSON-LD payload is correct`() {
val jsonLdFile = ClassPathResource("/ngsild/subscription_update.json")
val subscriptionId = "urn:ngsi-ld:Subscription:04".toUri()
val parsedSubscription = parseSubscriptionUpdate(jsonLdFile.inputStream.readBytes().toString(Charsets.UTF_8))
val parsedSubscription = parseSubscriptionUpdate(
jsonLdFile.inputStream.readBytes().toString(Charsets.UTF_8),
listOf(apicContext!!)
)

every { subscriptionService.exists(any()) } returns Mono.just(true)
every { subscriptionService.isCreatorOf(any(), any()) } returns Mono.just(true)
Expand All @@ -382,7 +390,10 @@ class SubscriptionHandlerTests {
fun `update subscription should return a 500 if update in DB failed`() {
val jsonLdFile = ClassPathResource("/ngsild/subscription_update.json")
val subscriptionId = "urn:ngsi-ld:Subscription:04".toUri()
val parsedSubscription = parseSubscriptionUpdate(jsonLdFile.inputStream.readBytes().toString(Charsets.UTF_8))
val parsedSubscription = parseSubscriptionUpdate(
jsonLdFile.inputStream.readBytes().toString(Charsets.UTF_8),
listOf(apicContext!!)
)

every { subscriptionService.exists(any()) } returns Mono.just(true)
every { subscriptionService.isCreatorOf(any(), any()) } returns Mono.just(true)
Expand Down Expand Up @@ -434,6 +445,7 @@ class SubscriptionHandlerTests {
every { subscriptionService.exists(any()) } returns Mono.just(true)
every { subscriptionService.isCreatorOf(any(), any()) } returns Mono.just(true)

@Suppress("MaxLineLength")
webClient.patch()
.uri("/ngsi-ld/v1/subscriptions/$subscriptionId")
.bodyValue(jsonLdFile)
Expand All @@ -444,7 +456,7 @@ class SubscriptionHandlerTests {
{
"type":"https://uri.etsi.org/ngsi-ld/errors/BadRequestData",
"title":"The request includes input data which does not meet the requirements of the operation",
"detail":"JSON-LD @context not found in request payload body"
"detail":"Request payload must contain @context term for a request having an application/ld+json content type"
}
""".trimIndent()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
}
},
"@context":[
"http://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld",
"https://gist.githubusercontent.com/bobeal/2e5905a069ad534b4919839b6b4c1245/raw/ed0b0103c8b498c034d8ad367d3494d02a9ad28b/apic.jsonld",
"https://gist.githubusercontent.com/bobeal/4a836c81b837673b12e9db9916b1cd35/raw/82fba02005f3fc572d60744e38f6591bbaa09d6d/egm.jsonld"
"https://raw.githubusercontent.com/easy-global-market/ngsild-api-data-models/master/apic/jsonld-contexts/apic-compound.jsonld"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
}
},
"@context":[
"http://uri.etsi.org/ngsi-ld/v1/ngsi-ld-core-context.jsonld",
"https://gist.githubusercontent.com/bobeal/2e5905a069ad534b4919839b6b4c1245/raw/ed0b0103c8b498c034d8ad367d3494d02a9ad28b/apic.jsonld",
"https://gist.githubusercontent.com/bobeal/4a836c81b837673b12e9db9916b1cd35/raw/82fba02005f3fc572d60744e38f6591bbaa09d6d/egm.jsonld"
"https://raw.githubusercontent.com/easy-global-market/ngsild-api-data-models/master/apic/jsonld-contexts/apic-compound.jsonld"
]
}

0 comments on commit 2c1568d

Please sign in to comment.