This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new 66862b2679 GH-3501: Updates for Titanium 1.7.0
66862b2679 is described below

commit 66862b26795b1c351e0f327f7399d26c722186f6
Author: Andy Seaborne <[email protected]>
AuthorDate: Wed Oct 8 09:28:32 2025 +0100

    GH-3501: Updates for Titanium 1.7.0
---
 .../org/apache/jena/riot/lang/LangJSONLD11.java    |   9 +-
 .../org/apache/jena/riot/system/JenaTitanium.java  |  67 ++++++-----
 .../apache/jena/riot/writer/JsonLD11Writer.java    | 128 ++++++++++++++++-----
 .../org/apache/jena/riot/lang/TestLangJsonLD.java  |   8 +-
 .../org/apache/jena/system/TestJenaTitanium.java   |   2 +-
 pom.xml                                            |   2 +-
 6 files changed, 152 insertions(+), 64 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangJSONLD11.java 
b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangJSONLD11.java
index d960bdb2e7..fe1cea703c 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangJSONLD11.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangJSONLD11.java
@@ -20,6 +20,7 @@ package org.apache.jena.riot.lang;
 
 import java.io.InputStream;
 import java.io.Reader;
+import java.net.URI;
 import java.util.Set;
 import java.util.function.BiConsumer;
 
@@ -29,7 +30,6 @@ import com.apicatalog.jsonld.JsonLdOptions;
 import com.apicatalog.jsonld.document.Document;
 import com.apicatalog.jsonld.document.JsonDocument;
 import com.apicatalog.jsonld.lang.Keywords;
-import com.apicatalog.rdf.RdfDataset;
 import com.apicatalog.rdf.api.RdfConsumerException;
 import com.apicatalog.rdf.api.RdfQuadConsumer;
 
