diff --git a/build.sbt b/build.sbt index e729d8e..12f7f03 100644 --- a/build.sbt +++ b/build.sbt @@ -6,7 +6,7 @@ resolvers += "Sonatype OSS Snapshots" at "https://s01.oss.sonatype.org/content/repositories/snapshots" lazy val jenaV = "5.3.0" -lazy val jellyV = "2.10.3" +lazy val jellyV = "3.0.0" addCommandAlias("fixAll", "scalafixAll; scalafmtAll") @@ -35,7 +35,8 @@ lazy val root = (project in file(".")) "org.slf4j" % "slf4j-simple" % "2.0.17", "org.apache.jena" % "jena-core" % jenaV, "org.apache.jena" % "jena-arq" % jenaV, - "eu.ostrzyciel.jelly" %% "jelly-jena" % jellyV, + "eu.neverblink.jelly" % "jelly-jena" % jellyV, + "eu.neverblink.jelly" % "jelly-core-protos-google" % jellyV, "com.github.alexarchambault" %% "case-app" % "2.1.0-M30", "org.scalatest" %% "scalatest" % "3.2.19" % Test, "org.yaml" % "snakeyaml" % "2.4" % Test, diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/Version.scala b/src/main/scala/eu/neverblink/jelly/cli/command/Version.scala index 072392e..c9c75f7 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/Version.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/Version.scala @@ -21,7 +21,7 @@ object Version extends JellyCommand[VersionOptions]: val jenaV = BuildInfo.libraryDependencies .find(_.startsWith("org.apache.jena:jena-core:")).get.split(":")(2) val jellyV = BuildInfo.libraryDependencies - .find(_.startsWith("eu.ostrzyciel.jelly:jelly-jena:")).get.split(":")(2) + .find(_.startsWith("eu.neverblink.jelly:jelly-jena:")).get.split(":")(2) printLine(f""" |jelly-cli ${BuildInfo.version} |---------------------------------------------- diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala index 85c511f..42336a9 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala @@ -5,14 +5,18 @@ import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.rdf.util.* import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat.* import eu.neverblink.jelly.cli.util.args.IndexRange -import eu.ostrzyciel.jelly.convert.jena.JenaConverterFactory -import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamFrame -import org.apache.jena.graph.Triple +import eu.neverblink.jelly.convert.jena.JenaConverterFactory +import eu.neverblink.jelly.core.JellyOptions +import eu.neverblink.jelly.core.RdfHandler.AnyStatementHandler +import eu.neverblink.jelly.core.proto.v1.RdfStreamFrame +import eu.neverblink.jelly.core.proto.google.v1 as google +import org.apache.jena.graph.{Node, Triple} import org.apache.jena.riot.Lang import org.apache.jena.riot.system.StreamRDFWriter import org.apache.jena.sparql.core.Quad import java.io.{InputStream, OutputStream} +import scala.jdk.CollectionConverters.* object RdfFromJellyPrint extends RdfCommandPrintUtil[RdfFormat.Writeable]: override val defaultFormat: RdfFormat = RdfFormat.NQuads @@ -89,12 +93,26 @@ object RdfFromJelly extends RdfSerDesCommand[RdfFromJellyOptions, RdfFormat.Writ val writer = StreamRDFWriter.getWriterStream(outputStream, jenaLang) // Whether the output is active at this moment var outputEnabled = false - val decoder = JenaConverterFactory.anyStatementDecoder( + val handler = new AnyStatementHandler[Node] { + override def handleNamespace(prefix: String, namespace: Node): Unit = { + if outputEnabled then writer.prefix(prefix, namespace.getURI) + } + + override def handleTriple(subject: Node, predicate: Node, `object`: Node): Unit = { + if outputEnabled then writer.triple(Triple.create(subject, predicate, `object`)) + } + + override def handleQuad(subject: Node, predicate: Node, `object`: Node, graph: Node): Unit = { + if outputEnabled then writer.quad(Quad.create(graph, subject, predicate, `object`)) + } + } + + val decoder = JenaConverterFactory.getInstance().anyStatementDecoder( // Only pass on the namespaces to the writer if the output is enabled - namespaceHandler = (String, Node) => { - if outputEnabled then writer.prefix(String, Node.getURI) - }, + handler, + JellyOptions.DEFAULT_SUPPORTED_OPTIONS, ) + val inputFrames = takeFrames.end match case Some(end) => JellyUtil.iterateRdfStream(inputStream).take(end) case None => JellyUtil.iterateRdfStream(inputStream) @@ -102,17 +120,13 @@ object RdfFromJelly extends RdfSerDesCommand[RdfFromJellyOptions, RdfFormat.Writ for (frame, i) <- inputFrames.zipWithIndex do // If we are not yet in the output range, still fully parse the frame and update the decoder // state. We need this to decode the later frames correctly. - if i < startFrom then for row <- frame.rows do decoder.ingestRowFlat(row) + if i < startFrom then for row <- frame.getRows.asScala do decoder.ingestRow(row) else // TODO: write frame index as a comment here // https://github.com/Jelly-RDF/cli/issues/4 outputEnabled = true // We are in the output range, so we can start writing the output - for row <- frame.rows do - decoder.ingestRowFlat(row) match - case null => () - case t: Triple => writer.triple(t) - case q: Quad => writer.quad(q) + for row <- frame.getRows.asScala do decoder.ingestRow(row) writer.finish() /** This method reads the Jelly file, rewrites it to Jelly text and writes it to some output @@ -128,7 +142,7 @@ object RdfFromJelly extends RdfSerDesCommand[RdfFromJellyOptions, RdfFormat.Writ // we want to write a comment to the file before each frame val comment = f"# Frame $frameIndex\n" outputStream.write(comment.getBytes) - val frame = f.toProtoString + val frame = google.RdfStreamFrame.parseFrom(f.toByteArray).toString // the protoString is basically the jelly-txt format already outputStream.write(frame.getBytes) diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspect.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspect.scala index 28fc131..454a2ef 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspect.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspect.scala @@ -4,7 +4,9 @@ import caseapp.{ArgsName, ExtraName, HelpMessage, Recurse} import caseapp.core.RemainingArgs import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.rdf.util.{FrameInfo, JellyUtil, MetricsPrinter} -import eu.ostrzyciel.jelly.core.proto.v1.* +import eu.neverblink.jelly.core.proto.v1.* + +import scala.jdk.CollectionConverters.* import java.io.InputStream @HelpMessage( @@ -57,8 +59,11 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]: frame: RdfStreamFrame, frameIndex: Int, ): FrameInfo = - val metrics = new FrameInfo(frameIndex, frame.metadata) - frame.rows.foreach(r => metricsForRow(r, metrics)) + val metrics = new FrameInfo( + frameIndex, + frame.getMetadata.asScala.map(entry => entry.getKey -> entry.getValue).toMap, + ) + frame.getRows.asScala.foreach(r => metricsForRow(r, metrics)) metrics try { @@ -80,7 +85,7 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]: row: RdfStreamRow, metadata: FrameInfo, ): Unit = - row.row match { + row.getRow match { case r: RdfTriple => metadata.tripleCount += 1 case r: RdfQuad => metadata.quadCount += 1 case r: RdfNameEntry => metadata.nameCount += 1 @@ -102,9 +107,10 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]: */ private def checkOptions(headFrame: Option[RdfStreamFrame]): RdfStreamOptions = if headFrame.isEmpty then throw new RuntimeException("No frames in the stream.") - if headFrame.get.rows.isEmpty then throw new RuntimeException("No rows in the frame.") - val frameRows = headFrame.get.rows - frameRows.head.row match { + if headFrame.get.getRows.asScala.isEmpty then + throw new RuntimeException("No rows in the frame.") + val frameRows = headFrame.get.getRows.asScala + frameRows.head.getRow match { case r: RdfStreamOptions => r case _ => throw new RuntimeException("First row of the frame is not an options row.") } diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfSerDesCommand.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfSerDesCommand.scala index 29b3e8b..e14589c 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfSerDesCommand.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfSerDesCommand.scala @@ -7,7 +7,7 @@ import caseapp.* import eu.neverblink.jelly.cli.command.rdf.util.{RdfCommandPrintUtil, RdfFormat} import scala.reflect.TypeTest -import eu.ostrzyciel.jelly.core.{RdfProtoDeserializationError, RdfProtoSerializationError} +import eu.neverblink.jelly.core.{RdfProtoDeserializationError, RdfProtoSerializationError} import java.io.{InputStream, OutputStream} diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala index ce47dc3..2575771 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala @@ -1,12 +1,15 @@ package eu.neverblink.jelly.cli.command.rdf import caseapp.* +import com.google.protobuf.TextFormat import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.rdf.util.* import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat.* import eu.neverblink.jelly.cli.util.jena.riot.JellyStreamWriterGraphs -import eu.ostrzyciel.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage, JellyStreamWriter} -import eu.ostrzyciel.jelly.core.proto.v1.{LogicalStreamType, RdfStreamFrame, RdfStreamOptions} +import eu.neverblink.jelly.convert.jena.JenaConverterFactory +import eu.neverblink.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage, JellyStreamWriter} +import eu.neverblink.jelly.core.proto.google.v1 as google +import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamOptions} import org.apache.jena.riot.system.StreamRDFWriter import org.apache.jena.riot.{Lang, RDFParser, RIOT} @@ -102,25 +105,27 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable val jellyOpt = getOptions.jellySerializationOptions.asRdfStreamOptions // Configure the writer val jellyWriter = - if jellyOpt.physicalType.isGraphs then + if jellyOpt.getPhysicalType == PhysicalStreamType.GRAPHS then // GRAPHS JellyStreamWriterGraphs( - JellyFormatVariant( - // By default, set the logical stream type to FLAT_QUADS (this is what JellyStreamWriter - // in jelly-jena does for physical type QUADS). - opt = jellyOpt.withLogicalType( - if jellyOpt.logicalType.isUnspecified then LogicalStreamType.FLAT_QUADS - else jellyOpt.logicalType, - ), - frameSize = getOptions.rowsPerFrame, - enableNamespaceDeclarations = getOptions.enableNamespaceDeclarations, - delimited = getOptions.delimited, - ), + JellyFormatVariant + .builder() + .options( + jellyOpt.clone.setLogicalType( + if jellyOpt.getLogicalType == LogicalStreamType.UNSPECIFIED then + LogicalStreamType.FLAT_QUADS + else jellyOpt.getLogicalType, + ), + ) + .frameSize(getOptions.rowsPerFrame) + .enableNamespaceDeclarations(getOptions.enableNamespaceDeclarations) + .isDelimited(getOptions.delimited) + .build(), out = outputStream, ) else // TRIPLES or QUADS - if jellyOpt.physicalType.isUnspecified then + if jellyOpt.getPhysicalType == PhysicalStreamType.UNSPECIFIED then if !isQuietMode && isLogicalGrouped(jellyOpt) then printLine( "WARNING: Logical type setting ignored because physical type is not set. " + @@ -145,13 +150,14 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable ) else // If the physical type is specified, we can just construct the writer - val variant = JellyFormatVariant( - opt = jellyOpt, - frameSize = getOptions.rowsPerFrame, - enableNamespaceDeclarations = getOptions.enableNamespaceDeclarations, - delimited = getOptions.delimited, - ) - JellyStreamWriter(variant, outputStream) + val variant = JellyFormatVariant + .builder() + .options(jellyOpt) + .frameSize(getOptions.rowsPerFrame) + .enableNamespaceDeclarations(getOptions.enableNamespaceDeclarations) + .isDelimited(getOptions.delimited) + .build() + JellyStreamWriter(JenaConverterFactory.getInstance(), variant, outputStream) RDFParser.source(inputStream).lang(jenaLang).parse(jellyWriter) @@ -172,7 +178,7 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable Using.resource(InputStreamReader(inputStream)) { r1 => Using.resource(BufferedReader(r1)) { reader => jellyTextStreamAsFrames(reader) - .map(txt => RdfStreamFrame.fromAscii(txt)) + .map(txt => TextFormat.parse(txt, classOf[google.RdfStreamFrame])) .foreach(frame => { if getOptions.delimited then frame.writeDelimitedTo(outputStream) else frame.writeTo(outputStream) @@ -189,7 +195,7 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable private def isLogicalGrouped( jellyOpt: RdfStreamOptions, ): Boolean = - !(jellyOpt.logicalType.isFlatQuads || jellyOpt.logicalType.isFlatTriples || jellyOpt.logicalType.isUnspecified) + !(jellyOpt.getLogicalType == LogicalStreamType.FLAT_QUADS || jellyOpt.getLogicalType == LogicalStreamType.FLAT_TRIPLES || jellyOpt.getLogicalType == LogicalStreamType.UNSPECIFIED) /** Iterate over a Jelly text stream and return the frames as strings to be parsed. * @param reader diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscode.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscode.scala index 5730b47..4382d9d 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscode.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscode.scala @@ -3,11 +3,11 @@ package eu.neverblink.jelly.cli.command.rdf import caseapp.* import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.rdf.util.* -import eu.ostrzyciel.jelly.core.RdfProtoError -import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamOptions -import eu.ostrzyciel.jelly.core.{JellyOptions, ProtoTranscoder} +import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, RdfStreamOptions} +import eu.neverblink.jelly.core.{JellyOptions, JellyTranscoderFactory, RdfProtoTranscodingError} import java.io.{InputStream, OutputStream} +import scala.jdk.CollectionConverters.* @HelpMessage( "Quickly transcodes the input Jelly file into another Jelly file.\n" + @@ -44,7 +44,7 @@ object RdfTranscode extends JellyCommand[RdfTranscodeOptions]: val (inputStream, outputStream) = getIoStreamsFromOptions(remainingArgs.remaining.headOption, options.outputFile) try jellyToJelly(inputStream, outputStream, outOpt) - catch case e: RdfProtoError => throw JellyTranscodingError(e.getMessage) + catch case e: RdfProtoTranscodingError => throw JellyTranscodingError(e.getMessage) /** Transcodes the input Jelly stream into another Jelly stream. * @param inputStream @@ -61,20 +61,21 @@ object RdfTranscode extends JellyCommand[RdfTranscodeOptions]: ): Unit = val in = JellyUtil.iterateRdfStream(inputStream).buffered val head = in.head - if head.rows.isEmpty then throw CriticalException("Empty input stream") - if !head.rows.head.row.isOptions then + if head.getRows.asScala.isEmpty then throw CriticalException("Empty input stream") + if !head.getRows.asScala.head.hasOptions then throw CriticalException("First input row is not an options row") - val inOpt = head.rows.head.row.options + val inOpt = head.getRows.asScala.head.getOptions - val transcoder = ProtoTranscoder.fastMergingTranscoder( - supportedInputOptions = JellyOptions.defaultSupportedOptions, - outputOptions = outOpt.copy( + val transcoder = JellyTranscoderFactory.fastMergingTranscoder( + JellyOptions.DEFAULT_SUPPORTED_OPTIONS, + outOpt.clone() // There is no way to specify the physical type with options currently. // Just use the one from the input. - physicalType = inOpt.physicalType, - logicalType = - if outOpt.logicalType.isUnspecified then inOpt.logicalType else outOpt.logicalType, - ), + .setPhysicalType(inOpt.getPhysicalType) + .setLogicalType( + if outOpt.getLogicalType == LogicalStreamType.UNSPECIFIED then inOpt.getLogicalType + else outOpt.getLogicalType, + ), ) in.map(transcoder.ingestFrame) diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidate.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidate.scala index 5b0a647..72138d1 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidate.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidate.scala @@ -6,15 +6,17 @@ import eu.neverblink.jelly.cli.command.rdf.util.* import eu.neverblink.jelly.cli.util.args.IndexRange import eu.neverblink.jelly.cli.util.io.IoUtil import eu.neverblink.jelly.cli.util.jena.* -import eu.ostrzyciel.jelly.convert.jena.JenaConverterFactory -import eu.ostrzyciel.jelly.core.JellyOptions -import eu.ostrzyciel.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamOptions} -import org.apache.jena.graph.Triple +import eu.neverblink.jelly.convert.jena.JenaConverterFactory +import eu.neverblink.jelly.core.JellyOptions +import eu.neverblink.jelly.core.RdfHandler.AnyStatementHandler +import eu.neverblink.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamOptions} +import org.apache.jena.graph.{Node, Triple} import org.apache.jena.riot.RDFParser import org.apache.jena.riot.system.StreamRDFLib import org.apache.jena.sparql.core.Quad import scala.annotation.tailrec +import scala.jdk.CollectionConverters.* import scala.util.Using object RdfValidatePrint extends RdfCommandPrintUtil[RdfFormat.Jena]: @@ -110,13 +112,13 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]: throw CriticalException("Expected undelimited input, but the file was delimited") private def validateOptions(frames: Seq[RdfStreamFrame]): RdfStreamOptions = - if !frames.head.rows.head.row.isOptions then + if !frames.head.getRows.asScala.head.hasOptions then throw CriticalException("First row in the input stream does not contain stream options") - val streamOptions = frames.head.rows.head.row.options + val streamOptions = frames.head.getRows.asScala.head.getOptions // If we have expected options, we need to read and validate them val expectedOptions = getOptions.optionsFile.map { optionsFileName => val o = Using.resource(IoUtil.inputStream(optionsFileName)) { is => - JellyUtil.iterateRdfStream(is).next().rows.head.row.options + JellyUtil.iterateRdfStream(is).next().getRows.asScala.head.getOptions } if streamOptions != o then throw CriticalException( @@ -126,13 +128,13 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]: ) o } - if streamOptions.version <= 0 then + if streamOptions.getVersion <= 0 then throw CriticalException( "The version field in RdfStreamOptions is <= 0. This field MUST be set to a positive value.", ) JellyOptions.checkCompatibility( streamOptions, - expectedOptions.getOrElse(JellyOptions.defaultSupportedOptions), + expectedOptions.getOrElse(JellyOptions.DEFAULT_SUPPORTED_OPTIONS), ) streamOptions @@ -146,41 +148,52 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]: val jellyStreamConsumer = if maybeRdfComparison.isDefined then StreamRdfCollector() else StreamRDFLib.sinkNull() - val dec = JenaConverterFactory.anyStatementDecoder( - None, - (prefix, iri) => jellyStreamConsumer.prefix(prefix, iri.getURI), + + val startFrom = frameIndices.start.getOrElse(0) + var currentPosition = 0 + + val handler = new AnyStatementHandler[Node] { + override def handleNamespace(prefix: String, namespace: Node): Unit = + jellyStreamConsumer.prefix(prefix, namespace.getURI) + + override def handleTriple(subject: Node, predicate: Node, `object`: Node): Unit = { + val t = Triple.create(subject, predicate, `object`) + if !opt.getGeneralizedStatements && StatementUtils.isGeneralized(t) then + throw CriticalException(s"Unexpected generalized triple in frame $currentPosition: $t") + if !opt.getRdfStar && StatementUtils.isRdfStar(t) then + throw CriticalException(s"Unexpected RDF-star triple in frame $currentPosition: $t") + // Add the triple to the comparison set, if we are in the compare range + if currentPosition >= startFrom then jellyStreamConsumer.triple(t) + } + + override def handleQuad(subject: Node, predicate: Node, `object`: Node, graph: Node): Unit = { + val q = new Quad(graph, subject, predicate, `object`) + if !opt.getGeneralizedStatements && StatementUtils.isGeneralized(q) then + throw CriticalException(s"Unexpected generalized quad in frame $currentPosition: $q") + if !opt.getRdfStar && StatementUtils.isRdfStar(q) then + throw CriticalException(s"Unexpected RDF-star quad in frame $currentPosition: $q") + // Add the quad to the comparison set, if we are in the compare range + if currentPosition >= startFrom then jellyStreamConsumer.quad(q) + } + } + val dec = JenaConverterFactory.getInstance().anyStatementDecoder( + handler, + JellyOptions.DEFAULT_SUPPORTED_OPTIONS, ) val frames2 = frameIndices.end match case Some(end) => frames.take(end) case None => frames - val startFrom = frameIndices.start.getOrElse(0) + for (frame, i) <- frames2.zipWithIndex do - for row <- frame.rows do - if row.row.isOptions && row.row.options != opt then + for row <- frame.getRows.asScala do + if row.hasOptions && row.getOptions != opt then throw CriticalException( s"Later occurrence of stream options in frame $i does not match the first", ) // Push the stream frames through the decoder // This will catch most of the errors - dec.ingestRowFlat(row) match - case null => () - // Check if the stream really does not contain any RDF-star or generalized statements - // if it doesn't declare to use them. This is normally not checked by the decoder - // because it's too performance-costly. - case t: Triple => - if !opt.generalizedStatements && StatementUtils.isGeneralized(t) then - throw CriticalException(s"Unexpected generalized triple in frame $i: $t") - if !opt.rdfStar && StatementUtils.isRdfStar(t) then - throw CriticalException(s"Unexpected RDF-star triple in frame $i: $t") - // Add the triple to the comparison set, if we are in the compare range - if i >= startFrom then jellyStreamConsumer.triple(t) - case q: Quad => - if !opt.generalizedStatements && StatementUtils.isGeneralized(q) then - throw CriticalException(s"Unexpected generalized quad in frame $i: $q") - if !opt.rdfStar && StatementUtils.isRdfStar(q) then - throw CriticalException(s"Unexpected RDF-star quad in frame $i: $q") - // Add the quad to the comparison set, if we are in the compare range - if i >= startFrom then jellyStreamConsumer.quad(q) + currentPosition = i + dec.ingestRow(row) // Compare the Jelly data with the reference RDF data, if specified maybeRdfComparison.foreach { rdfComparison => val actual = jellyStreamConsumer.asInstanceOf[StreamRdfCollector] @@ -202,7 +215,7 @@ object RdfValidate extends JellyCommand[RdfValidateOptions]: frames: Seq[RdfStreamFrame], ): Seq[RdfStreamFrame] = if frames.isEmpty then throw CriticalException("Empty input stream") - else if frames.head.rows.isEmpty then + else if frames.head.getRows.isEmpty then // We want to accept empty frames in the stream, but not empty streams if frames.tail.isEmpty then throw CriticalException("All frames are empty") skipEmptyFrames(frames.tail) diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/JellyUtil.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/JellyUtil.scala index ad1ad7c..542cd52 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/JellyUtil.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/JellyUtil.scala @@ -1,7 +1,7 @@ package eu.neverblink.jelly.cli.command.rdf.util -import eu.ostrzyciel.jelly.core.IoUtils -import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamFrame +import eu.neverblink.jelly.core.utils.IoUtils +import eu.neverblink.jelly.core.proto.v1.RdfStreamFrame import java.io.InputStream @@ -23,17 +23,18 @@ object JellyUtil: */ def iterateRdfStreamWithDelimitingInfo( inputStream: InputStream, - ): (Boolean, Iterator[RdfStreamFrame]) = - IoUtils.autodetectDelimiting(inputStream) match - case (false, newIn) => - // Non-delimited Jelly file - // In this case, we can only read one frame - (false, Iterator(RdfStreamFrame.parseFrom(newIn))) - case (true, newIn) => - // Delimited Jelly file - // In this case, we can read multiple frames - ( - true, - Iterator.continually(RdfStreamFrame.parseDelimitedFrom(newIn)) - .takeWhile(_.isDefined).map(_.get), - ) + ): (Boolean, Iterator[RdfStreamFrame]) = { + val delimitingResponse = IoUtils.autodetectDelimiting(inputStream) + if delimitingResponse.isDelimited then + // Delimited Jelly file + // In this case, we can read multiple frames + ( + true, + Iterator.continually(RdfStreamFrame.parseDelimitedFrom(delimitingResponse.newInput)) + .takeWhile(_ != null), + ) + else + // Non-delimited Jelly file + // In this case, we can only read one frame + (false, Iterator(RdfStreamFrame.parseFrom(delimitingResponse.newInput))) + } diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/MetricsPrinter.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/MetricsPrinter.scala index 202528e..05287bb 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/MetricsPrinter.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/MetricsPrinter.scala @@ -3,9 +3,10 @@ package eu.neverblink.jelly.cli.command.rdf.util import com.google.protobuf.ByteString import eu.neverblink.jelly.cli.util.io.YamlDocBuilder import eu.neverblink.jelly.cli.util.io.YamlDocBuilder.* -import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamOptions +import eu.neverblink.jelly.core.proto.v1.RdfStreamOptions import java.io.OutputStream +import scala.language.postfixOps /** This class is used to store the metrics for a single frame */ @@ -94,15 +95,15 @@ object MetricsPrinter: options: RdfStreamOptions, ): YamlMap = YamlMap( - "stream_name" -> YamlString(options.streamName), - "physical_type" -> YamlEnum(options.physicalType.toString, options.physicalType.value), - "generalized_statements" -> YamlBool(options.generalizedStatements), - "rdf_star" -> YamlBool(options.rdfStar), - "max_name_table_size" -> YamlInt(options.maxNameTableSize), - "max_prefix_table_size" -> YamlInt(options.maxPrefixTableSize), - "max_datatype_table_size" -> YamlInt(options.maxDatatypeTableSize), - "logical_type" -> YamlEnum(options.logicalType.toString, options.logicalType.value), - "version" -> YamlInt(options.version), + "stream_name" -> YamlString(options.getStreamName), + "physical_type" -> YamlEnum(options.getPhysicalType.toString, options.getPhysicalTypeValue), + "generalized_statements" -> YamlBool(options.getGeneralizedStatements), + "rdf_star" -> YamlBool(options.getRdfStar), + "max_name_table_size" -> YamlInt(options.getMaxNameTableSize), + "max_prefix_table_size" -> YamlInt(options.getMaxPrefixTableSize), + "max_datatype_table_size" -> YamlInt(options.getMaxDatatypeTableSize), + "logical_type" -> YamlEnum(options.getLogicalType.toString, options.getLogicalTypeValue), + "version" -> YamlInt(options.getVersion), ) private def formatStatsIndex( diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfFormat.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfFormat.scala index 736dcd6..42cb8a2 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfFormat.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfFormat.scala @@ -1,6 +1,6 @@ package eu.neverblink.jelly.cli.command.rdf.util -import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage +import eu.neverblink.jelly.convert.jena.riot.JellyLanguage import org.apache.jena.riot.{Lang, RDFLanguages} sealed trait RdfFormat: diff --git a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfJellySerializationOptions.scala b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfJellySerializationOptions.scala index 2a10250..0b00d62 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfJellySerializationOptions.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/command/rdf/util/RdfJellySerializationOptions.scala @@ -2,8 +2,9 @@ package eu.neverblink.jelly.cli.command.rdf.util import caseapp.* import eu.neverblink.jelly.cli.InvalidArgument -import eu.ostrzyciel.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamOptions} -import eu.ostrzyciel.jelly.core.{JellyOptions, LogicalStreamTypeFactory} +import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamOptions} +import eu.neverblink.jelly.core.utils.LogicalStreamTypeUtils +import eu.neverblink.jelly.core.JellyOptions /** Options for serializing in Jelly-RDF */ case class RdfJellySerializationOptions( @@ -16,17 +17,17 @@ case class RdfJellySerializationOptions( @HelpMessage("Whether the stream may contain RDF-star statements. Default: true") `opt.rdfStar`: Boolean = true, @HelpMessage( - "Maximum size of the name lookup table. Default: " + JellyOptions.bigStrict.maxNameTableSize, + "Maximum size of the name lookup table. Default: " + JellyOptions.BIG_STRICT.getMaxNameTableSize, ) - `opt.maxNameTableSize`: Int = JellyOptions.bigStrict.maxNameTableSize, + `opt.maxNameTableSize`: Int = JellyOptions.BIG_STRICT.getMaxNameTableSize, @HelpMessage( - "Maximum size of the prefix lookup table. Default: " + JellyOptions.bigStrict.maxPrefixTableSize, + "Maximum size of the prefix lookup table. Default: " + JellyOptions.BIG_STRICT.getMaxPrefixTableSize, ) - `opt.maxPrefixTableSize`: Int = JellyOptions.bigStrict.maxPrefixTableSize, + `opt.maxPrefixTableSize`: Int = JellyOptions.BIG_STRICT.getMaxPrefixTableSize, @HelpMessage( - "Maximum size of the datatype lookup table. Default: " + JellyOptions.bigStrict.maxDatatypeTableSize, + "Maximum size of the datatype lookup table. Default: " + JellyOptions.BIG_STRICT.getMaxDatatypeTableSize, ) - `opt.maxDatatypeTableSize`: Int = JellyOptions.bigStrict.maxDatatypeTableSize, + `opt.maxDatatypeTableSize`: Int = JellyOptions.BIG_STRICT.getMaxDatatypeTableSize, @HelpMessage( "Physical stream type. One of: TRIPLES, QUADS, GRAPHS. " + "Default: either TRIPLES or QUADS, depending on the input format.", @@ -50,7 +51,9 @@ case class RdfJellySerializationOptions( "https://w3id.org/stax/ontology#" + wordSeq.mkString + "Stream" case _ => "" // invalid IRI, we'll catch it in the next step } - val logicalType = logicalIri.flatMap(LogicalStreamTypeFactory.fromOntologyIri) + val logicalType = logicalIri.flatMap({ iri => + Option(LogicalStreamTypeUtils.fromOntologyIri(iri)) + }) if logicalIri.isDefined && logicalType.isEmpty then throw InvalidArgument( "--opt.logical-type", @@ -68,13 +71,12 @@ case class RdfJellySerializationOptions( Some("Physical type must be one of: TRIPLES, QUADS, GRAPHS"), ) case None => PhysicalStreamType.UNSPECIFIED - RdfStreamOptions( - streamName = `opt.streamName`, - generalizedStatements = `opt.generalizedStatements`, - rdfStar = `opt.rdfStar`, - maxNameTableSize = `opt.maxNameTableSize`, - maxPrefixTableSize = `opt.maxPrefixTableSize`, - maxDatatypeTableSize = `opt.maxDatatypeTableSize`, - physicalType = physicalType, - logicalType = logicalType.getOrElse(LogicalStreamType.UNSPECIFIED), - ) + RdfStreamOptions.newInstance() + .setStreamName(`opt.streamName`) + .setGeneralizedStatements(`opt.generalizedStatements`) + .setRdfStar(`opt.rdfStar`) + .setMaxNameTableSize(`opt.maxNameTableSize`) + .setMaxPrefixTableSize(`opt.maxPrefixTableSize`) + .setMaxDatatypeTableSize(`opt.maxDatatypeTableSize`) + .setPhysicalType(physicalType) + .setLogicalType(logicalType.getOrElse(LogicalStreamType.UNSPECIFIED)) diff --git a/src/main/scala/eu/neverblink/jelly/cli/util/jena/OrderedRdfCompare.scala b/src/main/scala/eu/neverblink/jelly/cli/util/jena/OrderedRdfCompare.scala index 1b7c5a6..0f9ab4e 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/util/jena/OrderedRdfCompare.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/util/jena/OrderedRdfCompare.scala @@ -1,7 +1,7 @@ package eu.neverblink.jelly.cli.util.jena import eu.neverblink.jelly.cli.CriticalException -import eu.ostrzyciel.jelly.core.NamespaceDeclaration +import eu.neverblink.jelly.core.NamespaceDeclaration import org.apache.jena.graph.{Node, Triple} import org.apache.jena.sparql.core.Quad diff --git a/src/main/scala/eu/neverblink/jelly/cli/util/jena/RdfElement.scala b/src/main/scala/eu/neverblink/jelly/cli/util/jena/RdfElement.scala index 6960b2b..d6a5f5a 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/util/jena/RdfElement.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/util/jena/RdfElement.scala @@ -1,6 +1,6 @@ package eu.neverblink.jelly.cli.util.jena -import eu.ostrzyciel.jelly.core.NamespaceDeclaration +import eu.neverblink.jelly.core.NamespaceDeclaration import org.apache.jena.graph.Triple import org.apache.jena.sparql.core.Quad diff --git a/src/main/scala/eu/neverblink/jelly/cli/util/jena/StreamRdfCollector.scala b/src/main/scala/eu/neverblink/jelly/cli/util/jena/StreamRdfCollector.scala index 9ef287e..c67edf2 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/util/jena/StreamRdfCollector.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/util/jena/StreamRdfCollector.scala @@ -1,6 +1,6 @@ package eu.neverblink.jelly.cli.util.jena -import eu.ostrzyciel.jelly.core.NamespaceDeclaration +import eu.neverblink.jelly.core.NamespaceDeclaration import org.apache.jena.graph.Triple import org.apache.jena.riot.system.StreamRDF import org.apache.jena.sparql.core.Quad diff --git a/src/main/scala/eu/neverblink/jelly/cli/util/jena/riot/JellyStreamWriterGraphs.scala b/src/main/scala/eu/neverblink/jelly/cli/util/jena/riot/JellyStreamWriterGraphs.scala index 3fa0ce0..8987a4c 100644 --- a/src/main/scala/eu/neverblink/jelly/cli/util/jena/riot/JellyStreamWriterGraphs.scala +++ b/src/main/scala/eu/neverblink/jelly/cli/util/jena/riot/JellyStreamWriterGraphs.scala @@ -1,15 +1,15 @@ package eu.neverblink.jelly.cli.util.jena.riot -import eu.ostrzyciel.jelly.convert.jena.JenaConverterFactory -import eu.ostrzyciel.jelly.convert.jena.riot.JellyFormatVariant -import eu.ostrzyciel.jelly.core.ProtoEncoder -import eu.ostrzyciel.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamRow} -import org.apache.jena.graph.{Node, Triple} +import eu.neverblink.jelly.convert.jena.JenaConverterFactory +import eu.neverblink.jelly.convert.jena.riot.JellyFormatVariant +import eu.neverblink.jelly.core.ProtoEncoder +import eu.neverblink.jelly.core.memory.RowBuffer +import eu.neverblink.jelly.core.proto.v1.RdfStreamFrame +import org.apache.jena.graph.{Node, NodeFactory, Triple} import org.apache.jena.riot.system.StreamRDF import org.apache.jena.sparql.core.Quad import java.io.OutputStream -import scala.collection.mutable.ListBuffer /** A stream writer that writes RDF data in Jelly format, using the GRAPHS physical stream type. * @@ -17,14 +17,14 @@ import scala.collection.mutable.ListBuffer * is needed to support the remaining GRAPHS physical stream type. */ final class JellyStreamWriterGraphs(opt: JellyFormatVariant, out: OutputStream) extends StreamRDF: - private val buffer: ListBuffer[RdfStreamRow] = new ListBuffer[RdfStreamRow]() + private val buffer = RowBuffer.newLazyImmutable() // We don't set any options here – it is the responsibility of the caller to set // a valid stream type (GRAPHS). - private val encoder = JenaConverterFactory.encoder( - ProtoEncoder.Params( - opt.opt, - opt.enableNamespaceDeclarations, - Some(buffer), + private val encoder = JenaConverterFactory.getInstance().encoder( + ProtoEncoder.Params.of( + opt.getOptions, + opt.isEnableNamespaceDeclarations, + buffer, ), ) private var currentGraph: Node = null @@ -34,56 +34,62 @@ final class JellyStreamWriterGraphs(opt: JellyFormatVariant, out: OutputStream) override def triple(triple: Triple): Unit = handleGraph(Quad.defaultGraphIRI) - encoder.addTripleStatement(triple) - if opt.delimited && buffer.size >= opt.frameSize then flushBuffer() + encoder.handleTriple(triple.getSubject, triple.getPredicate, triple.getObject) + if opt.isDelimited && buffer.size >= opt.getFrameSize then flushBuffer() override def quad(quad: Quad): Unit = handleGraph(quad.getGraph) - encoder.addTripleStatement( + encoder.handleTriple( quad.getSubject, quad.getPredicate, quad.getObject, ) - if opt.delimited && buffer.size >= opt.frameSize then flushBuffer() + if opt.isDelimited && buffer.size >= opt.getFrameSize then flushBuffer() // Not supported override def base(base: String): Unit = () override def prefix(prefix: String, iri: String): Unit = - if opt.enableNamespaceDeclarations then - encoder.declareNamespace(prefix, iri) - if opt.delimited && buffer.size >= opt.frameSize then flushBuffer() + if opt.isEnableNamespaceDeclarations then + encoder.handleNamespace(prefix, NodeFactory.createURI(iri)) + if opt.isDelimited && buffer.size >= opt.getFrameSize then flushBuffer() private def handleGraph(graph: Node): Unit = if currentGraph == null then // First graph in the stream - encoder.startGraph(graph) + encoder.handleGraphStart(graph) currentGraph = graph else if Quad.isDefaultGraph(currentGraph) then if !Quad.isDefaultGraph(graph) then // We are switching default -> named - encoder.endGraph() - encoder.startGraph(graph) + encoder.handleGraphEnd() + encoder.handleGraphStart(graph) currentGraph = graph else if Quad.isDefaultGraph(graph) || graph != currentGraph then // We are switching named -> named or named -> default - encoder.endGraph() - encoder.startGraph(graph) + encoder.handleGraphEnd() + encoder.handleGraphStart(graph) currentGraph = graph // Flush the buffer and finish the stream override def finish(): Unit = if currentGraph != null then - encoder.endGraph() + encoder.handleGraphEnd() currentGraph = null - if !opt.delimited then + if !opt.isDelimited then // Non-delimited variant – whole stream in one frame - val frame = RdfStreamFrame(rows = buffer.toList) + val frame = RdfStreamFrame.newInstance() + buffer.forEach { row => + frame.addRows(row) + } frame.writeTo(out) - else if buffer.nonEmpty then flushBuffer() + else if !buffer.isEmpty then flushBuffer() out.flush() private def flushBuffer(): Unit = - val frame = RdfStreamFrame(rows = buffer.toList) + val frame = RdfStreamFrame.newInstance() + buffer.forEach { row => + frame.addRows(row) + } frame.writeDelimitedTo(out) buffer.clear() diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala index 9bfb281..3933bb7 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/DataGenHelper.scala @@ -1,7 +1,7 @@ package eu.neverblink.jelly.cli.command.helpers -import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage -import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamFrame +import eu.neverblink.jelly.convert.jena.riot.JellyLanguage +import eu.neverblink.jelly.core.proto.google.v1 as google import org.apache.jena.query.{Dataset, DatasetFactory} import org.apache.jena.rdf.model.{Model, ModelFactory, ResourceFactory} import org.apache.jena.riot.{Lang, RDFDataMgr, RDFLanguages} @@ -75,8 +75,8 @@ object DataGenHelper: */ def generateJellyText(nTriples: Int): String = val bytes = generateJellyBytes(nTriples) - val frame = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(bytes)) - frame.get.toProtoString + val frame = google.RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(bytes)) + frame.toString /** This method generates a Jelly byte input stream with nTriples * @param nTriples diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/RdfAdapter.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/RdfAdapter.scala new file mode 100644 index 0000000..18b96bb --- /dev/null +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/RdfAdapter.scala @@ -0,0 +1,244 @@ +package eu.neverblink.jelly.cli.command.helpers + +import com.google.protobuf.ByteString +import eu.neverblink.jelly.core.proto.v1.* +import eu.neverblink.jelly.core.proto.v1.RdfStreamFrame.MetadataEntry + +import scala.jdk.CollectionConverters.* + +object RdfAdapter: + + def rdfNameEntry(id: Int, value: String): RdfNameEntry = + RdfNameEntry.newInstance() + .setId(id) + .setValue(value) + + def rdfNameEntry(value: String): RdfNameEntry = + RdfNameEntry.newInstance() + .setValue(value) + + def rdfPrefixEntry(id: Int, value: String): RdfPrefixEntry = + RdfPrefixEntry.newInstance() + .setId(id) + .setValue(value) + + def rdfDatatypeEntry(id: Int, value: String): RdfDatatypeEntry = + RdfDatatypeEntry.newInstance() + .setId(id) + .setValue(value) + + def rdfNamespaceDeclaration(name: String, value: RdfIri): RdfNamespaceDeclaration = + RdfNamespaceDeclaration.newInstance() + .setName(name) + .setValue(value) + + def rdfLiteral(lex: String): RdfLiteral = + RdfLiteral.newInstance() + .setLex(lex) + + def rdfLiteral(lex: String, langtag: String): RdfLiteral = + RdfLiteral.newInstance() + .setLex(lex) + .setLangtag(langtag) + + def rdfLiteral(lex: String, datatype: Int): RdfLiteral = + RdfLiteral.newInstance() + .setLex(lex) + .setDatatype(datatype) + + def rdfIri(prefixId: Int, nameId: Int): RdfIri = + RdfIri.newInstance() + .setNameId(nameId) + .setPrefixId(prefixId) + + def rdfStreamFrame( + rows: Seq[RdfStreamRow], + metadata: Map[String, ByteString] = Map.empty, + ): RdfStreamFrame = + val frame = RdfStreamFrame.newInstance() + frame.getRows.addAll(rows.asJava) + metadata.foreach((key, value) => + frame.getMetadata.add( + MetadataEntry.newInstance().setKey(key).setValue(value), + ), + ) + frame + + type RdfStreamRowValue = + RdfStreamOptions | RdfTriple | RdfQuad | RdfGraphStart | RdfGraphEnd | RdfNamespaceDeclaration | + RdfNameEntry | RdfPrefixEntry | RdfDatatypeEntry | Null + + def rdfStreamRowFromValue(value: RdfStreamRowValue): RdfStreamRow = + value match { + case v: RdfStreamOptions => rdfStreamRow(v) + case v: RdfTriple => rdfStreamRow(v) + case v: RdfQuad => rdfStreamRow(v) + case v: RdfGraphStart => rdfStreamRow(v) + case v: RdfGraphEnd => rdfStreamRow(v) + case v: RdfNamespaceDeclaration => rdfStreamRow(v) + case v: RdfNameEntry => rdfStreamRow(v) + case v: RdfPrefixEntry => rdfStreamRow(v) + case v: RdfDatatypeEntry => rdfStreamRow(v) + } + + def rdfStreamRow(row: RdfNameEntry): RdfStreamRow = + RdfStreamRow.newInstance() + .setName(row) + + def rdfStreamRow(row: RdfPrefixEntry): RdfStreamRow = + RdfStreamRow.newInstance() + .setPrefix(row) + + def rdfStreamRow(row: RdfStreamOptions): RdfStreamRow = + RdfStreamRow.newInstance() + .setOptions(row) + + def rdfStreamRow(row: RdfTriple): RdfStreamRow = + RdfStreamRow.newInstance() + .setTriple(row) + + def rdfStreamRow(row: RdfQuad): RdfStreamRow = + RdfStreamRow.newInstance() + .setQuad(row) + + def rdfStreamRow(row: RdfGraphStart): RdfStreamRow = + RdfStreamRow.newInstance() + .setGraphStart(row) + + def rdfStreamRow(row: RdfGraphEnd): RdfStreamRow = + RdfStreamRow.newInstance() + .setGraphEnd(row) + + def rdfStreamRow(row: RdfNamespaceDeclaration): RdfStreamRow = + RdfStreamRow.newInstance() + .setNamespace(row) + + def rdfStreamRow(row: RdfDatatypeEntry): RdfStreamRow = + RdfStreamRow.newInstance() + .setDatatype(row) + + def rdfStreamRow(): RdfStreamRow = + RdfStreamRow.newInstance() + + def rdfStreamOptions( + streamName: String = "", + maxNameTableSize: Int = 1, + maxPrefixTableSize: Int = 1, + maxDatatypeTableSize: Int = 1, + version: Int = 1, + physicalType: PhysicalStreamType = PhysicalStreamType.UNSPECIFIED, + logicalType: LogicalStreamType = LogicalStreamType.UNSPECIFIED, + ): RdfStreamOptions = + RdfStreamOptions.newInstance() + .setStreamName(streamName) + .setMaxNameTableSize(maxNameTableSize) + .setMaxPrefixTableSize(maxPrefixTableSize) + .setMaxDatatypeTableSize(maxDatatypeTableSize) + .setVersion(version) + .setPhysicalType(physicalType) + .setLogicalType(logicalType) + + def rdfDefaultGraph(): RdfDefaultGraph = + RdfDefaultGraph.EMPTY + + type RdfGraphValue = + RdfIri | String | RdfDefaultGraph | RdfLiteral | Null + + def rdfGraphStart(graph: RdfGraphValue): RdfGraphStart = { + val graphStart = RdfGraphStart.newInstance() + + graph match + case g: RdfIri => graphStart.setGIri(g) + case g: String => graphStart.setGBnode(g) + case g: RdfDefaultGraph => graphStart.setGDefaultGraph(g) + case g: RdfLiteral => graphStart.setGLiteral(g) + + graphStart + } + + def rdfGraphStart(): RdfGraphStart = + RdfGraphStart.newInstance() + + def rdfGraphEnd(): RdfGraphEnd = + RdfGraphEnd.EMPTY + + def rdfQuad( + subject: RdfSpoValue, + predicate: RdfSpoValue, + `object`: RdfSpoValue, + graph: RdfGraphValue = null, + ): RdfQuad = { + var quad = RdfQuad.newInstance() + + if subject != null then + subject match + case s: RdfIri => quad = quad.setSIri(s) + case s: String => quad = quad.setSBnode(s) + case s: RdfLiteral => quad = quad.setSLiteral(s) + case s: RdfTriple => quad = quad.setSTripleTerm(s) + + if predicate != null then + predicate match + case p: RdfIri => quad = quad.setPIri(p) + case p: String => quad = quad.setPBnode(p) + case p: RdfLiteral => quad = quad.setPLiteral(p) + case p: RdfTriple => quad = quad.setPTripleTerm(p) + + if `object` != null then + `object` match + case o: RdfIri => quad = quad.setOIri(o) + case o: String => quad = quad.setOBnode(o) + case o: RdfLiteral => quad = quad.setOLiteral(o) + case o: RdfTriple => quad = quad.setOTripleTerm(o) + + if graph != null then + graph match + case g: RdfIri => quad = quad.setGIri(g) + case g: String => quad = quad.setGBnode(g) + case g: RdfDefaultGraph => quad = quad.setGDefaultGraph(g) + case g: RdfLiteral => quad = quad.setGLiteral(g) + + quad + } + + type RdfSpoValue = + RdfIri | String | RdfLiteral | RdfTriple | Null + + def rdfTriple(subject: RdfSpoValue, predicate: RdfSpoValue, `object`: RdfSpoValue): RdfTriple = { + var triple = RdfTriple.newInstance() + + if subject != null then + subject match + case s: RdfIri => triple = triple.setSIri(s) + case s: String => triple = triple.setSBnode(s) + case s: RdfLiteral => triple = triple.setSLiteral(s) + case s: RdfTriple => triple = triple.setSTripleTerm(s) + + if predicate != null then + predicate match + case p: RdfIri => triple = triple.setPIri(p) + case p: String => triple = triple.setPBnode(p) + case p: RdfLiteral => triple = triple.setPLiteral(p) + case p: RdfTriple => triple = triple.setPTripleTerm(p) + + if `object` != null then + `object` match + case o: RdfIri => triple = triple.setOIri(o) + case o: String => triple = triple.setOBnode(o) + case o: RdfLiteral => triple = triple.setOLiteral(o) + case o: RdfTriple => triple = triple.setOTripleTerm(o) + + triple + } + + def extractRdfStreamRow(row: RdfStreamRow): RdfStreamRowValue = + if row.hasOptions then row.getOptions + else if row.hasName then row.getName + else if row.hasPrefix then row.getPrefix + else if row.hasTriple then row.getTriple + else if row.hasQuad then row.getQuad + else if row.hasGraphStart then row.getGraphStart + else if row.hasGraphEnd then row.getGraphEnd + else if row.hasNamespace then row.getNamespace + else if row.hasDatatype then row.getDatatype + else null diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala index 47158d6..2352bd2 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala @@ -1,9 +1,10 @@ package eu.neverblink.jelly.cli.command.helpers import eu.neverblink.jelly.cli.util.jena.riot.CliRiot -import eu.ostrzyciel.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage} +import eu.neverblink.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage} +import eu.neverblink.jelly.core.JellyOptions import org.apache.jena.graph.Triple -import org.apache.jena.riot.{Lang, RDFDataMgr, RDFFormat, RDFLanguages} +import org.apache.jena.riot.{Lang, RDFDataMgr, RDFFormat, RDFLanguages, RDFWriter, RIOT} import org.apache.jena.sparql.graph.GraphFactory import org.apache.jena.sys.JenaSystem import org.scalatest.BeforeAndAfterAll @@ -101,10 +102,21 @@ trait TestFixtureHelper extends BeforeAndAfterAll: val tempFile = Files.createTempFile(tmpDir, randomUUID.toString, f".${extension}") val customFormat = new RDFFormat( JellyLanguage.JELLY, - JellyFormatVariant(frameSize = frameSize), + JellyFormatVariant.builder.frameSize(frameSize).build(), + ) + + val writerContext = RIOT.getContext.copy.set( + JellyLanguage.SYMBOL_STREAM_OPTIONS, + JellyOptions.SMALL_ALL_FEATURES.clone().setStreamName("Stream"), ) val model = DataGenHelper.generateTripleModel(testCardinality) - RDFDataMgr.write(new FileOutputStream(tempFile.toFile), model, customFormat) + + RDFWriter.create() + .format(customFormat) + .context(writerContext) + .source(model) + .build() + .output(new FileOutputStream(tempFile.toFile)) try { testCode(tempFile.toString) } finally { tempFile.toFile.delete() } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJellySpec.scala index 55a263f..1a97cad 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJellySpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJellySpec.scala @@ -4,8 +4,8 @@ import com.google.protobuf.InvalidProtocolBufferException import eu.neverblink.jelly.cli.* import eu.neverblink.jelly.cli.command.helpers.* import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat -import eu.ostrzyciel.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamFrame} -import eu.ostrzyciel.jelly.core.{JellyOptions, ProtoTranscoder} +import eu.neverblink.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamFrame} +import eu.neverblink.jelly.core.{JellyOptions, JellyTranscoderFactory} import org.apache.jena.riot.RDFLanguages import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec @@ -23,13 +23,12 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with TestFixtureHelper: // Make a test input stream with 10 frames... all are the same, but it doesn't matter private val input10Frames: Array[Byte] = { val j1 = DataGenHelper.generateJellyBytes(testCardinality) - val f1 = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(j1)).get + val f1 = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(j1)) val os = ByteArrayOutputStream() // Need to use the transcoder to make sure the lookup IDs are correct - val transcoder = ProtoTranscoder.fastMergingTranscoderUnsafe( - outputOptions = JellyOptions.bigGeneralized.withPhysicalType( - PhysicalStreamType.TRIPLES, - ), + val transcoder = JellyTranscoderFactory.fastMergingTranscoderUnsafe( + JellyOptions.BIG_GENERALIZED.clone + .setPhysicalType(PhysicalStreamType.TRIPLES), ) for _ <- 0 until 10 do transcoder.ingestFrame(f1).writeDelimitedTo(os) os.toByteArray @@ -147,7 +146,7 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with TestFixtureHelper: val outString = """# Frame 0 |rows { | options { - | stream_name: "" + | stream_name: "Stream" | physical_type: PHYSICAL_STREAM_TYPE_TRIPLES | generalized_statements: true | rdf_star: true @@ -182,7 +181,7 @@ class RdfFromJellySpec extends AnyWordSpec with Matchers with TestFixtureHelper: """# Frame 0 |rows { | options { - | stream_name: "" + | stream_name: "Stream" | physical_type: PHYSICAL_STREAM_TYPE_TRIPLES | generalized_statements: true | rdf_star: true diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspectSpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspectSpec.scala index 5cf1a00..9d31a49 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspectSpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspectSpec.scala @@ -3,8 +3,8 @@ package eu.neverblink.jelly.cli.command.rdf import com.google.protobuf.ByteString import eu.neverblink.jelly.cli.{ExitException, InvalidJellyFile} import eu.neverblink.jelly.cli.command.helpers.TestFixtureHelper -import eu.ostrzyciel.jelly.core.JellyOptions -import eu.ostrzyciel.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamRow} +import eu.neverblink.jelly.core.JellyOptions +import eu.neverblink.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamRow} import scala.jdk.CollectionConverters.* import org.scalatest.matchers.should.Matchers @@ -74,10 +74,16 @@ class RdfInspectSpec extends AnyWordSpec with Matchers with TestFixtureHelper: ) "print frame metadata in --per-frame" in { - val inFrame = RdfStreamFrame( - rows = Seq(RdfStreamRow(JellyOptions.bigGeneralized)), - metadata = Map("key" -> ByteString.fromHex("1337ff")), - ) + val inFrame = RdfStreamFrame.newInstance() + .addRows( + RdfStreamRow.newInstance() + .setOptions(JellyOptions.BIG_GENERALIZED), + ) + .addMetadata( + RdfStreamFrame.MetadataEntry.newInstance() + .setKey("key") + .setValue(ByteString.fromHex("1337ff")), + ) val inBytes = inFrame.toByteArray RdfInspect.setStdIn(ByteArrayInputStream(inBytes)) val (out, err) = RdfInspect.runTestCommand(List("rdf", "inspect", "--per-frame")) diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJellySpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJellySpec.scala index 7aee84c..f6e3a6b 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJellySpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJellySpec.scala @@ -3,9 +3,10 @@ package eu.neverblink.jelly.cli.command.rdf import eu.neverblink.jelly.cli.command.helpers.{DataGenHelper, TestFixtureHelper} import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat import eu.neverblink.jelly.cli.* -import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage -import eu.ostrzyciel.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamFrame} -import eu.ostrzyciel.jelly.core.{IoUtils, JellyOptions} +import eu.neverblink.jelly.convert.jena.riot.JellyLanguage +import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamFrame} +import eu.neverblink.jelly.core.JellyOptions +import eu.neverblink.jelly.core.utils.IoUtils import org.apache.jena.rdf.model.{Model, ModelFactory} import org.apache.jena.riot.{RDFLanguages, RDFParser} import org.apache.jena.sparql.core.DatasetGraphFactory @@ -33,8 +34,7 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: def readJellyFile(inputStream: InputStream): Seq[RdfStreamFrame] = Using(inputStream) { content => Iterator.continually(RdfStreamFrame.parseDelimitedFrom(content)) - .takeWhile(_.nonEmpty) - .map(_.get) + .takeWhile(_ != null) .toSeq } match { case scala.util.Success(value) => value @@ -48,7 +48,7 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: RdfToJelly.runTestCommand(List("rdf", "to-jelly", f)) val bytes = RdfToJelly.getOutBytes // Make sure it's written in the delimited format - IoUtils.autodetectDelimiting(new ByteArrayInputStream(bytes))._1 should be(true) + IoUtils.autodetectDelimiting(new ByteArrayInputStream(bytes)).isDelimited should be(true) val content = translateJellyBack(ByteArrayInputStream(bytes)) content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) } @@ -118,8 +118,7 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: for gn <- ds.listGraphNodes().asScala do ds.getGraph(gn).size() should be(testCardinality) // Check the logical stream type -- should be the default one val frame = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(bytes)) - .get - frame.rows.head.row.options.logicalType should be(LogicalStreamType.FLAT_QUADS) + frame.getRows.asScala.head.getOptions.getLogicalType should be(LogicalStreamType.FLAT_QUADS) } "input stream to output stream, GRAPHS stream type, 5 RDF datasets" in { @@ -152,8 +151,7 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: for gn <- ds.listGraphNodes().asScala do ds.getGraph(gn).size() should be(testCardinality) // Check the logical stream type -- should be DATASETS val frame = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(outBytes)) - .get - frame.rows.head.row.options.logicalType should be(LogicalStreamType.DATASETS) + frame.getRows.asScala.head.getOptions.getLogicalType should be(LogicalStreamType.DATASETS) } "an input stream to file" in withEmptyJellyFile { j => @@ -187,15 +185,15 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: val content = translateJellyBack(new FileInputStream(j)) content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.streamName should be("testName") - opts.generalizedStatements should be(false) - opts.rdfStar should be(false) - opts.maxNameTableSize should be(100) - opts.maxPrefixTableSize should be(100) - opts.maxDatatypeTableSize should be(100) - opts.logicalType should be(LogicalStreamType.FLAT_QUADS) - opts.version should be(1) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getStreamName should be("testName") + opts.getGeneralizedStatements should be(false) + opts.getRdfStar should be(false) + opts.getMaxNameTableSize should be(100) + opts.getMaxPrefixTableSize should be(100) + opts.getMaxDatatypeTableSize should be(100) + opts.getLogicalType should be(LogicalStreamType.FLAT_QUADS) + opts.getVersion should be(1) } } @@ -215,15 +213,15 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: val content = translateJellyBack(new FileInputStream(j)) content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.streamName should be("") - opts.generalizedStatements should be(true) - opts.rdfStar should be(true) - opts.maxNameTableSize should be(JellyOptions.bigStrict.maxNameTableSize) - opts.maxPrefixTableSize should be(JellyOptions.bigStrict.maxPrefixTableSize) - opts.maxDatatypeTableSize should be(JellyOptions.bigStrict.maxDatatypeTableSize) - opts.logicalType should be(LogicalStreamType.FLAT_QUADS) - opts.version should be(1) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getStreamName should be("") + opts.getGeneralizedStatements should be(true) + opts.getRdfStar should be(true) + opts.getMaxNameTableSize should be(JellyOptions.BIG_STRICT.getMaxNameTableSize) + opts.getMaxPrefixTableSize should be(JellyOptions.BIG_STRICT.getMaxPrefixTableSize) + opts.getMaxDatatypeTableSize should be(JellyOptions.BIG_STRICT.getMaxDatatypeTableSize) + opts.getLogicalType should be(LogicalStreamType.FLAT_QUADS) + opts.getVersion should be(1) } } @@ -245,16 +243,16 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: val content = translateJellyBack(new FileInputStream(j)) content.containsAll(DataGenHelper.generateTripleModel(testCardinality).listStatements()) val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.streamName should be("") - opts.generalizedStatements should be(true) - opts.rdfStar should be(true) - opts.maxNameTableSize should be(JellyOptions.bigStrict.maxNameTableSize) - opts.maxPrefixTableSize should be(JellyOptions.bigStrict.maxPrefixTableSize) - opts.maxDatatypeTableSize should be(JellyOptions.bigStrict.maxDatatypeTableSize) - opts.physicalType should be(PhysicalStreamType.QUADS) - opts.logicalType should be(LogicalStreamType.DATASETS) - opts.version should be(1) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getStreamName should be("") + opts.getGeneralizedStatements should be(true) + opts.getRdfStar should be(true) + opts.getMaxNameTableSize should be(JellyOptions.BIG_STRICT.getMaxNameTableSize) + opts.getMaxPrefixTableSize should be(JellyOptions.BIG_STRICT.getMaxPrefixTableSize) + opts.getMaxDatatypeTableSize should be(JellyOptions.BIG_STRICT.getMaxDatatypeTableSize) + opts.getPhysicalType should be(PhysicalStreamType.QUADS) + opts.getLogicalType should be(LogicalStreamType.DATASETS) + opts.getVersion should be(1) } } @@ -278,7 +276,7 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: for frame <- frames do // The encoder may slightly overshoot the target if it needs to pack the lookup entries // together with the triple. - frame.rows.size should be <= 15 + frame.getRows.size should be <= 15 } } @@ -301,8 +299,8 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: // N-Quads. // TODO: test if the namespace declarations are preserved with Turtle or RDF/XML input. val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.version should be(2) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getVersion should be(2) } } @@ -319,10 +317,10 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: j, ), ) - val (delimited, is) = IoUtils.autodetectDelimiting(new FileInputStream(j)) - delimited should be(false) - val frame = RdfStreamFrame.parseFrom(is) - frame.rows.size should be > 0 + val delimitingResponse = IoUtils.autodetectDelimiting(new FileInputStream(j)) + delimitingResponse.isDelimited should be(false) + val frame = RdfStreamFrame.parseFrom(delimitingResponse.newInput) + frame.getRows.size should be > 0 } } } @@ -360,16 +358,18 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: DataGenHelper.generateTripleModel(testCardinality).listStatements(), ) val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.streamName should be("") - opts.generalizedStatements should be(true) - opts.rdfStar should be(true) - opts.maxNameTableSize should be(JellyOptions.bigStrict.maxNameTableSize) - opts.maxPrefixTableSize should be(JellyOptions.bigStrict.maxPrefixTableSize) - opts.maxDatatypeTableSize should be(JellyOptions.bigStrict.maxDatatypeTableSize) - opts.physicalType should be(PhysicalStreamType.TRIPLES) - opts.logicalType should be(LogicalStreamType.GRAPHS) - opts.version should be(1) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getStreamName should be("") + opts.getGeneralizedStatements should be(true) + opts.getRdfStar should be(true) + opts.getMaxNameTableSize should be(JellyOptions.BIG_STRICT.getMaxNameTableSize) + opts.getMaxPrefixTableSize should be(JellyOptions.BIG_STRICT.getMaxPrefixTableSize) + opts.getMaxDatatypeTableSize should be( + JellyOptions.BIG_STRICT.getMaxDatatypeTableSize, + ) + opts.getPhysicalType should be(PhysicalStreamType.TRIPLES) + opts.getLogicalType should be(LogicalStreamType.GRAPHS) + opts.getVersion should be(1) } }, jenaLang = RDFLanguages.NTRIPLES, @@ -394,15 +394,17 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: DataGenHelper.generateTripleModel(testCardinality).listStatements(), ) val frames = readJellyFile(new FileInputStream(j)) - val opts = frames.head.rows.head.row.options - opts.streamName should be("") - opts.generalizedStatements should be(true) - opts.rdfStar should be(true) - opts.maxNameTableSize should be(JellyOptions.bigStrict.maxNameTableSize) - opts.maxPrefixTableSize should be(JellyOptions.bigStrict.maxPrefixTableSize) - opts.maxDatatypeTableSize should be(JellyOptions.bigStrict.maxDatatypeTableSize) - opts.logicalType should be(LogicalStreamType.FLAT_TRIPLES) - opts.version should be(1) + val opts = frames.head.getRows.asScala.head.getOptions + opts.getStreamName should be("") + opts.getGeneralizedStatements should be(true) + opts.getRdfStar should be(true) + opts.getMaxNameTableSize should be(JellyOptions.BIG_STRICT.getMaxNameTableSize) + opts.getMaxPrefixTableSize should be(JellyOptions.BIG_STRICT.getMaxPrefixTableSize) + opts.getMaxDatatypeTableSize should be( + JellyOptions.BIG_STRICT.getMaxDatatypeTableSize, + ) + opts.getLogicalType should be(LogicalStreamType.FLAT_TRIPLES) + opts.getVersion should be(1) RdfToJelly.getErrString should include( "WARNING: Logical type setting ignored because physical type is not set.", ) @@ -545,10 +547,10 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: outFile, ), ) - val (delimited, is) = IoUtils.autodetectDelimiting(new FileInputStream(outFile)) - delimited should be(false) - val frame = RdfStreamFrame.parseFrom(is) - frame.rows.size should be > 0 + val delimitingResponse = IoUtils.autodetectDelimiting(new FileInputStream(outFile)) + delimitingResponse.isDelimited should be(false) + val frame = RdfStreamFrame.parseFrom(delimitingResponse.newInput) + frame.getRows.size should be > 0 } } @@ -565,11 +567,11 @@ class RdfToJellySpec extends AnyWordSpec with TestFixtureHelper with Matchers: outFile, ), ) - val (delimited, is) = IoUtils.autodetectDelimiting(new FileInputStream(outFile)) - delimited should be(true) + val delimitingResponse = IoUtils.autodetectDelimiting(new FileInputStream(outFile)) + delimitingResponse.isDelimited should be(true) val frames = readJellyFile(new FileInputStream(outFile)) frames.size should be > testCardinality - for frame <- frames do frame.rows.size should be(1) + for frame <- frames do frame.getRows.size should be(1) } } } diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscodeSpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscodeSpec.scala index 854f8ba..3f362df 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscodeSpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscodeSpec.scala @@ -3,11 +3,12 @@ package eu.neverblink.jelly.cli.command.rdf import eu.neverblink.jelly.cli.{ExitException, JellyTranscodingError} import eu.neverblink.jelly.cli.command.helpers.TestFixtureHelper import eu.neverblink.jelly.cli.command.rdf.util.{JellyUtil, RdfJellySerializationOptions} -import eu.ostrzyciel.jelly.core.proto.v1.* +import eu.neverblink.jelly.core.proto.v1.* import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec import java.io.{ByteArrayInputStream, FileInputStream} +import scala.jdk.CollectionConverters.* class RdfTranscodeSpec extends AnyWordSpec, Matchers, TestFixtureHelper: protected val testCardinality: Int = 36 @@ -16,15 +17,15 @@ class RdfTranscodeSpec extends AnyWordSpec, Matchers, TestFixtureHelper: private def checkOutputWithDefaultOptions(b: Array[Byte]): Unit = val outF = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(b)) - outF.get.rows.size should be > 36 - val opt = outF.get.rows.head.row.options - opt.physicalType should be(PhysicalStreamType.TRIPLES) - opt.logicalType should be(LogicalStreamType.FLAT_TRIPLES) - opt.maxNameTableSize should be(defaultOpt.maxNameTableSize) - opt.maxPrefixTableSize should be(defaultOpt.maxPrefixTableSize) - opt.maxDatatypeTableSize should be(defaultOpt.maxDatatypeTableSize) - opt.rdfStar should be(defaultOpt.rdfStar) - opt.generalizedStatements should be(defaultOpt.generalizedStatements) + outF.getRows.size should be > 36 + val opt = outF.getRows.asScala.head.getOptions + opt.getPhysicalType should be(PhysicalStreamType.TRIPLES) + opt.getLogicalType should be(LogicalStreamType.FLAT_TRIPLES) + opt.getMaxNameTableSize should be(defaultOpt.getMaxNameTableSize) + opt.getMaxPrefixTableSize should be(defaultOpt.getMaxPrefixTableSize) + opt.getMaxDatatypeTableSize should be(defaultOpt.getMaxDatatypeTableSize) + opt.getRdfStar should be(defaultOpt.getRdfStar) + opt.getGeneralizedStatements should be(defaultOpt.getGeneralizedStatements) "rdf transcode command" should { "transcode input file with no additional options" in withFullJellyFile { j => @@ -59,7 +60,7 @@ class RdfTranscodeSpec extends AnyWordSpec, Matchers, TestFixtureHelper: val outFrames = JellyUtil.iterateRdfStream(ByteArrayInputStream(outB)).toSeq outFrames.size should be(100) outFrames.foreach { f => - f.rows.size should be >= testCardinality + f.getRows.size should be >= testCardinality } } @@ -74,12 +75,12 @@ class RdfTranscodeSpec extends AnyWordSpec, Matchers, TestFixtureHelper: ), ) val outB = RdfTranscode.getOutBytes - val f = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(outB)).get - f.rows.size should be > testCardinality - val opt = f.rows.head.row.options - opt.maxPrefixTableSize should be(600) - opt.physicalType should be(PhysicalStreamType.TRIPLES) - opt.logicalType should be(LogicalStreamType.GRAPHS) + val f = RdfStreamFrame.parseDelimitedFrom(ByteArrayInputStream(outB)) + f.getRows.size should be > testCardinality + val opt = f.getRows.asScala.head.getOptions + opt.getMaxPrefixTableSize should be(600) + opt.getPhysicalType should be(PhysicalStreamType.TRIPLES) + opt.getLogicalType should be(LogicalStreamType.GRAPHS) } "not allow for output name table size to smaller than the input" in withFullJellyFile { j => diff --git a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidateSpec.scala b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidateSpec.scala index f253bc1..12b4584 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidateSpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/command/rdf/RdfValidateSpec.scala @@ -1,11 +1,13 @@ package eu.neverblink.jelly.cli.command.rdf import eu.neverblink.jelly.cli.command.helpers.TestFixtureHelper +import eu.neverblink.jelly.cli.command.helpers.RdfAdapter.* import eu.neverblink.jelly.cli.{CriticalException, ExitException} -import eu.ostrzyciel.jelly.convert.jena.JenaConverterFactory -import eu.ostrzyciel.jelly.convert.jena.riot.JellyLanguage -import eu.ostrzyciel.jelly.core.proto.v1.* -import eu.ostrzyciel.jelly.core.{JellyOptions, ProtoEncoder, RdfProtoDeserializationError} +import eu.neverblink.jelly.convert.jena.JenaConverterFactory +import eu.neverblink.jelly.convert.jena.riot.JellyLanguage +import eu.neverblink.jelly.core.memory.RowBuffer +import eu.neverblink.jelly.core.proto.v1.* +import eu.neverblink.jelly.core.{JellyOptions, ProtoEncoder, RdfProtoDeserializationError} import org.apache.jena.graph.{NodeFactory, Triple} import org.apache.jena.riot.Lang import org.scalatest.matchers.should.Matchers @@ -13,6 +15,7 @@ import org.scalatest.wordspec.AnyWordSpec import java.io.{ByteArrayInputStream, ByteArrayOutputStream, FileInputStream} import scala.util.Using +import scala.jdk.CollectionConverters.* class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: protected val testCardinality: Int = 37 @@ -43,10 +46,10 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: ) "validate delimiting" when { - val frame = RdfStreamFrame( + val frame = rdfStreamFrame( Seq( - RdfStreamRow( - RdfStreamOptions( + rdfStreamRow( + rdfStreamOptions( physicalType = PhysicalStreamType.QUADS, maxNameTableSize = 100, maxPrefixTableSize = 100, @@ -124,8 +127,8 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: "validate basic stream structure" when { "first row in stream is not options" in { - val f = RdfStreamFrame( - Seq(RdfStreamRow(RdfGraphStart())), + val f = rdfStreamFrame( + Seq(rdfStreamRow(rdfGraphStart())), ) RdfValidate.setStdIn(ByteArrayInputStream(f.toByteArray)) val e = intercept[ExitException] { @@ -138,17 +141,19 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "triple used in a QUADS stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setPhysicalType(PhysicalStreamType.QUADS).setVersion( + 1, + ), ), - RdfStreamRow(RdfNameEntry(value = "a")), - RdfStreamRow( - RdfTriple( - RdfIri(0, 1), - RdfIri(0, 1), - RdfIri(0, 1), + rdfStreamRow(rdfNameEntry(value = "a")), + rdfStreamRow( + rdfTriple( + rdfIri(0, 1), + rdfIri(0, 1), + rdfIri(0, 1), ), ), ), @@ -162,53 +167,55 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } val rdfStarTriple = Seq( - RdfStreamRow(RdfNameEntry(value = "a")), - RdfStreamRow( - RdfTriple( - RdfIri(0, 1), - RdfIri(0, 1), - RdfTriple(RdfIri(0, 1), RdfIri(0, 1), RdfIri(0, 1)), + rdfStreamRow(rdfNameEntry(value = "a")), + rdfStreamRow( + rdfTriple( + rdfIri(0, 1), + rdfIri(0, 1), + rdfTriple(rdfIri(0, 1), rdfIri(0, 1), rdfIri(0, 1)), ), ), ) val generalizedTriple = Seq( - RdfStreamRow(RdfNameEntry(value = "a")), - RdfStreamRow( - RdfTriple( - RdfLiteral("aaaa"), - RdfIri(0, 1), - RdfIri(0, 1), + rdfStreamRow(rdfNameEntry(value = "a")), + rdfStreamRow( + rdfTriple( + rdfLiteral("aaaa"), + rdfIri(0, 1), + rdfIri(0, 1), ), ), ) val rdfStarQuad = Seq( - RdfStreamRow(RdfNameEntry(value = "a")), - RdfStreamRow( - RdfQuad( - RdfIri(0, 1), - RdfIri(0, 1), - RdfTriple(RdfIri(0, 1), RdfIri(0, 1), RdfIri(0, 1)), - RdfIri(0, 1), + rdfStreamRow(rdfNameEntry(value = "a")), + rdfStreamRow( + rdfQuad( + rdfIri(0, 1), + rdfIri(0, 1), + rdfTriple(rdfIri(0, 1), rdfIri(0, 1), rdfIri(0, 1)), + rdfIri(0, 1), ), ), ) val generalizedQuad = Seq( - RdfStreamRow(RdfNameEntry(value = "a")), - RdfStreamRow( - RdfQuad( - RdfIri(0, 1), - RdfIri(0, 1), - RdfIri(0, 1), - RdfLiteral("aaaa"), + rdfStreamRow(rdfNameEntry(value = "a")), + rdfStreamRow( + rdfQuad( + rdfIri(0, 1), + rdfIri(0, 1), + rdfIri(0, 1), + rdfLiteral("aaaa"), ), ), ) "RDF-star triple used in an RDF-star stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallRdfStar.withPhysicalType(PhysicalStreamType.TRIPLES).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_RDF_STAR.clone.setPhysicalType( + PhysicalStreamType.TRIPLES, + ).setVersion(1), ), ) ++ rdfStarTriple, ) @@ -217,10 +224,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "RDF-star triple used in a non-RDF-star stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.TRIPLES).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setPhysicalType( + PhysicalStreamType.TRIPLES, + ).setVersion(1), ), ) ++ rdfStarTriple, ) @@ -233,12 +242,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "generalized triple used in a generalized stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallGeneralized.withPhysicalType( + rdfStreamRow( + JellyOptions.SMALL_GENERALIZED.clone.setPhysicalType( PhysicalStreamType.TRIPLES, - ).withVersion(1), + ).setVersion(1), ), ) ++ generalizedTriple, ) @@ -247,10 +256,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "generalized triple used in a non-generalized stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.TRIPLES).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setPhysicalType( + PhysicalStreamType.TRIPLES, + ).setVersion(1), ), ) ++ generalizedTriple, ) @@ -263,10 +274,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "RDF-star quad used in an RDF-star stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallRdfStar.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_RDF_STAR.clone.setPhysicalType( + PhysicalStreamType.QUADS, + ).setVersion(1), ), ) ++ rdfStarQuad, ) @@ -275,10 +288,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "RDF-star quad used in a non-RDF-star stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setPhysicalType(PhysicalStreamType.QUADS).setVersion( + 1, + ), ), ) ++ rdfStarQuad, ) @@ -291,12 +306,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "generalized quad used in a generalized stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallGeneralized.withPhysicalType( + rdfStreamRow( + JellyOptions.SMALL_GENERALIZED.clone.setPhysicalType( PhysicalStreamType.QUADS, - ).withVersion(1), + ).setVersion(1), ), ) ++ generalizedQuad, ) @@ -305,10 +320,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "generalized quad used in a non-generalized stream" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setPhysicalType(PhysicalStreamType.QUADS).setVersion( + 1, + ), ), ) ++ generalizedQuad, ) @@ -321,11 +338,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "repeated stream options (matching)" in { - val o = JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1) - val f = RdfStreamFrame( + val o = + JellyOptions.SMALL_STRICT.clone.setPhysicalType(PhysicalStreamType.QUADS).setVersion(1) + val f = rdfStreamFrame( Seq( - RdfStreamRow(o), - RdfStreamRow(o), + rdfStreamRow(o), + rdfStreamRow(o), ), ) RdfValidate.setStdIn(ByteArrayInputStream(f.toByteArray)) @@ -333,11 +351,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "repeated stream options (differing)" in { - val o = JellyOptions.smallStrict.withPhysicalType(PhysicalStreamType.QUADS).withVersion(1) - val f = RdfStreamFrame( + val o = + JellyOptions.SMALL_STRICT.clone.setPhysicalType(PhysicalStreamType.QUADS).setVersion(1) + val f = rdfStreamFrame( Seq( - RdfStreamRow(o), - RdfStreamRow(o.withVersion(2)), + rdfStreamRow(o), + rdfStreamRow(o.clone.setVersion(2)), ), ) RdfValidate.setStdIn(ByteArrayInputStream(f.toByteArray)) @@ -353,10 +372,10 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: "validate options" when { "invalid input options supplied, no validation source" in { - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallStrict.withVersion(2), + rdfStreamRow( + JellyOptions.SMALL_STRICT.clone.setVersion(2), ), ), ) @@ -365,12 +384,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: RdfValidate.runTestCommand(List("rdf", "validate")) } e.cause.get shouldBe a[RdfProtoDeserializationError] - e.cause.get.getMessage should include("Incoming physical stream type is not set") + e.cause.get.getMessage should include("Incoming physical stream type is not recognized.") } "version in options is set to 0" in { - val f = RdfStreamFrame( - Seq(RdfStreamRow(JellyOptions.smallStrict)), + val f = rdfStreamFrame( + Seq(rdfStreamRow(JellyOptions.SMALL_STRICT)), ) RdfValidate.setStdIn(ByteArrayInputStream(f.toByteArray)) val e = intercept[ExitException] { @@ -381,13 +400,14 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "same input options supplied as in the validation source" in withFullJellyFile { j => - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.smallAllFeatures - .withPhysicalType(PhysicalStreamType.TRIPLES) - .withLogicalType(LogicalStreamType.FLAT_TRIPLES) - .withVersion(1), + rdfStreamRow( + JellyOptions.SMALL_ALL_FEATURES + .clone.setPhysicalType(PhysicalStreamType.TRIPLES) + .setLogicalType(LogicalStreamType.FLAT_TRIPLES) + .setVersion(1) + .setStreamName("Stream"), ), ), ) @@ -396,12 +416,12 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: } "different input options supplied as in the validation source" in withFullJellyFile { j => - val f = RdfStreamFrame( + val f = rdfStreamFrame( Seq( - RdfStreamRow( - JellyOptions.bigStrict - .withPhysicalType(PhysicalStreamType.TRIPLES) - .withVersion(1), + rdfStreamRow( + JellyOptions.BIG_STRICT + .clone.setPhysicalType(PhysicalStreamType.TRIPLES) + .setVersion(1), ), ), ) @@ -477,15 +497,16 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: jenaF => withFullJellyFile { jellyF => val frame1 = Using.resource(FileInputStream(jellyF)) { is => - RdfStreamFrame.parseDelimitedFrom(is).get + RdfStreamFrame.parseDelimitedFrom(is) } - val frame2 = RdfStreamFrame( + val frame2 = rdfStreamFrame( Seq( - RdfStreamRow(RdfTriple(RdfLiteral("aaaa"), RdfLiteral("aaaa"), RdfLiteral("aaaa"))), + rdfStreamRow(rdfTriple(rdfLiteral("aaaa"), rdfLiteral("aaaa"), rdfLiteral("aaaa"))), ), ) - val frames = Seq(RdfStreamFrame(Seq(frame1.rows.head))) :+ frame2 :+ frame1 :++ - (1 to 10).map { _ => frame2 } + val frames = + Seq(rdfStreamFrame(Seq(frame1.getRows.asScala.head))) :+ frame2 :+ frame1 :++ + (1 to 10).map { _ => frame2 } val b = { val os = ByteArrayOutputStream() @@ -511,11 +532,11 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: "content does not match the reference RDF file, using slices" in withFullJenaFile { jenaF => withFullJellyFile { jellyF => val frame1 = Using.resource(FileInputStream(jellyF)) { is => - RdfStreamFrame.parseDelimitedFrom(is).get + RdfStreamFrame.parseDelimitedFrom(is) } val frames = frame1 +: (1 to 10).map { i => - RdfStreamFrame( - Seq(RdfStreamRow(RdfTriple(RdfIri(0, i), RdfIri(0, i), RdfLiteral("aaaa")))), + rdfStreamFrame( + Seq(rdfStreamRow(rdfTriple(rdfIri(0, i), rdfIri(0, i), rdfLiteral("aaaa")))), ) } val b = { @@ -614,13 +635,17 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: ), ), ) - val enc = JenaConverterFactory.encoder( - ProtoEncoder.Params( - JellyOptions.smallRdfStar.withPhysicalType(PhysicalStreamType.TRIPLES), + + val buffer = RowBuffer.newLazyImmutable() + val enc = JenaConverterFactory.getInstance().encoder( + ProtoEncoder.Params.of( + JellyOptions.SMALL_RDF_STAR.clone.setPhysicalType(PhysicalStreamType.TRIPLES), + true, + buffer, ), ) - val rows = enc.addTripleStatement(t) - val f = RdfStreamFrame(rows.toSeq) + enc.handleTriple(t.getSubject, t.getPredicate, t.getObject) + val f = rdfStreamFrame(buffer.asScala.toSeq) val is = ByteArrayInputStream(f.toByteArray) RdfValidate.setStdIn(is) val (out, err) = RdfValidate.runTestCommand(List("rdf", "validate")) @@ -639,13 +664,17 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: ), NodeFactory.createBlankNode(), ) - val enc = JenaConverterFactory.encoder( - ProtoEncoder.Params( - JellyOptions.smallRdfStar.withPhysicalType(PhysicalStreamType.TRIPLES), + val buffer = RowBuffer.newLazyImmutable() + val enc = JenaConverterFactory.getInstance().encoder( + ProtoEncoder.Params.of( + JellyOptions.SMALL_RDF_STAR.clone.setPhysicalType(PhysicalStreamType.TRIPLES), + true, + buffer, ), ) - val rows = enc.addTripleStatement(t) - val f = RdfStreamFrame(rows.toSeq) + + enc.handleTriple(t.getSubject, t.getPredicate, t.getObject) + val f = rdfStreamFrame(buffer.asScala.toSeq) val is = ByteArrayInputStream(f.toByteArray) RdfValidate.setStdIn(is) val e = intercept[ExitException] { @@ -664,13 +693,17 @@ class RdfValidateSpec extends AnyWordSpec, Matchers, TestFixtureHelper: ), ) val t = Triple.create(quoted, quoted, quoted) - val enc = JenaConverterFactory.encoder( - ProtoEncoder.Params( - JellyOptions.smallAllFeatures.withPhysicalType(PhysicalStreamType.TRIPLES), + + val buffer = RowBuffer.newLazyImmutable() + val enc = JenaConverterFactory.getInstance().encoder( + ProtoEncoder.Params.of( + JellyOptions.SMALL_ALL_FEATURES.clone.setPhysicalType(PhysicalStreamType.TRIPLES), + true, + buffer, ), ) - val rows = enc.addTripleStatement(t) - val f = RdfStreamFrame(rows.toSeq) + enc.handleTriple(t.getSubject, t.getPredicate, t.getObject) + val f = rdfStreamFrame(buffer.asScala.toSeq) val is = ByteArrayInputStream(f.toByteArray) RdfValidate.setStdIn(is) val (out, err) = RdfValidate.runTestCommand(List("rdf", "validate")) diff --git a/src/test/scala/eu/neverblink/jelly/cli/util/jena/RdfCompareSpec.scala b/src/test/scala/eu/neverblink/jelly/cli/util/jena/RdfCompareSpec.scala index a87eb62..33985c2 100644 --- a/src/test/scala/eu/neverblink/jelly/cli/util/jena/RdfCompareSpec.scala +++ b/src/test/scala/eu/neverblink/jelly/cli/util/jena/RdfCompareSpec.scala @@ -1,7 +1,7 @@ package eu.neverblink.jelly.cli.util.jena import eu.neverblink.jelly.cli.CriticalException -import eu.ostrzyciel.jelly.core.NamespaceDeclaration +import eu.neverblink.jelly.core.NamespaceDeclaration import org.apache.jena.graph.{NodeFactory, Triple} import org.apache.jena.sparql.core.Quad import org.scalatest.matchers.should.Matchers