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 c91bce89d3 GH-3698: Allow JSON-LD conversion outside of read/write 
operations
c91bce89d3 is described below

commit c91bce89d357f1b52257fe5f9ae6eeb746b8149d
Author: Simon Dumas <[email protected]>
AuthorDate: Thu Jan 15 12:00:11 2026 +0100

    GH-3698: Allow JSON-LD conversion outside of read/write operations
---
 .../org/apache/jena/riot/lang/LangJSONLD11.java    |  86 +--------------
 .../jena/riot/system/jsonld/JenaToTitanium.java    |  99 +++++++++++++++++
 .../riot/system/jsonld/TitaniumJsonLdOptions.java  |  50 +++++++++
 .../jena/riot/system/jsonld/TitaniumToJena.java    |  96 ++++++++++++++++
 .../apache/jena/riot/writer/JsonLD11Writer.java    |  78 ++-----------
 .../riot/system/jsonld/TestJenaToTitanium.java     | 121 +++++++++++++++++++++
 6 files changed, 377 insertions(+), 153 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 323889c1ff..f9487df5e7 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
@@ -23,27 +23,18 @@ 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;
 
-import com.apicatalog.jsonld.JsonLd;
 import com.apicatalog.jsonld.JsonLdError;
 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.api.RdfConsumerException;
-import com.apicatalog.rdf.api.RdfQuadConsumer;
-
 import jakarta.json.*;
 import jakarta.json.stream.JsonLocation;
 import org.apache.jena.atlas.logging.Log;
 import org.apache.jena.atlas.web.ContentType;
-import org.apache.jena.datatypes.RDFDatatype;
-import org.apache.jena.datatypes.TypeMapper;
-import org.apache.jena.graph.Node;
-import org.apache.jena.graph.Triple;
 import org.apache.jena.irix.IRIs;
 import org.apache.jena.riot.Lang;
 import org.apache.jena.riot.ReaderRIOT;
@@ -51,8 +42,9 @@ import org.apache.jena.riot.RiotException;
 import org.apache.jena.riot.system.ErrorHandler;
 import org.apache.jena.riot.system.ParserProfile;
 import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.riot.system.jsonld.TitaniumJsonLdOptions;
+import org.apache.jena.riot.system.jsonld.TitaniumToJena;
 import org.apache.jena.sparql.SystemARQ;
-import org.apache.jena.sparql.core.Quad;
 import org.apache.jena.sparql.util.Context;
 import org.apache.jena.sparql.util.Symbol;
 
@@ -116,14 +108,9 @@ 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);
+        JsonLdOptions opts = TitaniumJsonLdOptions.get(baseURI, context);
         extractPrefixes(document, output::prefix);
-
-        RdfQuadConsumer consumer = new JsonLDToStreamRDF(output, profile);
-        JsonLd.toRdf(document).options(opts).provide(consumer);
-
-        // Titanium 1.5.0 and earlier.
-        // JenaTitanium.convert(dataset, profile, output);
+        TitaniumToJena.convert(document, opts, output, profile);
     }
 
     /**
@@ -230,69 +217,4 @@ public class LangJSONLD11 implements ReaderRIOT {
             }
         });
     }
-
-    /**
-     * Get the (jsonld) options from the jena context if exists or create 
default
-     */
-    private static JsonLdOptions getJsonLdOptions(String baseURI, Context 
jenaContext) {
-        JsonLdOptions opts = jenaContext.get(JSONLD_OPTIONS);
-        if ( opts == null )
-            opts = new JsonLdOptions();
-        if ( baseURI != null )
-            opts.setBase(URI.create(baseURI));
-        return opts;
-    }
-
-    static class JsonLDToStreamRDF implements RdfQuadConsumer {
-        private static long line = -1L;
-        private static long col = -1L;
-
-        private final StreamRDF output;
-        private final ParserProfile profile;
-
-        JsonLDToStreamRDF(StreamRDF output, ParserProfile profile) {
-            this.output = output;
-            this.profile = profile;
-        }
-
-        @Override
-        public RdfQuadConsumer quad(String subject, String predicate, String 
object,
-                                    String datatype, String language, String 
direction,
-                                    String graph) throws RdfConsumerException {
-            Node g = (graph == null) ? null : convertToNode(graph);
-            Node s = convertToNode(subject);
-            Node p = convertToNode(predicate);
-            Node o;
-
-            if ( RdfQuadConsumer.isLiteral(datatype, language, direction) )
-                o = convertToLiteral(object, datatype, language, direction);
-            else
-                o = convertToNode(object);
-
-            if ( g == null )
-                output.triple(Triple.create(s, p, o));
-            else
-                output.quad(Quad.create(g, s, p, o));
-            return this;
-        }
-        private Node convertToNode(String str) {
-            if ( RdfQuadConsumer.isBlank(str) ) {
-                str = str.substring(2); // Remove "_:"
-                Node bn = profile.getFactorRDF().createBlankNode(str);
-                return bn;
-            }
-            str = profile.resolveIRI(str, line, col);
-            Node iri = profile.createURI(str, line, col);
-            return iri;
-        }
-
-        private Node convertToLiteral(String lexical, String datatypeURI, 
String language, String direction) {
-            if ( RdfQuadConsumer.isLangString(datatypeURI, language, 
direction) )
-                return profile.createLangLiteral(lexical, language, line, col);
-            if ( RdfQuadConsumer.isDirLangString(datatypeURI, language, 
direction) )
-                return profile.createLangDirLiteral(lexical, language, 
direction, line, col);
-            RDFDatatype dType = 
TypeMapper.getInstance().getSafeTypeByName(datatypeURI) ;
-            return profile.createTypedLiteral(lexical, dType, line, col);
-        }
-    }
 }