@@ -114,7 +114,6 @@ public class LangJSONLD11 implements ReaderRIOT {
     private void read(Document document, String baseURI, StreamRDF output, 
Context context) throws JsonLdError {
         // JSON-LD to RDF
         JsonLdOptions opts = getJsonLdOptions(baseURI, context);
-        RdfDataset dataset = 
JsonLd.toRdf(document).options(opts).base(baseURI).get();
         extractPrefixes(document, output::prefix);
 
         RdfQuadConsumer consumer = new JsonLDToStreamRDF(output, profile);
@@ -234,7 +233,11 @@ public class LangJSONLD11 implements ReaderRIOT {
      */
     private static JsonLdOptions getJsonLdOptions(String baseURI, Context 
jenaContext) {
         JsonLdOptions opts = jenaContext.get(JSONLD_OPTIONS);
-        return (opts != null) ? opts : new JsonLdOptions();
+        if ( opts == null )
+            opts = new JsonLdOptions();
+        if ( baseURI != null )
+            opts.setBase(URI.create(baseURI));
+        return opts;
     }
 
     static class JsonLDToStreamRDF implements RdfQuadConsumer {
diff --git 
a/jena-arq/src/main/java/org/apache/jena/riot/system/JenaTitanium.java 
b/jena-arq/src/main/java/org/apache/jena/riot/system/JenaTitanium.java
index 7c9f4cf95d..ee0fa0b595 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/system/JenaTitanium.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/system/JenaTitanium.java
@@ -34,7 +34,12 @@ import org.apache.jena.sparql.core.DatasetGraphFactory;
 import org.apache.jena.sparql.core.Quad;
 import org.apache.jena.sparql.util.NodeUtils;
 
-/** Conversion to/from Titanium JSON-LD objects */
+
+/**
+/** Conversion to Titanium JSON-LD.
+ * @deprecated To be removed (not needed for Titanium 1.7.0, which introduces 
titanium-rdf-primitives)
+ */
+@Deprecated(forRemoval = true)
 public class JenaTitanium {
 
     public static class JenaTitaniumException extends JenaException {
@@ -43,7 +48,9 @@ public class JenaTitanium {
 
     /**
      * Translate a Jena {@link DatasetGraph} to a Titanium JSON-LD dataset
+     * @deprecated due to changes introduced in Titanium 1.7.0.
      */
+    @Deprecated(forRemoval = true)
     public static RdfDataset convert(DatasetGraph dataset) {
         RdfProvider provider = RdfProvider.provider();
         RdfDataset rdfDataset = provider.createDataset();
@@ -66,6 +73,30 @@ public class JenaTitanium {
         return rdfDataset;
     }
 
+    private static RdfResource resource(RdfProvider provider, NodeToLabel 
labelMapping, Node node) {
+        if ( node.isBlank() ) {
+            String s = labelMapping.get(null, node);
+            return provider.createBlankNode(s);
+        }
+
+        if ( node.isURI() )
+            return provider.createIRI(node.getURI());
+        throw new JenaTitaniumException("Can not convert to an RdfResource : 
"+node);
+    }
+
+    private static RdfValue nodeToValue(RdfProvider provider, NodeToLabel 
labelMapping, Node node) {
+        if ( node.isBlank() || node.isURI() )
+                return resource(provider, labelMapping, node);
+
+        if ( node.isLiteral()) {
+            String lex = node.getLiteralLexicalForm();
+            if ( NodeUtils.hasLang(node) )
+                return provider.createLangString(lex, 
node.getLiteralLanguage());
+            return provider.createTypedString(lex, 
node.getLiteralDatatypeURI());
+        }
+        throw new JenaTitaniumException("Can not be converted: "+node);
+    }
+
     /**
      * Translate a Titanium JSON-LD dataset to a {@link DatasetGraph}
      * @deprecated No longer used by the LangJSONLD_11
@@ -80,7 +111,9 @@ public class JenaTitanium {
 
     /**
      * Translate a Titanium JSON-LD dataset to a {@link DatasetGraph}
+     * @deprecated No longer used by the LangJSONLD_11
      */
+    @Deprecated(forRemoval = true)
     public static DatasetGraph convert(RdfDataset dataset) {
         DatasetGraph dsg = DatasetGraphFactory.createTxnMem();
         StreamRDF dest = StreamRDFLib.dataset(dsg);
@@ -89,15 +122,19 @@ public class JenaTitanium {
     }
 
     /**
-     * Translate a Titanium JSON-LD dataset to a {@link StreamRDF}
+     * Translate a Titanium JSON-LD dataset and output to a {@link StreamRDF}
+     * @deprecated No longer used by the LangJSONLD_11
      */
+    @Deprecated(forRemoval = true)
     public static void convert(RdfDataset dataset, StreamRDF output) {
         convert(dataset, RiotLib.dftProfile(), output);
     }
 
     /**
-     * Translate a Titanium JSON-LD dataset to a {@link StreamRDF}.
+     * Translate a Titanium JSON-LD dataset and output to a {@link StreamRDF}
+     * @deprecated No longer used by the LangJSONLD_11
      */
+    @Deprecated(forRemoval = true)
     public static void convert(RdfDataset dataset, ParserProfile 
parserProfile, StreamRDF output) {
         for ( RdfNQuad rdfQuad : dataset.toList() ) {
             Optional<RdfResource> gn = rdfQuad.getGraphName();
@@ -147,28 +184,4 @@ public class JenaTitanium {
         }
         throw new JenaTitaniumException("Not recognized: "+value);
     }
-
-    private static RdfResource resource(RdfProvider provider, NodeToLabel 
labelMapping, Node node) {
-        if ( node.isBlank() ) {
-            String s = labelMapping.get(null, node);
-            return provider.createBlankNode(s);
-        }
-
-        if ( node.isURI() )
-            return provider.createIRI(node.getURI());
-        throw new JenaTitaniumException("Can not convert to an RdfResource : 
"+node);
-    }
-
-    private static RdfValue nodeToValue(RdfProvider provider, NodeToLabel 
labelMapping, Node node) {
-        if ( node.isBlank() || node.isURI() )
-                return resource(provider, labelMapping, node);
-
-        if ( node.isLiteral()) {
-            String lex = node.getLiteralLexicalForm();
-            if ( NodeUtils.hasLang(node) )
-                return provider.createLangString(lex, 
node.getLiteralLanguage());
-            return provider.createTypedString(lex, 
node.getLiteralDatatypeURI());
-        }
-        throw new JenaTitaniumException("Can not be converted: "+node);
-    }
 }
diff --git 
a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLD11Writer.java 
b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLD11Writer.java
index 4821de2c6d..9b4d261474 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLD11Writer.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/JsonLD11Writer.java
@@ -27,30 +27,30 @@ import java.util.Objects;
 import com.apicatalog.jsonld.JsonLd;
 import com.apicatalog.jsonld.JsonLdError;
 import com.apicatalog.jsonld.JsonLdOptions;
+import com.apicatalog.jsonld.JsonLdVersion;
 import com.apicatalog.jsonld.api.CompactionApi;
 import com.apicatalog.jsonld.document.Document;
 import com.apicatalog.jsonld.document.JsonDocument;
-import com.apicatalog.jsonld.document.RdfDocument;
 import com.apicatalog.jsonld.lang.Keywords;
-import com.apicatalog.jsonld.processor.FromRdfProcessor;
-import com.apicatalog.rdf.RdfDataset;
+import com.apicatalog.jsonld.serialization.QuadsToJsonld;
+import com.apicatalog.rdf.api.RdfConsumerException;
 
 import jakarta.json.*;
 import jakarta.json.stream.JsonGenerator;
 import org.apache.jena.atlas.lib.Lib;
 import org.apache.jena.atlas.logging.FmtLog;
+import org.apache.jena.graph.Node;
 import org.apache.jena.riot.Lang;
 import org.apache.jena.riot.RDFFormat;
 import org.apache.jena.riot.RDFFormatVariant;
 import org.apache.jena.riot.WriterDatasetRIOT;
-import org.apache.jena.riot.system.JenaTitanium;
 import org.apache.jena.riot.system.PrefixMap;
 import org.apache.jena.shared.JenaException;
 import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
 import org.apache.jena.sparql.util.Context;
 
 public class JsonLD11Writer implements WriterDatasetRIOT {
-
     // It does not matter what the non-null value of PRETTY_PRINTING is (it 
could be "false"!).
     // It is the keys presence that matters.
     private static Map<String, ?> configIndented = 
Map.of(JsonGenerator.PRETTY_PRINTING, true);
@@ -62,10 +62,6 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
         this.format = format;
     }
 
-    private Map<String, ?> config(boolean indented) {
-        return indented ? configIndented : configFlat;
-    }
-
     @Override
     public void write(OutputStream outputStream, DatasetGraph datasetGraph, 
PrefixMap prefixMap, String baseURI, Context context) {
         Objects.requireNonNull(outputStream);
@@ -85,26 +81,30 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
         return format.getLang();
     }
 
+    // Write JSON-LD
+
+    static class JenaTitaniumException extends JenaException {
+        JenaTitaniumException(String msg) { super(msg); }
+    }
+
     private void write$(OutputStream output, Writer writer, DatasetGraph dsg) {
         try {
-            // Context, including prefixes.
-            RdfDataset ds = JenaTitanium.convert(dsg);
-            Document doc = RdfDocument.of(ds);
+            JsonArray array = datasetToJSON(dsg);
+
             RDFFormatVariant variant = format.getVariant();
-            // We do not write top-level arrays.
             JsonStructure writeThis;
             boolean indented = true;
 
             // Choose algorithms
             if ( Lib.equals(variant, RDFFormat.PRETTY) ) {
-                writeThis = writePretty(doc, dsg);
+                writeThis = writePretty(array, dsg);
             } else if ( variant == null || Lib.equals(variant, 
RDFFormat.PLAIN) ) {
-                writeThis = writePlain(doc, dsg);
+                writeThis = writePlain(array, dsg);
             } else if ( Lib.equals(variant, RDFFormat.FLAT) ) {
-                writeThis = writePlain(doc, dsg);
+                writeThis = writePlain(array, dsg);
                 indented = false;
             } else {
-                writeThis = writePretty(doc, dsg);
+                writeThis = writePretty(array, dsg);
             }
 
             if ( writeThis == null ) {
@@ -116,29 +116,85 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
                 FmtLog.warn(this.getClass(), "Output is not a JSON object 
(%s)", writeThis.getClass().getSimpleName());
             }
 
-            JsonWriter jsonWriter = startWrite(output, writer, indented);
-            jsonWriter.write(writeThis);
-            finishWrite(output, writer, indented);
+            writeJson(writeThis, output, writer, indented);
         } catch (Throwable ex) {
             throw new JenaException("Exception while writing JSON-LD 1.1", ex);
         }
     }
 
+    /** Jena DatasetGraph to JSON(LD), Titanium QuadsToJsonld in version 
1.7.0. */
+    private static JsonArray datasetToJSON(DatasetGraph dsg) throws 
JsonLdError {
+        QuadsToJsonld consumer = JsonLd.fromRdf();
+        consumer.mode(JsonLdVersion.V1_1);
+        dsg.stream().forEach( quad->{
+            String s = resource(quad.getSubject());
+            String p = resource(quad.getPredicate());
+            String g = resourceGraphName(quad.getGraph());
+            Node obj = quad.getObject();
+
+            if ( obj.isURI() || obj.isBlank() ) {
+                String o = resource(obj);
+                try {
+                    consumer.quad(s, p, o, null, null, null, g);
+                } catch (RdfConsumerException e) {
+                    e.printStackTrace();
+                }
+            } else if ( obj.isLiteral() ) {
+                String lex = obj.getLiteralLexicalForm();
+                String datatype = obj.getLiteralDatatypeURI();
+                String lang = obj.getLiteralLanguage();
+                if ( lang.isEmpty() )
+                    lang = null;
+                String dir = null;
+                if ( obj.getLiteralBaseDirection() != null )
+                    dir = obj.getLiteralBaseDirection().toString();
+                try {
+                    consumer.quad(s, p, lex, datatype, lang, dir, g);
+                } catch (RdfConsumerException ex) {
+                    throw new JenaException("Exception while translating to 
JSON-LD", ex);
+                }
+            } else if  ( obj.isTripleTerm() ) {
+                throw new JenaTitaniumException("Triple terms not supported 
for JSON-LD");
+            } else {
+                throw new JenaTitaniumException("Encountered unexpected term: 
"+obj);
+            }
+        });
+
+        JsonArray array = consumer.toJsonLd();
+        return array;
+    }
+
+    private static String resourceGraphName(Node gn) {
+        if ( gn == null || Quad.isDefaultGraph(gn) )
+            return null;
+        return resource(gn);
+    }
+
+    private static String resource(Node term) {
+        if ( term.isBlank() )
+            return "_:"+term.getBlankNodeLabel();
+        if ( term.isURI() )
+            return term.getURI();
+        throw new JenaTitaniumException("Not a URI or a blank node");
+    }
+
+    private Map<String, ?> config(boolean indented) {
+        return indented ? configIndented : configFlat;
+    }
+
     // Plain - no @context.
-    private JsonStructure writePlain(Document doc, DatasetGraph dsg) throws 
JsonLdError {
-        JsonArray array = JsonLd.fromRdf(doc).get();
+    private JsonStructure writePlain(JsonArray array, DatasetGraph dsg) throws 
JsonLdError {
         JsonObject writeRdf = Json.createObjectBuilder()
                 .add(Keywords.GRAPH, array)
                 .build();
         return writeRdf;
     }
 
-    private JsonStructure writePretty(Document doc, DatasetGraph dsg) throws 
JsonLdError {
+    private JsonStructure writePretty(JsonArray array, DatasetGraph dsg) 
throws JsonLdError {
         JsonLdOptions options = new JsonLdOptions();
         // Native types.
         // This looses information -- xsd:int becomes xsd:integer, xsd:double 
becomes xsd:decimal
         //   options.setUseNativeTypes(true);
-        JsonArray array = FromRdfProcessor.fromRdf(doc, options);
 
         // Build context
         JsonObjectBuilder cxt = Json.createObjectBuilder();
@@ -172,12 +228,6 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
         return x;
     }
 
-    private JsonWriter startWrite(OutputStream output, Writer writer, boolean 
indented) {
-        Map<String,?> config = config(indented);
-        JsonWriterFactory factory = Json.createWriterFactory(config);
-        return (output != null ) ? factory.createWriter(output) : 
factory.createWriter(writer);
-    }
-
     /*
      * if (pretty) {
         Map<String, Boolean> config = new HashMap<>();
@@ -195,6 +245,24 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
     }
      */
 
+    // JsonWriter
+
+
+    private void writeJson(JsonStructure json, OutputStream output, Writer 
writer, boolean indented) throws IOException {
+        JsonWriter jw = startWrite(output, writer, true);
+        try {
+            jw.write(json);
+        } finally {
+            finishWrite(output, writer, true);
+        }
+    }
+
+    private JsonWriter startWrite(OutputStream output, Writer writer, boolean 
indented) {
+        Map<String,?> config = config(indented);
+        JsonWriterFactory factory = Json.createWriterFactory(config);
+        return (output != null ) ? factory.createWriter(output) : 
factory.createWriter(writer);
+    }
+
     private void finishWrite(OutputStream output, Writer writer, boolean 
indented) throws IOException {
         boolean outputNL = indented;
         if ( output != null ) {
diff --git 
a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangJsonLD.java 
b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangJsonLD.java
index 9805892f89..4e16f7b68d 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangJsonLD.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangJsonLD.java
@@ -18,6 +18,7 @@
 
 package org.apache.jena.riot.lang;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -62,10 +63,13 @@ public class TestLangJsonLD {
         //        "@type": "RelType",
         //        "http://example/p": { "@id" : "#frag" }
         //     }
-        String jsonld = "{ '@id': './relative', '@type': 'RelType', 
'http://example/p': { '@id' : '#frag' } }";
-        jsonld = jsonld.replaceAll("'",  "\"");
+
+        String jsonld = """
+                { "@id": "./relative", "@type": "RelType", "http://example/p": 
{ "@id" : "#frag" } }
+                """;
         Graph g = RDFParser.fromString(jsonld, 
Lang.JSONLD).base("http://base/abc";).toGraph();
         assertNotNull(g);
+        assertFalse(g.isEmpty());
         Triple t = SSE.parseTriple("( <http://base/relative> 
<http://example/p> <http://base/abc#frag> )");
         assertTrue(g.contains(t));
     }
diff --git 
a/jena-arq/src/test/java/org/apache/jena/system/TestJenaTitanium.java 
b/jena-arq/src/test/java/org/apache/jena/system/TestJenaTitanium.java
index f1caf80976..1ed5738bd8 100644
--- a/jena-arq/src/test/java/org/apache/jena/system/TestJenaTitanium.java
+++ b/jena-arq/src/test/java/org/apache/jena/system/TestJenaTitanium.java
@@ -42,6 +42,7 @@ import org.apache.jena.sparql.core.Quad;
 import org.apache.jena.sparql.sse.SSE;
 import org.apache.jena.sparql.util.IsoMatcher;
 
+@SuppressWarnings({"removal", "deprecation"})
 public class TestJenaTitanium {
 
     @Test
@@ -97,7 +98,6 @@ public class TestJenaTitanium {
 
         // Check the RdfDataset
         try ( StringWriter writer = new StringWriter() ) {
-            @SuppressWarnings("deprecation")
             RdfWriter w = new com.apicatalog.rdf.io.nquad.NQuadsWriter(writer);
             w.write(rdfDataset);
             String s = writer.toString();
diff --git a/pom.xml b/pom.xml
index 985358dd0d..26d31e8111 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,7 +63,7 @@
     <ver.log4j2>2.25.2</ver.log4j2>
 
     <!-- JSON-LD 1.1 -->
-    <ver.titanium-json-ld>1.6.0</ver.titanium-json-ld>
+    <ver.titanium-json-ld>1.7.0</ver.titanium-json-ld>
     <ver.jakarta.json>2.0.1</ver.jakarta.json>
 
     <!-- These two must be in-step -->

Reply via email to