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