diff --git 
a/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/JenaToTitanium.java 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/JenaToTitanium.java
new file mode 100644
index 0000000000..c89940e29d
--- /dev/null
+++ 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/JenaToTitanium.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.riot.system.jsonld;
+
+import com.apicatalog.jsonld.JsonLd;
+import com.apicatalog.jsonld.JsonLdError;
+import com.apicatalog.jsonld.JsonLdOptions;
+import com.apicatalog.jsonld.JsonLdVersion;
+import com.apicatalog.jsonld.serialization.QuadsToJsonld;
+import com.apicatalog.rdf.api.RdfConsumerException;
+import jakarta.json.JsonArray;
+import org.apache.jena.graph.Node;
+import org.apache.jena.shared.JenaException;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+
+public class JenaToTitanium {
+
+    static class JenaTitaniumException extends JenaException {
+        JenaTitaniumException(String msg) { super(msg); }
+        JenaTitaniumException(String msg, Throwable cause)   { super(msg, 
cause) ; }
+    }
+
+    /** Translates a Jena {@link DatasetGraph} to a JSON-LD document **/
+    public static JsonArray convert(DatasetGraph dataset, JsonLdOptions opts) 
throws JsonLdError {
+        QuadsToJsonld consumer = JsonLd.fromRdf()
+                .options(opts)
+                .mode(JsonLdVersion.V1_1);
+        dataset.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 ex) {
+                    throw new JenaTitaniumException("Exception while 
translating to JSON-LD", ex);
+                }
+            } 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 JenaTitaniumException("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);
+            }
+        });
+
+        return consumer.toJsonLd();
+    }
+
+    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");
+    }
+
+}
diff --git 
a/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumJsonLdOptions.java
 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumJsonLdOptions.java
