diff --git a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/GraphResourceToNTriples.scala b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/GraphResourceToNTriples.scala index 3125d5c3fe..112964c317 100644 --- a/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/GraphResourceToNTriples.scala +++ b/delta/plugins/blazegraph/src/main/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/indexing/GraphResourceToNTriples.scala @@ -21,9 +21,7 @@ object GraphResourceToNTriples extends Pipe { def graphToNTriples(graphResource: GraphResource): IO[Option[NTriples]] = { val graph = graphResource.graph ++ graphResource.metadataGraph - IO - .fromEither(graph.toNTriples) - .map(triples => Option.when(!triples.isEmpty)(triples)) + graph.toNTriples.map(triples => Option.when(!triples.isEmpty)(triples)) } override def apply(element: SuccessElem[GraphResource]): IO[Elem[NTriples]] = diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/client/BlazegraphClientSpec.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/client/BlazegraphClientSpec.scala index f03ef56217..773681fa3a 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/client/BlazegraphClientSpec.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/client/BlazegraphClientSpec.scala @@ -49,13 +49,13 @@ class BlazegraphClientSpec(docker: BlazegraphDocker) private def nTriples(id: String = genString(), label: String = genString(), value: String = genString()) = { val json = jsonContentOf("sparql/example.jsonld", "id" -> id, "label" -> label, "value" -> value) - ExpandedJsonLd(json).accepted.toGraph.flatMap(_.toNTriples).rightValue + ExpandedJsonLd(json).accepted.toGraph.flatMap(_.toNTriples).accepted } private def nTriplesNested(id: String, label: String, name: String, title: String) = { val json = jsonContentOf("sparql/example-nested.jsonld", "id" -> id, "label" -> label, "name" -> name, "title" -> title) - ExpandedJsonLd(json).accepted.toGraph.flatMap(_.toNTriples).rightValue + ExpandedJsonLd(json).accepted.toGraph.flatMap(_.toNTriples).accepted } private def expectedResult(id: String, label: String, value: String) = diff --git a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala index 376973b5d3..0b57adb729 100644 --- a/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala +++ b/delta/plugins/blazegraph/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/blazegraph/routes/BlazegraphViewsQuerySpec.scala @@ -128,11 +128,11 @@ class BlazegraphViewsQuerySpec(docker: BlazegraphDocker) private def createNTriples(view: ViewRef*): NTriples = view.foldLeft(NTriples.empty) { (ntriples, view) => - createGraphs(view).foldLeft(ntriples)(_ ++ _.toNTriples.rightValue) + createGraphs(view).foldLeft(ntriples)(_ ++ _.toNTriples.accepted) } private def createTriples(view: ViewRef): Seq[NTriples] = - createGraphs(view).map(_.toNTriples.rightValue) + createGraphs(view).map(_.toNTriples.accepted) private def sparqlResourceLinkFor(resourceId: Iri, path: Iri) = SparqlResourceLink( diff --git a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/GraphResourceToDocumentSuite.scala b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/GraphResourceToDocumentSuite.scala index 50685793b5..93dce86706 100644 --- a/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/GraphResourceToDocumentSuite.scala +++ b/delta/plugins/elasticsearch/src/test/scala/ch/epfl/bluebrain/nexus/delta/plugins/elasticsearch/indexing/GraphResourceToDocumentSuite.scala @@ -36,7 +36,7 @@ class GraphResourceToDocumentSuite extends NexusSuite with Fixtures with JsonAss """ private val expanded = ExpandedJsonLd.expanded(expandedJson).rightValue - private val graph = Graph(expanded).rightValue + private val graph = Graph(expanded).accepted private val metadataGraph = graph private val context = ContextValue.fromFile("contexts/elasticsearch-indexing.json").accepted diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/Graph.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/Graph.scala index c0a71f5db2..33f6e6be03 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/Graph.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/Graph.scala @@ -178,22 +178,20 @@ final case class Graph private (rootNode: IriOrBNode, value: DatasetGraph) { sel /** * Attempts to convert the current Graph to the N-Triples format: https://www.w3.org/TR/n-triples/ */ - def toNTriples: Either[RdfError, NTriples] = - tryOrRdfError( + def toNTriples: IO[NTriples] = + tryExpensiveIO( RDFWriter.create().lang(Lang.NTRIPLES).source(collapseGraphs).asString(), Lang.NTRIPLES.getName - ) - .map(NTriples(_, rootNode)) + ).map(NTriples(_, rootNode)) /** * Attempts to convert the current Graph to the N-Quads format: https://www.w3.org/TR/n-quads/ */ - def toNQuads: Either[RdfError, NQuads] = - tryOrRdfError( + def toNQuads: IO[NQuads] = + tryExpensiveIO( RDFWriter.create().lang(Lang.NQUADS).source(value).asString(), Lang.NQUADS.getName - ) - .map(NQuads(_, rootNode)) + ).map(NQuads(_, rootNode)) /** * Transform the current graph to a new one via the provided construct query @@ -247,11 +245,11 @@ final case class Graph private (rootNode: IriOrBNode, value: DatasetGraph) { sel if (rootNode.isBNode) for { - expanded <- IO.fromEither(api.fromRdf(replace(rootNode, fakeId).value)) + expanded <- api.fromRdf(replace(rootNode, fakeId).value) framed <- computeCompacted(fakeId, expanded.asJson) } yield framed.replaceId(self.rootNode) else - IO.fromEither(api.fromRdf(value)).flatMap(expanded => computeCompacted(rootNode, expanded.asJson)) + api.fromRdf(value).flatMap(expanded => computeCompacted(rootNode, expanded.asJson)) } /** @@ -337,10 +335,10 @@ object Graph { */ final def apply( expanded: ExpandedJsonLd - )(implicit api: JsonLdApi, options: JsonLdOptions): Either[RdfError, Graph] = + )(implicit api: JsonLdApi, options: JsonLdOptions): IO[Graph] = (expanded.obj(keywords.graph), expanded.rootId) match { case (Some(_), _: BNode) => - Left(UnexpectedJsonLd("Expected named graph, but root @id not found")) + IO.raiseError(UnexpectedJsonLd("Expected named graph, but root @id not found")) case (Some(_), iri: Iri) => api.toRdf(expanded.json).map(g => Graph(iri, g)) case (None, _: BNode) => diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLd.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLd.scala index adeefebe5b..c87334084a 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLd.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLd.scala @@ -38,8 +38,7 @@ final case class CompactedJsonLd private (rootId: IriOrBNode, ctx: ContextValue, opts: JsonLdOptions, api: JsonLdApi, resolution: RemoteContextResolution - ): IO[Graph] = - toExpanded.flatMap(expanded => IO.fromEither(expanded.toGraph)) + ): IO[Graph] = toExpanded.flatMap(_.toGraph) /** * Merges the current document with the passed one, overriding the fields on the current with the passed. diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLd.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLd.scala index 5dc7a9b615..76a3a083b7 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLd.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLd.scala @@ -47,10 +47,7 @@ final case class ExpandedJsonLd private (rootId: IriOrBNode, obj: JsonObject) ex /** * Converts the current document to a [[Graph]] */ - def toGraph(implicit - opts: JsonLdOptions, - api: JsonLdApi - ): Either[RdfError, Graph] = Graph(self) + def toGraph(implicit opts: JsonLdOptions, api: JsonLdApi): IO[Graph] = Graph(self) /** * Converts the current document to an ''A'' diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdApi.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdApi.scala index 0a059415c6..b141d65bb9 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdApi.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdApi.scala @@ -1,7 +1,7 @@ package ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api import cats.effect.IO -import ch.epfl.bluebrain.nexus.delta.rdf.{ExplainResult, RdfError} +import ch.epfl.bluebrain.nexus.delta.rdf.ExplainResult import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.{ContextValue, JsonLdContext, RemoteContextResolution} import io.circe.{Json, JsonObject} import org.apache.jena.sparql.core.DatasetGraph @@ -35,9 +35,9 @@ trait JsonLdApi { frame: Json )(implicit opts: JsonLdOptions, rcr: RemoteContextResolution): IO[JsonObject] - private[rdf] def toRdf(input: Json)(implicit opts: JsonLdOptions): Either[RdfError, DatasetGraph] + private[rdf] def toRdf(input: Json)(implicit opts: JsonLdOptions): IO[DatasetGraph] - private[rdf] def fromRdf(input: DatasetGraph)(implicit opts: JsonLdOptions): Either[RdfError, Seq[JsonObject]] + private[rdf] def fromRdf(input: DatasetGraph)(implicit opts: JsonLdOptions): IO[Seq[JsonObject]] private[rdf] def context( value: ContextValue diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdJavaApi.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdJavaApi.scala index 8832af60b3..309b20ceaa 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdJavaApi.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/api/JsonLdJavaApi.scala @@ -2,13 +2,13 @@ package ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api import cats.effect.IO import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri -import ch.epfl.bluebrain.nexus.delta.rdf.{ExplainResult, RdfError} import ch.epfl.bluebrain.nexus.delta.rdf.RdfError.{ConversionError, RemoteContextCircularDependency, RemoteContextError, UnexpectedJsonLd, UnexpectedJsonLdContext} import ch.epfl.bluebrain.nexus.delta.rdf.implicits._ -import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdJavaApi.{tryExpensiveIO, tryOrRdfError} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApiConfig.ErrorHandling +import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdJavaApi.tryExpensiveIO import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context.JsonLdContext.keywords import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.context._ +import ch.epfl.bluebrain.nexus.delta.rdf.{ExplainResult, RdfError} import com.github.jsonldjava.core.JsonLdError.Error.RECURSIVE_CONTEXT_INCLUSION import com.github.jsonldjava.core.{Context, DocumentLoader, JsonLdError, JsonLdOptions => JsonLdJavaOptions, JsonLdProcessor} import com.github.jsonldjava.utils.JsonUtils @@ -16,8 +16,8 @@ import io.circe.syntax._ import io.circe.{parser, Json, JsonObject} import org.apache.jena.query.DatasetFactory import org.apache.jena.riot.RDFFormat.{JSONLD_EXPAND_FLAT => EXPAND} -import org.apache.jena.riot.system.ErrorHandlerFactory import org.apache.jena.riot._ +import org.apache.jena.riot.system.ErrorHandlerFactory import org.apache.jena.sparql.core.DatasetGraph import scala.annotation.nowarn @@ -72,7 +72,7 @@ final class JsonLdJavaApi(config: JsonLdApiConfig) extends JsonLdApi { framedObj <- IO.fromEither(toJsonObjectOrErr(framed)) } yield framedObj - override private[rdf] def toRdf(input: Json)(implicit opts: JsonLdOptions): Either[RdfError, DatasetGraph] = { + override private[rdf] def toRdf(input: Json)(implicit opts: JsonLdOptions): IO[DatasetGraph] = { val c = new JsonLDReadContext() c.setOptions(toOpts()) val ds = DatasetFactory.create @@ -90,18 +90,17 @@ final class JsonLdJavaApi(config: JsonLdApiConfig) extends JsonLdApi { } } val builder = opts.base.fold(initBuilder)(base => initBuilder.base(base.toString)) - tryOrRdfError(builder.parse(ds.asDatasetGraph()), "toRdf").as(ds.asDatasetGraph()) + tryExpensiveIO(builder.parse(ds.asDatasetGraph()), "toRdf").as(ds.asDatasetGraph()) } override private[rdf] def fromRdf( input: DatasetGraph - )(implicit opts: JsonLdOptions): Either[RdfError, Seq[JsonObject]] = { + )(implicit opts: JsonLdOptions): IO[Seq[JsonObject]] = { val c = new JsonLDWriteContext() c.setOptions(toOpts()) - for { - expanded <- tryOrRdfError(RDFWriter.create.format(EXPAND).source(input).context(c).asString(), "fromRdf") - expandedSeqObj <- toSeqJsonObjectOrErr(expanded) - } yield expandedSeqObj + tryExpensiveIO(RDFWriter.create.format(EXPAND).source(input).context(c).asString(), "fromRdf").flatMap { expanded => + IO.fromEither(toSeqJsonObjectOrErr(expanded)) + } } override private[rdf] def context( diff --git a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/encoder/JsonLdEncoder.scala b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/encoder/JsonLdEncoder.scala index 786fbb7390..3d9126e0c5 100644 --- a/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/encoder/JsonLdEncoder.scala +++ b/delta/rdf/src/main/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/encoder/JsonLdEncoder.scala @@ -60,10 +60,7 @@ trait JsonLdEncoder[A] { def ntriples( value: A )(implicit opts: JsonLdOptions, api: JsonLdApi, rcr: RemoteContextResolution): IO[NTriples] = - for { - graph <- graph(value) - ntriples <- IO.fromEither(graph.toNTriples) - } yield ntriples + graph(value).flatMap(_.toNTriples) /** * Converts a value of type ''A'' to [[NQuads]] format. @@ -74,10 +71,7 @@ trait JsonLdEncoder[A] { def nquads( value: A )(implicit opts: JsonLdOptions, api: JsonLdApi, rcr: RemoteContextResolution): IO[NQuads] = - for { - graph <- graph(value) - ntriples <- IO.fromEither(graph.toNQuads) - } yield ntriples + graph(value).flatMap(_.toNQuads) /** * Converts a value of type ''A'' to [[Graph]] @@ -88,10 +82,7 @@ trait JsonLdEncoder[A] { def graph( value: A )(implicit opts: JsonLdOptions, api: JsonLdApi, rcr: RemoteContextResolution): IO[Graph] = - for { - expanded <- expand(value) - graph <- IO.fromEither(expanded.toGraph) - } yield graph + expand(value).flatMap(_.toGraph) } diff --git a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/GraphSpec.scala b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/GraphSpec.scala index 59eb3e24db..c47791966f 100644 --- a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/GraphSpec.scala +++ b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/graph/GraphSpec.scala @@ -22,23 +22,23 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { val expandedJson = jsonContentOf("expanded.json") val expanded = ExpandedJsonLd.expanded(expandedJson).rightValue val nquads = NQuads(contentOf("nquads.nq"), iri) - val graph = Graph(expanded).rightValue + val graph = Graph(expanded).accepted val bnode = bNode(graph) val iriSubject = subject(iri) val rootBNode = BNode.random val expandedNoIdJson = expandedJson.removeAll(keywords.id -> iri) val expandedNoId = ExpandedJsonLd.expanded(expandedNoIdJson).rightValue.replaceId(rootBNode) - val graphNoId = Graph(expandedNoId).rightValue + val graphNoId = Graph(expandedNoId).accepted val bnodeNoId = bNode(graphNoId) val namedGraph = Graph( ExpandedJsonLd.expanded(jsonContentOf("graph/expanded-multiple-roots-namedgraph.json")).rightValue - ).rightValue + ).accepted val name = predicate(schema.name) val birthDate = predicate(schema + "birthDate") "be created from expanded jsonld" in { - Graph(expanded).rightValue.triples.size shouldEqual 16 + Graph(expanded).accepted.triples.size shouldEqual 16 } "be created from n-quads" in { @@ -46,13 +46,13 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { } "be created from expanded jsonld with a root blank node" in { - Graph(expandedNoId).rightValue.triples.size shouldEqual 16 + Graph(expandedNoId).accepted.triples.size shouldEqual 16 } "replace its root node" in { val iri2 = iri"http://example.com/newid" val subject2 = subject(iri2) - val graph = Graph(expanded).rightValue + val graph = Graph(expanded).accepted val graph2 = graph.replaceRootNode(iri2) val expected = graph.triples.map { case (s, p, o) => (if (s == iriSubject) subject2 else s, p, o) } graph2.rootNode shouldEqual iri2 @@ -107,7 +107,7 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { "be converted to NTriples" in { val expected = contentOf("ntriples.nt", "bnode" -> bnode.rdfFormat, "rootNode" -> iri.rdfFormat) - graph.toNTriples.rightValue.toString should equalLinesUnordered(expected) + graph.toNTriples.accepted.toString should equalLinesUnordered(expected) } "be created from NTriples" in { @@ -120,22 +120,22 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { "be converted to NTriples from a named graph" in { val expected = contentOf("graph/multiple-roots-namedgraph.nt") - namedGraph.toNTriples.rightValue.toString should equalLinesUnordered(expected) + namedGraph.toNTriples.accepted.toString should equalLinesUnordered(expected) } "be converted to NTriples with a root blank node" in { val expected = contentOf("ntriples.nt", "bnode" -> bnodeNoId.rdfFormat, "rootNode" -> rootBNode.rdfFormat) - graphNoId.toNTriples.rightValue.toString should equalLinesUnordered(expected) + graphNoId.toNTriples.accepted.toString should equalLinesUnordered(expected) } "be converted to NQuads" in { val expected = contentOf("ntriples.nt", "bnode" -> bnode.rdfFormat, "rootNode" -> iri.rdfFormat) - graph.toNQuads.rightValue.toString should equalLinesUnordered(expected) + graph.toNQuads.accepted.toString should equalLinesUnordered(expected) } "be converted to NQuads from a named graph" in { val expected = contentOf("graph/multiple-roots-namedgraph.nq") - namedGraph.toNQuads.rightValue.toString should equalLinesUnordered(expected) + namedGraph.toNQuads.accepted.toString should equalLinesUnordered(expected) } "be created from NQuads with a named graph" in { @@ -185,7 +185,7 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { "failed to be converted to compacted JSON-LD from a multiple root" in { val expandedJson = jsonContentOf("graph/expanded-multiple-roots.json") val expanded = ExpandedJsonLd(expandedJson).accepted - Graph(expanded).leftValue shouldEqual UnexpectedJsonLd("Expected named graph, but root @id not found") + Graph(expanded).rejected shouldEqual UnexpectedJsonLd("Expected named graph, but root @id not found") } "be converted to compacted JSON-LD from a named graph" in { @@ -265,7 +265,7 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { "raise an error with a strict parser when an iri is invalid" in { val expandedJson = jsonContentOf("expanded-invalid-iri.json") val expanded = ExpandedJsonLd.expanded(expandedJson).rightValue - Graph(expanded).leftValue shouldEqual ConversionError( + Graph(expanded).rejected shouldEqual ConversionError( "Bad IRI: < http://nexus.example.com/myid> Spaces are not legal in URIs/IRIs.", "toRdf" ) @@ -274,7 +274,7 @@ class GraphSpec extends CatsEffectSpec with GraphHelpers with CirceLiteral { "not raise an error with a lenient parser when an iri is invalid" in { val expandedJson = jsonContentOf("expanded-invalid-iri.json") val expanded = ExpandedJsonLd.expanded(expandedJson).rightValue - Graph(expanded)(JsonLdJavaApi.lenient, JsonLdOptions.defaults).rightValue + Graph(expanded)(JsonLdJavaApi.lenient, JsonLdOptions.defaults).accepted } } } diff --git a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLdSpec.scala b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLdSpec.scala index c8a1c07c85..213f85320d 100644 --- a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLdSpec.scala +++ b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/CompactedJsonLdSpec.scala @@ -65,7 +65,7 @@ class CompactedJsonLdSpec extends CatsEffectSpec with Fixtures with GraphHelpers val graph = compacted.toGraph.accepted val expected = contentOf("ntriples.nt", "bnode" -> bNode(graph).rdfFormat, "rootNode" -> iri.rdfFormat) graph.rootNode shouldEqual iri - graph.toNTriples.rightValue.toString should equalLinesUnordered(expected) + graph.toNTriples.accepted.toString should equalLinesUnordered(expected) } "be converted to graph with a root blank node" in { @@ -73,7 +73,7 @@ class CompactedJsonLdSpec extends CatsEffectSpec with Fixtures with GraphHelpers val graph = compacted.toGraph.accepted val expected = contentOf("ntriples.nt", "bnode" -> bNode(graph).rdfFormat, "rootNode" -> rootBNode.rdfFormat) graph.rootNode shouldEqual rootBNode - graph.toNTriples.rightValue.toString should equalLinesUnordered(expected) + graph.toNTriples.accepted.toString should equalLinesUnordered(expected) } "be merged with another compacted document" in { diff --git a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLdSpec.scala b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLdSpec.scala index 367ea9759a..a4405c640c 100644 --- a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLdSpec.scala +++ b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/jsonld/ExpandedJsonLdSpec.scala @@ -99,10 +99,10 @@ class ExpandedJsonLdSpec extends CatsEffectSpec with Fixtures with GraphHelpers "be converted to graph" in { val expanded = ExpandedJsonLd(compacted).accepted - val graph = expanded.toGraph.rightValue + val graph = expanded.toGraph.accepted val expected = contentOf("ntriples.nt", "bnode" -> bNode(graph).rdfFormat, "rootNode" -> iri.rdfFormat) graph.rootNode shouldEqual iri - graph.toNTriples.rightValue.toString should equalLinesUnordered(expected) + graph.toNTriples.accepted.toString should equalLinesUnordered(expected) } "add @id value" in { diff --git a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidateShaclSuite.scala b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidateShaclSuite.scala index 481abeda24..fe51269374 100644 --- a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidateShaclSuite.scala +++ b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidateShaclSuite.scala @@ -24,7 +24,7 @@ class ValidateShaclSuite extends NexusSuite { private val schemaGraph = toGraph(schema).accepted private val dataGraph = toGraph(data).accepted - private def toGraph(json: Json) = ExpandedJsonLd(json).map(_.toGraph).rethrow + private def toGraph(json: Json) = ExpandedJsonLd(json).flatMap(_.toGraph) test("Validate data from schema model") { shaclValidation(dataGraph, schemaGraph, reportDetails = true).assert(_.conformsWithTargetedNodes) diff --git a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidationReportSpec.scala b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidationReportSpec.scala index 2886f33971..ca91541ef4 100644 --- a/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidationReportSpec.scala +++ b/delta/rdf/src/test/scala/ch/epfl/bluebrain/nexus/delta/rdf/shacl/ValidationReportSpec.scala @@ -22,7 +22,7 @@ class ValidationReportSpec extends CatsEffectSpec { RemoteContextResolution.fixed(contexts.shacl -> shaclResolvedCtx) private def resource(json: Json): Resource = { - val g = Graph(ExpandedJsonLd(json).accepted).rightValue.value + val g = Graph(ExpandedJsonLd(json).accepted).accepted.value DatasetFactory.wrap(g).getDefaultModel.createResource() } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/jsonld/JsonLdAssembly.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/jsonld/JsonLdAssembly.scala index 83f452c550..6c39f9e54f 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/jsonld/JsonLdAssembly.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/jsonld/JsonLdAssembly.scala @@ -54,7 +54,7 @@ object JsonLdAssembly { )(implicit api: JsonLdApi, rcr: RemoteContextResolution): IO[JsonLdAssembly] = for { compacted <- expanded.toCompacted(ctx).adaptError { case err: RdfError => InvalidJsonLdFormat(Some(iri), err) } - graph <- IO.fromEither(expanded.toGraph).adaptError { case err: RdfError => InvalidJsonLdFormat(Some(iri), err) } + graph <- expanded.toGraph.adaptError { case err: RdfError => InvalidJsonLdFormat(Some(iri), err) } } yield JsonLdAssembly(iri, source, compacted, expanded, graph, RemoteContextRef(remoteContexts)) def empty(id: Iri): JsonLdAssembly = diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/Resources.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/Resources.scala index 84c9e76a7b..1d99eece08 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/Resources.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/Resources.scala @@ -476,7 +476,7 @@ object Resources { def updateResourceSchema(u: UpdateResourceSchema) = { for { state <- stateWhereResourceIsEditable(u) - stateJsonLd <- IO.fromEither(state.toAssembly) + stateJsonLd <- state.toAssembly schemaClaim = SchemaClaim.onUpdate(u.project, u.schemaRef, state.schema, u.caller) (schemaRev, schemaProject) <- validate(stateJsonLd, schemaClaim, u.projectContext.enforceSchema) types = state.expanded.getTypes.getOrElse(Set.empty) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesTrial.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesTrial.scala index 11b66fbbb4..77e204c983 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesTrial.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourcesTrial.scala @@ -115,7 +115,7 @@ object ResourcesTrial { projectContext <- fetchContext.onRead(project) schemaRefOpt <- IO.fromEither(expandResourceRef(schemaOpt, projectContext)) resource <- fetchResource(id, project) - jsonld <- IO.fromEither(resource.toAssembly) + jsonld <- resource.toAssembly schemaClaim = SchemaClaim.onUpdate(project, schemaRefOpt, resource.schema, caller) report <- validateResource(jsonld, schemaClaim, projectContext.enforceSchema) } yield report diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResource.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResource.scala index 89d5b6fcbc..1109bf6b67 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResource.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResource.scala @@ -80,14 +80,15 @@ object ValidateResource { jsonld: JsonLdAssembly, schemaRef: ResourceRef, schema: ResourceF[Schema] - ): IO[ValidationReport] = - validateShacl( - jsonld.graph ++ schema.value.ontologies, - schema.value.shapes, - reportDetails = true - ).adaptError { e => - ResourceShaclEngineRejection(jsonld.id, schemaRef, e) - }.span("validateShacl") + ): IO[ValidationReport] = { + for { + ontologies <- schema.value.ontologies + shapes <- schema.value.shapes + report <- validateShacl(jsonld.graph ++ ontologies, shapes, reportDetails = true) + } yield report + }.adaptError { e => + ResourceShaclEngineRejection(jsonld.id, schemaRef, e) + }.span("validateShacl") private def assertNotReservedId(resourceId: Iri) = { IO.raiseWhen(resourceId.startsWith(contexts.base))(ReservedResourceId(resourceId)) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala index c51e238770..3cac75b308 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/model/ResourceState.scala @@ -1,7 +1,9 @@ package ch.epfl.bluebrain.nexus.delta.sdk.resources.model +import cats.effect.IO import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri +import ch.epfl.bluebrain.nexus.delta.rdf.RdfError import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.{JsonLdApi, JsonLdJavaApi} import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.{CompactedJsonLd, ExpandedJsonLd} import ch.epfl.bluebrain.nexus.delta.sdk.DataResource @@ -75,13 +77,13 @@ final case class ResourceState( updatedBy: Subject ) extends ScopedState { - def toAssembly: Either[InvalidJsonLdFormat, JsonLdAssembly] = { + def toAssembly: IO[JsonLdAssembly] = { implicit val api: JsonLdApi = JsonLdJavaApi.lenient expanded.toGraph .map { graph => JsonLdAssembly(id, source, compacted, expanded, graph, remoteContexts) } - .leftMap { err => InvalidJsonLdFormat(Some(id), err) } + .adaptError { case err: RdfError => InvalidJsonLdFormat(Some(id), err) } } def toResource: DataResource = diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/ValidateSchema.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/ValidateSchema.scala index 4a85bf9769..07a72cd444 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/ValidateSchema.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/ValidateSchema.scala @@ -5,6 +5,7 @@ import cats.effect.IO import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.kernel.syntax._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri +import ch.epfl.bluebrain.nexus.delta.rdf.RdfError import ch.epfl.bluebrain.nexus.delta.rdf.graph.Graph import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.api.JsonLdApi @@ -29,13 +30,10 @@ object ValidateSchema { } yield report }.span("validateShacl") - private def toGraph(id: Iri, expanded: NonEmptyList[ExpandedJsonLd]) = { - val eitherGraph = - toFoldableOps(expanded) - .foldM(Graph.empty)((acc, expandedEntry) => expandedEntry.toGraph.map(acc ++ (_: Graph))) - .leftMap { err => InvalidJsonLdFormat(Some(id), err) } - IO.fromEither(eitherGraph) - } + private def toGraph(id: Iri, expanded: NonEmptyList[ExpandedJsonLd]) = + toFoldableOps(expanded) + .foldM(Graph.empty)((acc, expandedEntry) => expandedEntry.toGraph.map(acc ++ (_: Graph))) + .adaptError { case err: RdfError => InvalidJsonLdFormat(Some(id), err) } } } diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/job/SchemaValidationStream.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/job/SchemaValidationStream.scala index f9648c8650..f0e2078362 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/job/SchemaValidationStream.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/job/SchemaValidationStream.scala @@ -37,7 +37,7 @@ object SchemaValidationStream { private def validateSingle(resource: ResourceState) = for { - jsonld <- IO.fromEither(resource.toAssembly) + jsonld <- resource.toAssembly schema <- fetchSchema(Latest(resource.schema.iri), resource.schemaProject) _ <- validateResource(jsonld, schema).adaptErr { case r: ResourceRejection => FailureReason("ValidateSchema", r) diff --git a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala index 3ba1511b07..338a8a6355 100644 --- a/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala +++ b/delta/sdk/src/main/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/Schema.scala @@ -2,6 +2,7 @@ package ch.epfl.bluebrain.nexus.delta.sdk.schemas.model import cats.data.NonEmptyList import cats.effect.IO +import cats.syntax.all._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode.Iri import ch.epfl.bluebrain.nexus.delta.rdf.Triple.Triple @@ -38,7 +39,6 @@ import io.circe.{Encoder, Json} * @param expanded * the expanded JSON-LD representation of the schema with the imports resolutions applied */ -@SuppressWarnings(Array("OptionGet")) final case class Schema( id: Iri, project: ProjectRef, @@ -51,17 +51,11 @@ final case class Schema( /** * the shacl shapes of the schema */ - // It is fine to do it unsafely since we have already computed the graph on evaluation previously in order to validate the schema. - @transient - lazy val shapes: Graph = graph(_.contains(nxv.Schema)) + def shapes: IO[Graph] = graph(_.contains(nxv.Schema)) - /** - * the Graph representation of the imports that are ontologies - */ - @transient - lazy val ontologies: Graph = graph(types => types.contains(owl.Ontology) && !types.contains(nxv.Schema)) + def ontologies: IO[Graph] = graph(types => types.contains(owl.Ontology) && !types.contains(nxv.Schema)) - private def graph(filteredTypes: Set[Iri] => Boolean): Graph = { + private def graph(filteredTypes: Set[Iri] => Boolean): IO[Graph] = { implicit val api: JsonLdApi = JsonLdJavaApi.lenient val init: (Set[IriOrBNode], Vector[ExpandedJsonLd]) = (Set.empty[IriOrBNode], Vector.empty[ExpandedJsonLd]) val (_, filtered) = expanded.foldLeft(init) { @@ -72,8 +66,11 @@ final case class Schema( updatedSeen -> updatedAcc case ((seen, acc), _) => seen -> acc } - val triples = filtered.map(_.toGraph.toOption.get).foldLeft(Set.empty[Triple])((acc, g) => acc ++ g.triples) - Graph.empty(id).add(triples) + filtered + .foldLeftM(Set.empty[Triple]) { (acc, expanded) => + expanded.toGraph.map { g => acc ++ g.triples } + } + .map { triples => Graph.empty(id).add(triples) } } def metadata: Metadata = Metadata(tags.tags) diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourceInstanceFixture.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourceInstanceFixture.scala index 758226aa23..63227a5847 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourceInstanceFixture.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ResourceInstanceFixture.scala @@ -1,5 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.sdk.resources +import cats.effect.unsafe.implicits._ import ch.epfl.bluebrain.nexus.delta.rdf.IriOrBNode import ch.epfl.bluebrain.nexus.delta.rdf.Vocabulary.nxv import ch.epfl.bluebrain.nexus.delta.rdf.graph.Graph @@ -70,7 +71,7 @@ trait ResourceInstanceFixture extends CirceLiteral { val graph: Graph = { implicit val jsonldApi: JsonLdApi = JsonLdJavaApi.lenient - expanded.toGraph.toTry.get + expanded.toGraph.unsafeRunSync() } } diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResourceSuite.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResourceSuite.scala index 6fb93ada7a..100d7204f4 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResourceSuite.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/resources/ValidateResourceSuite.scala @@ -68,7 +68,7 @@ class ValidateResourceSuite extends NexusSuite { for { patchedSource <- sourceWithId(id, patchSource) expanded <- ExpandedJsonLd(patchedSource) - graph <- IO.fromEither(expanded.toGraph) + graph <- expanded.toGraph } yield JsonLdAssembly(id, patchedSource, CompactedJsonLd.empty, expanded, graph, Set.empty) } diff --git a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaSuite.scala b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaSuite.scala index da76badf19..9bff82e963 100644 --- a/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaSuite.scala +++ b/delta/sdk/src/test/scala/ch/epfl/bluebrain/nexus/delta/sdk/schemas/model/SchemaSuite.scala @@ -1,7 +1,6 @@ package ch.epfl.bluebrain.nexus.delta.sdk.schemas.model import cats.data.NonEmptyList -import cats.effect.IO import ch.epfl.bluebrain.nexus.delta.rdf.jsonld.ExpandedJsonLd import ch.epfl.bluebrain.nexus.delta.rdf.syntax._ import ch.epfl.bluebrain.nexus.delta.sdk.model.Tags @@ -17,15 +16,16 @@ class SchemaSuite extends NexusSuite with Fixtures { for { entitySource <- loader.jsonContentOf("schemas/entity.json") entityExpanded <- ExpandedJsonLd(jsonContentOf("schemas/entity-expanded.json")) - entityExpandedGraphSize <- IO.fromEither(entityExpanded.toGraph.map(_.getDefaultGraphSize)) + entityExpandedGraphSize <- entityExpanded.toGraph.map(_.getDefaultGraphSize) entityCompacted <- entityExpanded.toCompacted(entitySource.topContextValueOrEmpty) licenseExpanded <- ExpandedJsonLd(jsonContentOf("schemas/license-expanded.json")) - licenseExpandedGraphSize <- IO.fromEither(licenseExpanded.toGraph.map(_.getDefaultGraphSize)) + licenseExpandedGraphSize <- licenseExpanded.toGraph.map(_.getDefaultGraphSize) + id = iri"https://neuroshapes.org/commons/entity" + expandeds = NonEmptyList.of(entityExpanded, licenseExpanded, entityExpanded) + schema = Schema(id, project, Tags.empty, entitySource, entityCompacted, expandeds) + shapes <- schema.shapes } yield { - val id = iri"https://neuroshapes.org/commons/entity" - val expandeds = NonEmptyList.of(entityExpanded, licenseExpanded, entityExpanded) - val schema = Schema(id, project, Tags.empty, entitySource, entityCompacted, expandeds) - assertEquals(schema.shapes.getDefaultGraphSize, entityExpandedGraphSize + licenseExpandedGraphSize) + assertEquals(shapes.getDefaultGraphSize, entityExpandedGraphSize + licenseExpandedGraphSize) } }