diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16c5367fc..ea60dde62 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,10 +55,6 @@ jobs: if [ $JELLY_VERSION = "refs/heads/main" ]; then JELLY_VERSION="dev" fi - # For Jena 5.5.0 - sbt "integrationTests/testOnly *ProtocolConformanceSpec -- -z Jena -C eu.neverblink.jelly.integration_tests.util.ConformanceReporter" - # Jena 5.3.0 and the rest - sed -i "s/lazy val jenaV = .*/lazy val jenaV = \"5.3.0\"/g" build.sbt sbt "integrationTests/testOnly *ProtocolConformanceSpec -- -C eu.neverblink.jelly.integration_tests.util.ConformanceReporter" cd integration-tests/target tar -czf conformance_reports.tar.gz reports/ diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml index de2b72876..a3b6b9b00 100644 --- a/.github/workflows/scala.yml +++ b/.github/workflows/scala.yml @@ -23,12 +23,11 @@ jobs: # Tests run on JDK 21 (LTS baseline), 25, and the latest release (26). # Across those we also exercise the oldest and newest supported Jena/RDF4J versions. # The dependency is set by default to Jena 5.6. - # See: https://github.com/Jelly-RDF/jelly-jvm/issues/622 - os: ubuntu-latest java: 21 - # Jena 5.3.0 is the last version supporting RDF-star. - # 5.4.0 dropped it in favor of RDF1.2. - jena_version: "5.3.0" + # Jena 5.4.0 is the oldest supported version - it introduced the RDF 1.2 triple term + # API that we use, replacing the RDF-star API of 5.3.x and older. + jena_version: "5.4.0" # Test the last RDF4J 4.x version. rdf4j_version: "4.3.16" # Jena 6 requires Java 21. @@ -61,9 +60,8 @@ jobs: - name: Setup SBT uses: sbt/setup-sbt@v1 - # This is necessary, as Jena suddenly dropped support for RDF-star in 5.4.0 in favor of RDF1.2. - # We want to keep RDF-star support a possibility, so we test against Jena 5.3 as well as the latest version. - # See: https://github.com/Jelly-RDF/jelly-jvm/issues/368 + # Jena and RDF4J occasionally change their APIs between minor versions, so we test against + # the oldest and the newest supported version of each. - name: Switch Jena and RDF4J versions shell: bash run: | diff --git a/build.sbt b/build.sbt index 69da9ac5a..46e1555a2 100644 --- a/build.sbt +++ b/build.sbt @@ -63,9 +63,7 @@ lazy val commonSettings = Seq( ) ++ wErrorIfCI, // Explicitly specify the options for javadoc, otherwise sbt will pass all javacOptions to it // which will cause an error. - // Exclude org.apache to avoid including JenaCompatHelper. - // See: https://github.com/Jelly-RDF/jelly-jvm/issues/622 - Compile / doc / javacOptions := Seq("-source", "21", "-exclude", "org.apache"), + Compile / doc / javacOptions := Seq("-source", "21"), assemblyJarName := s"${name.value}.jar", assemblyMergeStrategy := { case x if x.endsWith("module-info.class") => MergeStrategy.concat diff --git a/docs/docs/index.md b/docs/docs/index.md index 9b380ac66..3a9de5f94 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -67,7 +67,7 @@ The following table shows the compatibility of the Jelly-JVM implementation with | Jelly-JVM | Java | Scala | RDF4J | Jena | Pekko | Neo4j | |:-----------------------------------------------------------------------------------------------------------------------------------------------:|:----:|:-------------------------:|:-----------:|:-------------------------------------:|:-----------------------------------------------------------------------:|:-----------------------------------------------------:| -| [4.0.x](https://w3id.org/jelly/jelly-jvm/4.0.x)–[**{{ jvm_package_version() }}**](https://w3id.org/jelly/jelly-jvm/{{ jvm_package_version() }}) | 21+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x–6.x.x | 1.1.x–1.2.x | {{ neo4j_version('min') }}–{{ neo4j_version('max') }} | +| [4.0.x](https://w3id.org/jelly/jelly-jvm/4.0.x)–[**{{ jvm_package_version() }}**](https://w3id.org/jelly/jelly-jvm/{{ jvm_package_version() }}) | 21+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.4.x–6.x.x | 1.1.x–1.2.x | {{ neo4j_version('min') }}–{{ neo4j_version('max') }} | | [3.7.x](https://w3id.org/jelly/jelly-jvm/3.7.x) | 17+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x–6.x.x | 1.1.x–1.2.x | 5.1.0–5.26.0 | | [3.5.x](https://w3id.org/jelly/jelly-jvm/3.5.x)–[3.6.x](https://w3id.org/jelly/jelly-jvm/3.6.x) | 17+ | 3.3.x (LTS)[^2] | 4.3.x–5.x.x | 5.x.x | 1.1.x–1.2.x | 5.1.0–5.26.0 | | [3.0.x](https://w3id.org/jelly/jelly-jvm/3.0.x)–[3.4.x](https://w3id.org/jelly/jelly-jvm/3.4.x) | 17+ | 3.3.x (LTS)[^2] | 5.x.x | 5.x.x | 1.1.x | – | diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala index 0c7f6fd28..cc472427c 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/patch/impl/JenaImplementation.scala @@ -4,7 +4,7 @@ import eu.neverblink.jelly.convert.jena.patch.* import eu.neverblink.jelly.core.patch.JellyPatchOptions import eu.neverblink.jelly.core.proto.v1.patch.{PatchStatementType, RdfPatchOptions} import eu.neverblink.jelly.integration_tests.patch.traits.* -import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, TestComparable} +import eu.neverblink.jelly.integration_tests.util.TestComparable import org.apache.jena.rdfpatch.text.RDFPatchReaderText import org.scalatest.matchers.should.Matchers.* @@ -26,7 +26,8 @@ object JenaImplementation extends RdfPatchImplementation[JenaChangesCollector]: override def name: String = "Jena" - override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher + // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2. + override def supportsRdfStar: Boolean = false override def readRdf(in: InputStream, stType: PatchStatementType): JenaChangesCollector = val collector = JellyPatchOps.changesCollector(stType) diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala index 2baa9e046..08da5c94b 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/JenaTestStream.scala @@ -3,7 +3,6 @@ package eu.neverblink.jelly.integration_tests.rdf import eu.neverblink.jelly.convert.jena.{JenaAdapters, JenaConverterFactory} import eu.neverblink.jelly.core.proto.v1.{RdfStreamFrame, RdfStreamOptions} import eu.neverblink.jelly.core.utils.{QuadExtractor, QuadMaker, TripleExtractor, TripleMaker} -import eu.neverblink.jelly.integration_tests.util.CompatibilityUtils import eu.neverblink.jelly.pekko.stream.{DecoderFlow, EncoderFlow, RdfSource, SizeLimiter} import org.apache.jena.graph.{Node, Triple} import org.apache.jena.riot.system.AsyncParser @@ -30,9 +29,10 @@ case object JenaTestStream extends TestStream: given JenaAdapters.DATASET_GRAPH_ADAPTER.type = JenaAdapters.DATASET_GRAPH_ADAPTER given JenaAdapters.MODEL_ADAPTER.type = JenaAdapters.MODEL_ADAPTER - override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdf12: Boolean = true - override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher + // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2. + override def supportsRdfStar: Boolean = false override def tripleSource( is: InputStream, diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala index 1820ce75c..1968a09c4 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaReactiveSerDes.scala @@ -3,7 +3,6 @@ package eu.neverblink.jelly.integration_tests.rdf.io import eu.neverblink.jelly.convert.jena.{JenaAdapters, JenaConverterFactory} import eu.neverblink.jelly.core.JellyOptions import eu.neverblink.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamOptions} -import eu.neverblink.jelly.integration_tests.util.CompatibilityUtils import eu.neverblink.jelly.pekko.stream.* import org.apache.jena.graph.{Node, Triple} import org.apache.jena.query.Dataset @@ -26,12 +25,12 @@ class JenaReactiveSerDes(implicit mat: Materializer) val name = "Reactive writes (Apache Jena)" - override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdf12: Boolean = true - override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher + // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2. + override def supportsRdfStar: Boolean = false - override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = - !CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = false override def readTriplesW3C(is: InputStream): Model = JenaSerDes.readTriplesW3C(is) diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala index e41345c5d..ae3ba1671 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaSerDes.scala @@ -3,7 +3,7 @@ package eu.neverblink.jelly.integration_tests.rdf.io import eu.neverblink.jelly.convert.jena.riot.{JellyFormatVariant, JellyLanguage} import eu.neverblink.jelly.core.JellyOptions import eu.neverblink.jelly.core.proto.v1.RdfStreamOptions -import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, Measure} +import eu.neverblink.jelly.integration_tests.util.Measure import org.apache.jena.query.{Dataset, DatasetFactory} import org.apache.jena.rdf.model.{Model, ModelFactory} import org.apache.jena.riot.* @@ -17,9 +17,10 @@ given Measure[Dataset] = (ds: Dataset) => ds.asDatasetGraph().find().asScala.siz object JenaSerDes extends NativeSerDes[Model, Dataset]: val name = "Jena" - override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdf12: Boolean = true - override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher + // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2. + override def supportsRdfStar: Boolean = false override def readTriplesW3C(is: InputStream): Model = val m = ModelFactory.createDefaultModel() diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala index 1c327a169..c46e0aaab 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/io/JenaStreamSerDes.scala @@ -4,8 +4,8 @@ import eu.neverblink.jelly.convert.jena.riot.JellyLanguage import eu.neverblink.jelly.core.JellyOptions import eu.neverblink.jelly.core.proto.v1.{PhysicalStreamType, RdfStreamOptions} import eu.neverblink.jelly.integration_tests.rdf.util.riot.TestRiot -import eu.neverblink.jelly.integration_tests.util.{CompatibilityUtils, Measure} -import org.apache.jena.graph.{JenaCompatHelper, Node, Triple} +import eu.neverblink.jelly.integration_tests.util.Measure +import org.apache.jena.graph.{Node, Triple} import org.apache.jena.riot.lang.LabelToNode import org.apache.jena.riot.system.{StreamRDFLib, StreamRDFWriter} import org.apache.jena.riot.{RDFParser, RIOT} @@ -26,12 +26,12 @@ object JenaStreamSerDes override def name: String = "Jena (StreamRDF)" - override def supportsRdf12: Boolean = CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdf12: Boolean = true - override def supportsRdfStar: Boolean = !CompatibilityUtils.jenaVersion54OrHigher + // Jena dropped RDF-star in 5.4.0, in favor of RDF 1.2. + override def supportsRdfStar: Boolean = false - override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = - !CompatibilityUtils.jenaVersion54OrHigher + override def supportsRdfStar(physicalStreamType: PhysicalStreamType): Boolean = false override def readTriplesW3C(is: InputStream): Seq[Triple] = val sink = SinkSeq[Triple]() @@ -215,7 +215,7 @@ object JenaStreamSerDes override def getBlankNodeLabel(node: Node): String = node.getBlankNodeLabel - override def isNodeTriple(node: Node): Boolean = JenaCompatHelper.isNodeTriple(node) + override def isNodeTriple(node: Node): Boolean = node.isTripleTerm override def iterateTerms(node: Triple | Quad): Seq[Node] = node match { diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala index 49d43fb48..fc04ff0cd 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/JenaToRdf4jAdapter.scala @@ -1,6 +1,6 @@ package eu.neverblink.jelly.integration_tests.rdf.util -import org.apache.jena.graph.{JenaCompatHelper, Node, Triple} +import org.apache.jena.graph.{Node, Triple} import org.apache.jena.riot.system.StreamRDF import org.apache.jena.sparql.core.Quad import org.eclipse.rdf4j.model.{IRI, Resource, Value} @@ -17,7 +17,7 @@ class JenaToRdf4jAdapter(delegate: RDFHandler) extends StreamRDF { def makeResource(n: Node): Resource = { if n.isBlank then vf.createBNode(n.getBlankNodeLabel) - else if JenaCompatHelper.isNodeTriple(n) then { + else if n.isTripleTerm then { val t = n.getTriple vf.createTriple( makeResource(t.getSubject), diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala index a3a56de55..73a308d0b 100644 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala +++ b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/rdf/util/riot/LangNTupleGeneralized.scala @@ -1,6 +1,6 @@ package eu.neverblink.jelly.integration_tests.rdf.util.riot -import org.apache.jena.graph.{JenaCompatHelper, Node, Triple} +import org.apache.jena.graph.{Node, NodeFactory, Triple} import org.apache.jena.riot.lang.LangNTuple import org.apache.jena.riot.system.{ParserProfile, StreamRDF} import org.apache.jena.riot.tokens.{StringType, Token, TokenType, Tokenizer} @@ -69,4 +69,4 @@ abstract class LangNTupleGeneralized[T](tokens: Tokenizer, profile: ParserProfil val x = nextToken if ((x.getType ne TokenType.GT2) && (x.getType ne TokenType.R_TRIPLE)) exception(x, "Triple term not terminated by >>: %s", x) - JenaCompatHelper.createTripleNode(t) + NodeFactory.createTripleTerm(t) diff --git a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala b/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala deleted file mode 100644 index 54392ecfd..000000000 --- a/integration-tests/src/test/scala/eu/neverblink/jelly/integration_tests/util/CompatibilityUtils.scala +++ /dev/null @@ -1,9 +0,0 @@ -package eu.neverblink.jelly.integration_tests.util - -import org.apache.jena.Jena - -object CompatibilityUtils: - lazy val jenaVersion54OrHigher: Boolean = { - val split = Jena.VERSION.split('.') - split(0).toInt > 5 || split(1).toInt >= 4 - } diff --git a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java index 1253b011e..01d58cb78 100644 --- a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java +++ b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaDecoderConverter.java @@ -4,7 +4,6 @@ import eu.neverblink.jelly.core.utils.QuadMaker; import eu.neverblink.jelly.core.utils.TripleMaker; import org.apache.jena.datatypes.RDFDatatype; -import org.apache.jena.graph.JenaCompatHelper; import org.apache.jena.graph.Node; import org.apache.jena.graph.NodeFactory; import org.apache.jena.graph.Triple; @@ -46,7 +45,7 @@ public Node makeIriNode(String iri) { @Override public Node makeTripleNode(Node s, Node p, Node o) { - return JenaCompatHelper.createTripleNode(s, p, o); + return NodeFactory.createTripleTerm(s, p, o); } @Override diff --git a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java index f481241bc..8cee6c3e6 100644 --- a/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java +++ b/jena/src/main/java/eu/neverblink/jelly/convert/jena/JenaEncoderConverter.java @@ -6,7 +6,6 @@ import eu.neverblink.jelly.core.utils.QuadExtractor; import eu.neverblink.jelly.core.utils.TripleExtractor; import org.apache.jena.datatypes.xsd.XSDDatatype; -import org.apache.jena.graph.JenaCompatHelper; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.sparql.core.Quad; @@ -37,7 +36,7 @@ public Object nodeToProto(NodeEncoder encoder, Node node) { } else { return encoder.makeLangLiteral(node, node.getLiteralLexicalForm(), lang); } - } else if (JenaCompatHelper.isNodeTriple(node)) { + } else if (node.isTripleTerm()) { // RDF-star node final var t = node.getTriple(); return encoder.makeQuotedTriple(t.getSubject(), t.getPredicate(), t.getObject()); diff --git a/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java b/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java deleted file mode 100644 index 8f75a8bb7..000000000 --- a/jena/src/main/java/org/apache/jena/graph/JenaCompatHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.apache.jena.graph; - -import eu.neverblink.jelly.core.InternalApi; - -/** - * Hack to avoid very complex dependency and method binding workarounds needed to support - * Jena 5.3, 5.4, and 6.0 at the same time. - * This class should be removed as soon as Jena 5.3 support is dropped. - * See: issue - */ -@InternalApi -public final class JenaCompatHelper { - - public static boolean isNodeTriple(Node node) { - return node instanceof Node_Triple; - } - - public static Node createTripleNode(Node s, Node p, Node o) { - return new Node_Triple(s, p, o); - } - - public static Node createTripleNode(Triple t) { - return new Node_Triple(t); - } -} diff --git a/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala b/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala similarity index 91% rename from jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala rename to jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala index 4bb76e816..c7b624836 100644 --- a/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaCompatHelperSpec.scala +++ b/jena/src/test/scala/eu/neverblink/jelly/convert/jena/JenaVersionSpec.scala @@ -4,7 +4,7 @@ import eu.neverblink.jelly.convert.jena.traits.JenaTest import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -class JenaCompatHelperSpec extends AnyWordSpec, Matchers, JenaTest: +class JenaVersionSpec extends AnyWordSpec, Matchers, JenaTest: val isCi: Boolean = System.getenv("CI") != null val jenaVersionCI: String = System.getenv("JENA_VERSION") val jenaVersionFromClass = org.apache.jena.Jena.VERSION