Skip to content

Commit

Permalink
Handle deserialization of empty remote contexts in ResourceEvents a…
Browse files Browse the repository at this point in the history
…nd `ResourceState` (#4317)
  • Loading branch information
olivergrabinski authored Oct 3, 2023
1 parent bf0e1f1 commit 523ff52
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import ch.epfl.bluebrain.nexus.delta.sourcing.model.{EntityType, Label, ProjectR
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.{deriveConfiguredCodec, deriveConfiguredEncoder}
import io.circe.syntax._
import io.circe.{Codec, Decoder, Encoder, Json, JsonObject}
import io.circe._

import java.time.Instant
import scala.annotation.nowarn
Expand Down Expand Up @@ -90,7 +90,8 @@ object ResourceEvent {
source: Json,
compacted: CompactedJsonLd,
expanded: ExpandedJsonLd,
remoteContexts: Set[RemoteContextRef],
// TODO: Remove default after 1.10 migration
remoteContexts: Set[RemoteContextRef] = Set.empty,
rev: Int,
instant: Instant,
subject: Subject
Expand Down Expand Up @@ -133,7 +134,8 @@ object ResourceEvent {
source: Json,
compacted: CompactedJsonLd,
expanded: ExpandedJsonLd,
remoteContexts: Set[RemoteContextRef],
// TODO: Remove default after 1.10 migration
remoteContexts: Set[RemoteContextRef] = Set.empty,
rev: Int,
instant: Instant,
subject: Subject
Expand Down Expand Up @@ -173,7 +175,8 @@ object ResourceEvent {
types: Set[Iri],
compacted: CompactedJsonLd,
expanded: ExpandedJsonLd,
remoteContexts: Set[RemoteContextRef],
// TODO: Remove default after 1.10 migration
remoteContexts: Set[RemoteContextRef] = Set.empty,
rev: Int,
instant: Instant,
subject: Subject
Expand Down Expand Up @@ -269,8 +272,9 @@ object ResourceEvent {
import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd.Database._
import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._

//TODO remove after migration of events
implicit val configuration: Configuration = Serializer.circeConfiguration
// TODO: The `.withDefaults` method is used in order to inject the default empty remoteContexts
// when deserializing an event that has none. Remove it after 1.10 migration.
implicit val configuration: Configuration = Serializer.circeConfiguration.withDefaults

implicit val coder: Codec.AsObject[ResourceEvent] = deriveConfiguredCodec[ResourceEvent]
Serializer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ final case class ResourceState(
source: Json,
compacted: CompactedJsonLd,
expanded: ExpandedJsonLd,
remoteContexts: Set[RemoteContextRef],
// TODO: Remove default after 1.10 migration
remoteContexts: Set[RemoteContextRef] = Set.empty,
rev: Int,
deprecated: Boolean,
schema: ResourceRef,
Expand Down Expand Up @@ -94,7 +95,10 @@ object ResourceState {
import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.CompactedJsonLd.Database._
import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd.Database._
import ch.epfl.bluebrain.nexus.delta.sourcing.model.Identity.Database._
implicit val configuration: Configuration = Serializer.circeConfiguration

// TODO: The `.withDefaults` method is used in order to inject the default empty remoteContexts
// when deserializing an event that has none. Remove it after 1.10 migration.
implicit val configuration: Configuration = Serializer.circeConfiguration.withDefaults
implicit val codec: Codec.AsObject[ResourceState] = deriveConfiguredCodec[ResourceState]
Serializer()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"project": "myorg/myproj",
"schema": "https://bluebrain.github.io/nexus/schemas/unconstrained.json?rev=1",
"schemaProject": "myorg/myproj",
"types": [
"https://neuroshapes.org/Morphology"
],
"source": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"compacted": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"expanded": [
{
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": [
"https://neuroshapes.org/Morphology"
],
"https://bluebrain.github.io/nexus/vocabulary/name": [
{
"@value": "Morphology 001"
}
]
}
],
"rev": 1,
"instant": "1970-01-01T00:00:00Z",
"subject": {
"subject": "username",
"realm": "myrealm",
"@type": "User"
},
"@type": "ResourceCreated"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"project": "myorg/myproj",
"schema": "https://bluebrain.github.io/nexus/schemas/unconstrained.json?rev=1",
"schemaProject": "myorg/myproj",
"types" : [
"https://neuroshapes.org/Morphology"
],
"compacted": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"expanded": [
{
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": [
"https://neuroshapes.org/Morphology"
],
"https://bluebrain.github.io/nexus/vocabulary/name": [
{
"@value": "Morphology 001"
}
]
}
],
"rev": 2,
"instant": "1970-01-01T00:00:00Z",
"subject": {
"subject": "username",
"realm": "myrealm",
"@type": "User"
},
"@type": "ResourceRefreshed"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"project": "myorg/myproj",
"schema": "https://bluebrain.github.io/nexus/schemas/unconstrained.json?rev=1",
"schemaProject": "myorg/myproj",
"types": [
"https://neuroshapes.org/Morphology"
],
"source": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"compacted": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"expanded": [
{
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": [
"https://neuroshapes.org/Morphology"
],
"https://bluebrain.github.io/nexus/vocabulary/name": [
{
"@value": "Morphology 001"
}
]
}
],
"rev": 2,
"instant": "1970-01-01T00:00:00Z",
"subject": {
"subject": "username",
"realm": "myrealm",
"@type": "User"
},
"@type": "ResourceUpdated"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"project": "myorg/myproj",
"schemaProject": "myorg/myproj",
"source": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"compacted": {
"@context": [
"https://neuroshapes.org",
"https://bluebrain.github.io/nexus/contexts/metadata.json",
{
"@vocab": "https://bluebrain.github.io/nexus/vocabulary/"
}
],
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": "Morphology",
"name": "Morphology 001"
},
"expanded": [
{
"@id": "https://bluebrain.github.io/nexus/vocabulary/myId",
"@type": [
"https://neuroshapes.org/Morphology"
],
"https://bluebrain.github.io/nexus/vocabulary/name": [
{
"@value": "Morphology 001"
}
]
}
],
"rev": 2,
"deprecated": false,
"schema": "https://bluebrain.github.io/nexus/schemas/unconstrained.json?rev=1",
"types": [
"https://neuroshapes.org/Morphology"
],
"tags": {
"mytag": 3
},
"createdAt": "1970-01-01T00:00:00Z",
"createdBy": {
"subject": "username",
"realm": "myrealm",
"@type": "User"
},
"updatedAt": "1970-01-01T00:00:00Z",
"updatedBy": {
"subject": "username",
"realm": "myrealm",
"@type": "User"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,21 @@ class ResourceSerializationSuite extends SerializationSuite with ResourceInstanc
)

resourcesMapping.foreach { case (event, (database, sse), action) =>
test(s"Correctly serialize ${event.getClass.getName}") {
test(s"Correctly serialize ${event.getClass.getSimpleName}") {
assertOutput(ResourceEvent.serializer, event, database)
}

test(s"Correctly deserialize ${event.getClass.getName}") {
test(s"Correctly deserialize ${event.getClass.getSimpleName}") {
assertEquals(ResourceEvent.serializer.codec.decodeJson(database), Right(event))
}

test(s"Correctly serialize ${event.getClass.getName} as an SSE") {
test(s"Correctly serialize ${event.getClass.getSimpleName} as an SSE") {
sseEncoder.toSse
.decodeJson(database)
.assertRight(SseData(ClassUtils.simpleName(event), Some(ProjectRef(org, proj)), sse))
}

test(s"Correctly encode ${event.getClass.getName} to metric") {
test(s"Correctly encode ${event.getClass.getSimpleName} to metric") {
ResourceEvent.resourceEventMetricEncoder.toMetric.decodeJson(database).assertRight {
ProjectScopedMetric(
instant,
Expand All @@ -139,6 +139,19 @@ class ResourceSerializationSuite extends SerializationSuite with ResourceInstanc
}
}

private val resourcesMappingNoRemoteContexts = List(
(created.noRemoteContext, jsonContentOf("resources/database/resource-created-no-remote-contexts.json")),
(updated.noRemoteContext, jsonContentOf("resources/database/resource-updated-no-remote-contexts.json")),
(refreshed.noRemoteContext, jsonContentOf("resources/database/resource-refreshed-no-remote-contexts.json"))
)

// TODO: Remove test after 1.10 migration.
resourcesMappingNoRemoteContexts.foreach { case (event, database) =>
test(s"Correctly deserialize a ${event.getClass.getSimpleName} with no RemoteContext") {
assertEquals(ResourceEvent.serializer.codec.decodeJson(database), Right(event))
}
}

private val state = ResourceState(
myId,
projectRef,
Expand All @@ -158,7 +171,8 @@ class ResourceSerializationSuite extends SerializationSuite with ResourceInstanc
updatedBy = subject
)

private val jsonState = jsonContentOf("/resources/resource-state.json")
private val jsonState = jsonContentOf("/resources/resource-state.json")
private val jsonStateNoRemoteContext = jsonContentOf("/resources/resource-state-no-remote-contexts.json")

test(s"Correctly serialize a ResourceState") {
assertOutput(ResourceState.serializer, state, jsonState)
Expand All @@ -168,4 +182,21 @@ class ResourceSerializationSuite extends SerializationSuite with ResourceInstanc
assertEquals(ResourceState.serializer.codec.decodeJson(jsonState), Right(state))
}

// TODO: Remove test after 1.10 migration.
test("Correctly deserialize a ResourceState with no remote contexts") {
assertEquals(
ResourceState.serializer.codec.decodeJson(jsonStateNoRemoteContext),
Right(state.copy(remoteContexts = Set.empty))
)
}

implicit class ResourceEventTestOps(event: ResourceEvent) {
def noRemoteContext: ResourceEvent = event match {
case r: ResourceCreated => r.copy(remoteContexts = Set.empty)
case r: ResourceUpdated => r.copy(remoteContexts = Set.empty)
case r: ResourceRefreshed => r.copy(remoteContexts = Set.empty)
case r => r
}
}

}

This file was deleted.

0 comments on commit 523ff52

Please sign in to comment.