Skip to content

Commit 6674be5

Browse files
Upgrade Jelly-JVM to 3.0.0 (#123)
* Upgrade Jelly to version 3.0.0 * Comments * Reformat * Update src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala Co-authored-by: Piotr Sowiński <[email protected]> * Update src/test/scala/eu/neverblink/jelly/cli/command/helpers/TestFixtureHelper.scala Co-authored-by: Piotr Sowiński <[email protected]> --------- Co-authored-by: Piotr Sowiński <[email protected]>
1 parent 81aa766 commit 6674be5

25 files changed

+754
-406
lines changed

build.sbt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ resolvers +=
66
"Sonatype OSS Snapshots" at "https://s01.oss.sonatype.org/content/repositories/snapshots"
77

88
lazy val jenaV = "5.3.0"
9-
lazy val jellyV = "2.10.3"
9+
lazy val jellyV = "3.0.0"
1010

1111
addCommandAlias("fixAll", "scalafixAll; scalafmtAll")
1212

@@ -35,7 +35,8 @@ lazy val root = (project in file("."))
3535
"org.slf4j" % "slf4j-simple" % "2.0.17",
3636
"org.apache.jena" % "jena-core" % jenaV,
3737
"org.apache.jena" % "jena-arq" % jenaV,
38-
"eu.ostrzyciel.jelly" %% "jelly-jena" % jellyV,
38+
"eu.neverblink.jelly" % "jelly-jena" % jellyV,
39+
"eu.neverblink.jelly" % "jelly-core-protos-google" % jellyV,
3940
"com.github.alexarchambault" %% "case-app" % "2.1.0-M30",
4041
"org.scalatest" %% "scalatest" % "3.2.19" % Test,
4142
"org.yaml" % "snakeyaml" % "2.4" % Test,

src/main/scala/eu/neverblink/jelly/cli/command/Version.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ object Version extends JellyCommand[VersionOptions]:
2121
val jenaV = BuildInfo.libraryDependencies
2222
.find(_.startsWith("org.apache.jena:jena-core:")).get.split(":")(2)
2323
val jellyV = BuildInfo.libraryDependencies
24-
.find(_.startsWith("eu.ostrzyciel.jelly:jelly-jena:")).get.split(":")(2)
24+
.find(_.startsWith("eu.neverblink.jelly:jelly-jena:")).get.split(":")(2)
2525
printLine(f"""
2626
|jelly-cli ${BuildInfo.version}
2727
|----------------------------------------------

src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfFromJelly.scala

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ import eu.neverblink.jelly.cli.*
55
import eu.neverblink.jelly.cli.command.rdf.util.*
66
import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat.*
77
import eu.neverblink.jelly.cli.util.args.IndexRange
8-
import eu.ostrzyciel.jelly.convert.jena.JenaConverterFactory
9-
import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamFrame
10-
import org.apache.jena.graph.Triple
8+
import eu.neverblink.jelly.convert.jena.JenaConverterFactory
9+
import eu.neverblink.jelly.core.JellyOptions
10+
import eu.neverblink.jelly.core.RdfHandler.AnyStatementHandler
11+
import eu.neverblink.jelly.core.proto.v1.RdfStreamFrame
12+
import eu.neverblink.jelly.core.proto.google.v1 as google
13+
import org.apache.jena.graph.{Node, Triple}
1114
import org.apache.jena.riot.Lang
1215
import org.apache.jena.riot.system.StreamRDFWriter
1316
import org.apache.jena.sparql.core.Quad
1417

1518
import java.io.{InputStream, OutputStream}
19+
import scala.jdk.CollectionConverters.*
1620

1721
object RdfFromJellyPrint extends RdfCommandPrintUtil[RdfFormat.Writeable]:
1822
override val defaultFormat: RdfFormat = RdfFormat.NQuads
@@ -89,30 +93,40 @@ object RdfFromJelly extends RdfSerDesCommand[RdfFromJellyOptions, RdfFormat.Writ
8993
val writer = StreamRDFWriter.getWriterStream(outputStream, jenaLang)
9094
// Whether the output is active at this moment
9195
var outputEnabled = false
92-
val decoder = JenaConverterFactory.anyStatementDecoder(
96+
val handler = new AnyStatementHandler[Node] {
97+
override def handleNamespace(prefix: String, namespace: Node): Unit = {
98+
if outputEnabled then writer.prefix(prefix, namespace.getURI)
99+
}
100+
101+
override def handleTriple(subject: Node, predicate: Node, `object`: Node): Unit = {
102+
if outputEnabled then writer.triple(Triple.create(subject, predicate, `object`))
103+
}
104+
105+
override def handleQuad(subject: Node, predicate: Node, `object`: Node, graph: Node): Unit = {
106+
if outputEnabled then writer.quad(Quad.create(graph, subject, predicate, `object`))
107+
}
108+
}
109+
110+
val decoder = JenaConverterFactory.getInstance().anyStatementDecoder(
93111
// Only pass on the namespaces to the writer if the output is enabled
94-
namespaceHandler = (String, Node) => {
95-
if outputEnabled then writer.prefix(String, Node.getURI)
96-
},
112+
handler,
113+
JellyOptions.DEFAULT_SUPPORTED_OPTIONS,
97114
)
115+
98116
val inputFrames = takeFrames.end match
99117
case Some(end) => JellyUtil.iterateRdfStream(inputStream).take(end)
100118
case None => JellyUtil.iterateRdfStream(inputStream)
101119
val startFrom = takeFrames.start.getOrElse(0)
102120
for (frame, i) <- inputFrames.zipWithIndex do
103121
// If we are not yet in the output range, still fully parse the frame and update the decoder
104122
// state. We need this to decode the later frames correctly.
105-
if i < startFrom then for row <- frame.rows do decoder.ingestRowFlat(row)
123+
if i < startFrom then for row <- frame.getRows.asScala do decoder.ingestRow(row)
106124
else
107125
// TODO: write frame index as a comment here
108126
// https://github.com/Jelly-RDF/cli/issues/4
109127
outputEnabled = true
110128
// We are in the output range, so we can start writing the output
111-
for row <- frame.rows do
112-
decoder.ingestRowFlat(row) match
113-
case null => ()
114-
case t: Triple => writer.triple(t)
115-
case q: Quad => writer.quad(q)
129+
for row <- frame.getRows.asScala do decoder.ingestRow(row)
116130
writer.finish()
117131

118132
/** 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
128142
// we want to write a comment to the file before each frame
129143
val comment = f"# Frame $frameIndex\n"
130144
outputStream.write(comment.getBytes)
131-
val frame = f.toProtoString
145+
val frame = google.RdfStreamFrame.parseFrom(f.toByteArray).toString
132146
// the protoString is basically the jelly-txt format already
133147
outputStream.write(frame.getBytes)
134148

src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfInspect.scala

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import caseapp.{ArgsName, ExtraName, HelpMessage, Recurse}
44
import caseapp.core.RemainingArgs
55
import eu.neverblink.jelly.cli.*
66
import eu.neverblink.jelly.cli.command.rdf.util.{FrameInfo, JellyUtil, MetricsPrinter}
7-
import eu.ostrzyciel.jelly.core.proto.v1.*
7+
import eu.neverblink.jelly.core.proto.v1.*
8+
9+
import scala.jdk.CollectionConverters.*
810

911
import java.io.InputStream
1012
@HelpMessage(
@@ -57,8 +59,11 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]:
5759
frame: RdfStreamFrame,
5860
frameIndex: Int,
5961
): FrameInfo =
60-
val metrics = new FrameInfo(frameIndex, frame.metadata)
61-
frame.rows.foreach(r => metricsForRow(r, metrics))
62+
val metrics = new FrameInfo(
63+
frameIndex,
64+
frame.getMetadata.asScala.map(entry => entry.getKey -> entry.getValue).toMap,
65+
)
66+
frame.getRows.asScala.foreach(r => metricsForRow(r, metrics))
6267
metrics
6368

6469
try {
@@ -80,7 +85,7 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]:
8085
row: RdfStreamRow,
8186
metadata: FrameInfo,
8287
): Unit =
83-
row.row match {
88+
row.getRow match {
8489
case r: RdfTriple => metadata.tripleCount += 1
8590
case r: RdfQuad => metadata.quadCount += 1
8691
case r: RdfNameEntry => metadata.nameCount += 1
@@ -102,9 +107,10 @@ object RdfInspect extends JellyCommand[RdfInspectOptions]:
102107
*/
103108
private def checkOptions(headFrame: Option[RdfStreamFrame]): RdfStreamOptions =
104109
if headFrame.isEmpty then throw new RuntimeException("No frames in the stream.")
105-
if headFrame.get.rows.isEmpty then throw new RuntimeException("No rows in the frame.")
106-
val frameRows = headFrame.get.rows
107-
frameRows.head.row match {
110+
if headFrame.get.getRows.asScala.isEmpty then
111+
throw new RuntimeException("No rows in the frame.")
112+
val frameRows = headFrame.get.getRows.asScala
113+
frameRows.head.getRow match {
108114
case r: RdfStreamOptions => r
109115
case _ => throw new RuntimeException("First row of the frame is not an options row.")
110116
}

src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfSerDesCommand.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import caseapp.*
77
import eu.neverblink.jelly.cli.command.rdf.util.{RdfCommandPrintUtil, RdfFormat}
88

99
import scala.reflect.TypeTest
10-
import eu.ostrzyciel.jelly.core.{RdfProtoDeserializationError, RdfProtoSerializationError}
10+
import eu.neverblink.jelly.core.{RdfProtoDeserializationError, RdfProtoSerializationError}
1111

1212
import java.io.{InputStream, OutputStream}
1313

src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfToJelly.scala

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package eu.neverblink.jelly.cli.command.rdf
22

33
import caseapp.*
4+
import com.google.protobuf.TextFormat
45
import eu.neverblink.jelly.cli.*
56
import eu.neverblink.jelly.cli.command.rdf.util.*
67
import eu.neverblink.jelly.cli.command.rdf.util.RdfFormat.*
78
import eu.neverblink.jelly.cli.util.jena.riot.JellyStreamWriterGraphs
8-
import eu.ostrzyciel.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage, JellyStreamWriter}
9-
import eu.ostrzyciel.jelly.core.proto.v1.{LogicalStreamType, RdfStreamFrame, RdfStreamOptions}
9+
import eu.neverblink.jelly.convert.jena.JenaConverterFactory
10+
import eu.neverblink.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage, JellyStreamWriter}
11+
import eu.neverblink.jelly.core.proto.google.v1 as google
12+
import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, PhysicalStreamType, RdfStreamOptions}
1013
import org.apache.jena.riot.system.StreamRDFWriter
1114
import org.apache.jena.riot.{Lang, RDFParser, RIOT}
1215

@@ -102,25 +105,27 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable
102105
val jellyOpt = getOptions.jellySerializationOptions.asRdfStreamOptions
103106
// Configure the writer
104107
val jellyWriter =
105-
if jellyOpt.physicalType.isGraphs then
108+
if jellyOpt.getPhysicalType == PhysicalStreamType.GRAPHS then
106109
// GRAPHS
107110
JellyStreamWriterGraphs(
108-
JellyFormatVariant(
109-
// By default, set the logical stream type to FLAT_QUADS (this is what JellyStreamWriter
110-
// in jelly-jena does for physical type QUADS).
111-
opt = jellyOpt.withLogicalType(
112-
if jellyOpt.logicalType.isUnspecified then LogicalStreamType.FLAT_QUADS
113-
else jellyOpt.logicalType,
114-
),
115-
frameSize = getOptions.rowsPerFrame,
116-
enableNamespaceDeclarations = getOptions.enableNamespaceDeclarations,
117-
delimited = getOptions.delimited,
118-
),
111+
JellyFormatVariant
112+
.builder()
113+
.options(
114+
jellyOpt.clone.setLogicalType(
115+
if jellyOpt.getLogicalType == LogicalStreamType.UNSPECIFIED then
116+
LogicalStreamType.FLAT_QUADS
117+
else jellyOpt.getLogicalType,
118+
),
119+
)
120+
.frameSize(getOptions.rowsPerFrame)
121+
.enableNamespaceDeclarations(getOptions.enableNamespaceDeclarations)
122+
.isDelimited(getOptions.delimited)
123+
.build(),
119124
out = outputStream,
120125
)
121126
else
122127
// TRIPLES or QUADS
123-
if jellyOpt.physicalType.isUnspecified then
128+
if jellyOpt.getPhysicalType == PhysicalStreamType.UNSPECIFIED then
124129
if !isQuietMode && isLogicalGrouped(jellyOpt) then
125130
printLine(
126131
"WARNING: Logical type setting ignored because physical type is not set. " +
@@ -145,13 +150,14 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable
145150
)
146151
else
147152
// If the physical type is specified, we can just construct the writer
148-
val variant = JellyFormatVariant(
149-
opt = jellyOpt,
150-
frameSize = getOptions.rowsPerFrame,
151-
enableNamespaceDeclarations = getOptions.enableNamespaceDeclarations,
152-
delimited = getOptions.delimited,
153-
)
154-
JellyStreamWriter(variant, outputStream)
153+
val variant = JellyFormatVariant
154+
.builder()
155+
.options(jellyOpt)
156+
.frameSize(getOptions.rowsPerFrame)
157+
.enableNamespaceDeclarations(getOptions.enableNamespaceDeclarations)
158+
.isDelimited(getOptions.delimited)
159+
.build()
160+
JellyStreamWriter(JenaConverterFactory.getInstance(), variant, outputStream)
155161

156162
RDFParser.source(inputStream).lang(jenaLang).parse(jellyWriter)
157163

@@ -172,7 +178,7 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable
172178
Using.resource(InputStreamReader(inputStream)) { r1 =>
173179
Using.resource(BufferedReader(r1)) { reader =>
174180
jellyTextStreamAsFrames(reader)
175-
.map(txt => RdfStreamFrame.fromAscii(txt))
181+
.map(txt => TextFormat.parse(txt, classOf[google.RdfStreamFrame]))
176182
.foreach(frame => {
177183
if getOptions.delimited then frame.writeDelimitedTo(outputStream)
178184
else frame.writeTo(outputStream)
@@ -189,7 +195,7 @@ object RdfToJelly extends RdfSerDesCommand[RdfToJellyOptions, RdfFormat.Readable
189195
private def isLogicalGrouped(
190196
jellyOpt: RdfStreamOptions,
191197
): Boolean =
192-
!(jellyOpt.logicalType.isFlatQuads || jellyOpt.logicalType.isFlatTriples || jellyOpt.logicalType.isUnspecified)
198+
!(jellyOpt.getLogicalType == LogicalStreamType.FLAT_QUADS || jellyOpt.getLogicalType == LogicalStreamType.FLAT_TRIPLES || jellyOpt.getLogicalType == LogicalStreamType.UNSPECIFIED)
193199

194200
/** Iterate over a Jelly text stream and return the frames as strings to be parsed.
195201
* @param reader

src/main/scala/eu/neverblink/jelly/cli/command/rdf/RdfTranscode.scala

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ package eu.neverblink.jelly.cli.command.rdf
33
import caseapp.*
44
import eu.neverblink.jelly.cli.*
55
import eu.neverblink.jelly.cli.command.rdf.util.*
6-
import eu.ostrzyciel.jelly.core.RdfProtoError
7-
import eu.ostrzyciel.jelly.core.proto.v1.RdfStreamOptions
8-
import eu.ostrzyciel.jelly.core.{JellyOptions, ProtoTranscoder}
6+
import eu.neverblink.jelly.core.proto.v1.{LogicalStreamType, RdfStreamOptions}
7+
import eu.neverblink.jelly.core.{JellyOptions, JellyTranscoderFactory, RdfProtoTranscodingError}
98

109
import java.io.{InputStream, OutputStream}
10+
import scala.jdk.CollectionConverters.*
1111

1212
@HelpMessage(
1313
"Quickly transcodes the input Jelly file into another Jelly file.\n" +
@@ -44,7 +44,7 @@ object RdfTranscode extends JellyCommand[RdfTranscodeOptions]:
4444
val (inputStream, outputStream) =
4545
getIoStreamsFromOptions(remainingArgs.remaining.headOption, options.outputFile)
4646
try jellyToJelly(inputStream, outputStream, outOpt)
47-
catch case e: RdfProtoError => throw JellyTranscodingError(e.getMessage)
47+
catch case e: RdfProtoTranscodingError => throw JellyTranscodingError(e.getMessage)
4848

4949
/** Transcodes the input Jelly stream into another Jelly stream.
5050
* @param inputStream
@@ -61,20 +61,21 @@ object RdfTranscode extends JellyCommand[RdfTranscodeOptions]:
6161
): Unit =
6262
val in = JellyUtil.iterateRdfStream(inputStream).buffered
6363
val head = in.head
64-
if head.rows.isEmpty then throw CriticalException("Empty input stream")
65-
if !head.rows.head.row.isOptions then
64+
if head.getRows.asScala.isEmpty then throw CriticalException("Empty input stream")
65+
if !head.getRows.asScala.head.hasOptions then
6666
throw CriticalException("First input row is not an options row")
67-
val inOpt = head.rows.head.row.options
67+
val inOpt = head.getRows.asScala.head.getOptions
6868

69-
val transcoder = ProtoTranscoder.fastMergingTranscoder(
70-
supportedInputOptions = JellyOptions.defaultSupportedOptions,
71-
outputOptions = outOpt.copy(
69+
val transcoder = JellyTranscoderFactory.fastMergingTranscoder(
70+
JellyOptions.DEFAULT_SUPPORTED_OPTIONS,
71+
outOpt.clone()
7272
// There is no way to specify the physical type with options currently.
7373
// Just use the one from the input.
74-
physicalType = inOpt.physicalType,
75-
logicalType =
76-
if outOpt.logicalType.isUnspecified then inOpt.logicalType else outOpt.logicalType,
77-
),
74+
.setPhysicalType(inOpt.getPhysicalType)
75+
.setLogicalType(
76+
if outOpt.getLogicalType == LogicalStreamType.UNSPECIFIED then inOpt.getLogicalType
77+
else outOpt.getLogicalType,
78+
),
7879
)
7980

8081
in.map(transcoder.ingestFrame)

0 commit comments

Comments
 (0)