new file mode 100644
index 0000000000..a724d986c7
--- /dev/null
+++ 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumJsonLdOptions.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.riot.system.jsonld;
+
+import java.net.URI;
+
+import com.apicatalog.jsonld.JsonLdOptions;
+import org.apache.jena.sparql.SystemARQ;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.Symbol;
+
+/**
+ * Get the (jsonld) options from the jena context if exists or create default
+ */
+public class TitaniumJsonLdOptions {
+
+    private static final String SYMBOLS_NS = 
"http://jena.apache.org/riot/jsonld#";;
+    /**
+     * value: the option object expected by JsonLdProcessor (instance of 
JsonLdOptions)
+     */
+    public static final Symbol JSONLD_OPTIONS = 
SystemARQ.allocSymbol(SYMBOLS_NS, "options");
+
+    public static JsonLdOptions get(String baseURI, Context jenaContext) {
+        JsonLdOptions opts = jenaContext.get(JSONLD_OPTIONS);
+        if ( opts == null )
+            opts = new JsonLdOptions();
+        if ( baseURI != null )
+            opts.setBase(URI.create(baseURI));
+        return opts;
+    }
+}
diff --git 
a/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumToJena.java 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumToJena.java
new file mode 100644
index 0000000000..380c05c8dc
--- /dev/null
+++ 
b/jena-arq/src/main/java/org/apache/jena/riot/system/jsonld/TitaniumToJena.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.riot.system.jsonld;
+
+import com.apicatalog.jsonld.JsonLd;
+import com.apicatalog.jsonld.JsonLdError;
+import com.apicatalog.jsonld.JsonLdOptions;
+import com.apicatalog.jsonld.document.Document;
+import com.apicatalog.rdf.api.RdfConsumerException;
+import com.apicatalog.rdf.api.RdfQuadConsumer;
+import org.apache.jena.datatypes.RDFDatatype;
+import org.apache.jena.datatypes.TypeMapper;
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.Triple;
+import org.apache.jena.riot.system.ParserProfile;
+import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.sparql.core.Quad;
+
+public class TitaniumToJena {
+
+    /** Translates a Titanium document to a {@link StreamRDF}  **/
+    public static void convert(Document document, JsonLdOptions opts, 
StreamRDF output, ParserProfile profile) throws JsonLdError {
+        RdfQuadConsumer consumer = new JsonLDToStreamRDF(output, profile);
+        JsonLd.toRdf(document).options(opts).provide(consumer);
+    }
+
+    static class JsonLDToStreamRDF implements RdfQuadConsumer {
+        private static final long line = -1L;
+        private static final long col = -1L;
+
+        private final StreamRDF output;
+        private final ParserProfile profile;
+
+        JsonLDToStreamRDF(StreamRDF output, ParserProfile profile) {
+            this.output = output;
+            this.profile = profile;
+        }
+
+        @Override
+        public RdfQuadConsumer quad(String subject, String predicate, String 
object,
+                                    String datatype, String language, String 
direction,
+                                    String graph) throws RdfConsumerException {
+            Node g = (graph == null) ? null : convertToNode(graph);
+            Node s = convertToNode(subject);
+            Node p = convertToNode(predicate);
+            Node o;
+
+            if ( RdfQuadConsumer.isLiteral(datatype, language, direction) )
+                o = convertToLiteral(object, datatype, language, direction);
+            else
+                o = convertToNode(object);
+
+            if ( g == null )
+                output.triple(Triple.create(s, p, o));
+            else
+                output.quad(Quad.create(g, s, p, o));
+            return this;
+        }
+        private Node convertToNode(String str) {
+            if ( RdfQuadConsumer.isBlank(str) ) {
+                str = str.substring(2); // Remove "_:"
+                return profile.getFactorRDF().createBlankNode(str);
+            }
+            str = profile.resolveIRI(str, line, col);
+            return profile.createURI(str, line, col);
+        }
+
+        private Node convertToLiteral(String lexical, String datatypeURI, 
String language, String direction) {
+            if ( RdfQuadConsumer.isLangString(datatypeURI, language, 
direction) )
+                return profile.createLangLiteral(lexical, language, line, col);
+            if ( RdfQuadConsumer.isDirLangString(datatypeURI, language, 
direction) )
+                return profile.createLangDirLiteral(lexical, language, 
direction, line, col);
+            RDFDatatype dType = 
TypeMapper.getInstance().getSafeTypeByName(datatypeURI) ;
+            return profile.createTypedLiteral(lexical, dType, line, col);
+        }
+    }
+}
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 f47b95728f..63dcc9639e 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
@@ -32,26 +32,23 @@ 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.lang.Keywords;
-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.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.PrefixMap;
+import org.apache.jena.riot.system.jsonld.JenaToTitanium;
+import org.apache.jena.riot.system.jsonld.TitaniumJsonLdOptions;
 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 {
@@ -70,14 +67,14 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
     public void write(OutputStream outputStream, DatasetGraph datasetGraph, 
PrefixMap prefixMap, String baseURI, Context context) {
         Objects.requireNonNull(outputStream);
         Objects.requireNonNull(datasetGraph);
-        write$(outputStream, null, datasetGraph);
+        write$(outputStream, null, datasetGraph, baseURI, context);
     }
 
     @Override
     public void write(Writer out, DatasetGraph datasetGraph, PrefixMap 
prefixMap, String baseURI, Context context) {
         Objects.requireNonNull(out);
         Objects.requireNonNull(datasetGraph);
-        write$(null, out, datasetGraph);
+        write$(null, out, datasetGraph, baseURI, context);
     }
 
     @Override
@@ -85,15 +82,10 @@ 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) {
+    private void write$(OutputStream output, Writer writer, DatasetGraph dsg, 
String baseURI, Context context) {
         try {
-            JsonArray array = datasetToJSON(dsg);
+            JsonLdOptions opts = TitaniumJsonLdOptions.get(baseURI, context);
+            JsonArray array = JenaToTitanium.convert(dsg, opts);
 
             RDFFormatVariant variant = format.getVariant();
             JsonStructure writeThis;
@@ -126,62 +118,6 @@ public class JsonLD11Writer implements WriterDatasetRIOT {
         }
     }
 
-    /** 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;
     }
diff --git 
a/jena-arq/src/test/java/org/apache/jena/riot/system/jsonld/TestJenaToTitanium.java
 
b/jena-arq/src/test/java/org/apache/jena/riot/system/jsonld/TestJenaToTitanium.java
new file mode 100644
index 0000000000..7306ffae8c
--- /dev/null
+++ 
b/jena-arq/src/test/java/org/apache/jena/riot/system/jsonld/TestJenaToTitanium.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.riot.system.jsonld;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.jena.riot.system.ErrorHandlerFactory;
+import org.apache.jena.riot.system.ParserProfile;
+import org.apache.jena.riot.system.RiotLib;
+import org.apache.jena.riot.system.StreamRDF;
+import org.apache.jena.riot.system.StreamRDFLib;
+import org.junit.jupiter.api.Test;
+
+import com.apicatalog.jsonld.JsonLdError;
+import com.apicatalog.jsonld.JsonLdOptions;
+import com.apicatalog.jsonld.document.JsonDocument;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonValue;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.datatypes.xsd.XSDDatatype;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.sparql.util.Context;
+import org.apache.jena.sparql.util.IsoMatcher;
+
+public class TestJenaToTitanium {
+
+    private JsonObject findInArray(JsonArray array, String key, String value) {
+        return array.stream()
+                .filter(jsonValue -> jsonValue.getValueType() == 
JsonValue.ValueType.OBJECT
+                        && jsonValue.asJsonObject().containsKey(key)
+                        && 
jsonValue.asJsonObject().getString(key).equals(value))
+                .map(JsonValue::asJsonObject).findFirst().orElse(null);
+    }
+
+    @Test
+    public void test_convert_titanium() throws JsonLdError {
+        JsonLdOptions options = TitaniumJsonLdOptions.get(null, 
Context.emptyContext());
+        ParserProfile profile = 
RiotLib.createParserProfile(RiotLib.factoryRDF(), 
ErrorHandlerFactory.errorHandlerStd, false);
+
+        String dsStr = StrUtils.strjoinNL
+                ("(dataset"
+                        , "  (_ :s :p :o)"
+                        , "  (_ :s :p 123)"
+                        , "  (_ :s :p 123.5)"
+                        , "  (_ :s :p 1e10)"
+                        , "  (_ :s :p '2021-08-10'^^xsd:date)"
+                        , "  (_ :s :p 'foo')"
+                        , "  (:g1 :s :p :o)"
+                        , "  (:g1 _:x :p :o)"
+                        , "  (:g2 _:x :p 123)"
+                        , "  (:g2 _:x :p 'abc'@en)"
+                        , "  (_:x _:x :p _:x)"
+                        ,")"
+                );
+        DatasetGraph dsg1 = SSE.parseDatasetGraph(dsStr);
+
+        JsonArray jsonld = JenaToTitanium.convert(dsg1, options);
+
+        // Should contain s, g1, g2, x
+        assertEquals(4, jsonld.size());
+
+        // Checking s
+        JsonObject s = findInArray(jsonld, "@id", "http://example/s";);
+        // Contains @id and p
+        assertEquals(2, s.size());
+        assertEquals("http://example/s";, s.getString("@id"));
+        assertTrue(s.containsKey("http://example/p";));
+
+        // s -> http://example/p
+        JsonArray sp = s.getJsonArray("http://example/p";);
+        assertNotNull(sp);
+
+        JsonObject dateValue = findInArray(sp, "@value", "2021-08-10");
+        assertEquals(2, dateValue.size());
+        assertEquals(XSDDatatype.XSDdate.getURI(), 
dateValue.getString("@type"));
+
+        // Checking g2
+        JsonObject g2 = findInArray(jsonld, "@id", "http://example/g2";);
+        assertTrue(g2.containsKey("@graph"));
+
+        // g2 -> @graph -> http://example/p
+        JsonArray g2p = 
g2.getJsonArray("@graph").getJsonObject(0).getJsonArray("http://example/p";);
+        assertEquals(2, g2p.size());
+
+        JsonObject stringLangValue = findInArray(g2p, "@value", "abc");
+        assertEquals("en", stringLangValue.getString("@language"));
+
+        // Converting back to Jena and checking that the result is isomorphic 
with the initial one
+        JsonDocument document = JsonDocument.of(jsonld);
+        DatasetGraph dsg2      = DatasetFactory.create().asDatasetGraph();
+        StreamRDF output = StreamRDFLib.dataset(dsg2);
+        TitaniumToJena.convert(document, options, output, profile);
+        assertTrue(IsoMatcher.isomorphic(dsg1, dsg2), "Datasets should be 
isomorphic");
+    }
+
+
+}
\ No newline at end of file

Reply via email to