Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ extraJavaModuleInfo {
automaticModule("com.github.jsonld-java:jsonld-java", "jsonld.java") // Module for JSON-LD Java
automaticModule("commons-lang:commons-lang", "commons.lang") // Module for Commons Lang
automaticModule("fr.inria.lille.shexjava:shexjava-core", "shexjava.core") // Module for ShexJava core
automaticModule("org.eclipse.rdf4j:rdf4j-model", "rdf4j.model") // Module for RDF4J model
// Nouveaux modules RDF4J
automaticModule("org.eclipse.rdf4j:rdf4j-rio-api", "rdf4j.rio.api")
automaticModule("org.eclipse.rdf4j:rdf4j-rio-turtle", "org.eclipse.rdf4j.rio.turtle")
automaticModule("org.eclipse.rdf4j:rdf4j-rio-jsonld", "org.eclipse.rdf4j.rio.jsonld")
automaticModule("org.eclipse.rdf4j:rdf4j-rio-rdfxml", "org.eclipse.rdf4j.rio.rdfxml")
automaticModule("org.eclipse.rdf4j:rdf4j-model", "rdf4j.model.api")
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package fr.inria.corese.core.next.api.base.model.serialization;

import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.Rio;
import org.eclipse.rdf4j.rio.WriterConfig;
import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings;

import java.io.OutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
* Utility class for serializing RDF4J {@link Model} objects to various RDF formats.
* This class provides static methods to write RDF data to an {@link OutputStream}
* in formats such as Turtle, JSON-LD, RDF/XML, and N-Triples, leveraging the RDF4J Rio API.
* It handles common serialization configurations like pretty-printing and
* provides dynamic format selection based on string identifiers.
*/
public class Rdf4jSerializationUtil {


private static final Map<String, RDFFormat> FORMAT_MAP = initFormatMap();

private static final WriterConfig DEFAULT_CONFIG = createDefaultConfig();

/**
* Initializes and returns an unmodifiable map of supported RDF format strings to their
* corresponding {@link RDFFormat} objects.
*
* @return An unmodifiable {@link Map} containing format string to {@link RDFFormat} mappings.
*/
private static Map<String, RDFFormat> initFormatMap() {
Map<String, RDFFormat> map = new HashMap<>();

// Common file extension for Turtle
map.put("turtle", RDFFormat.TURTLE);
map.put("ttl", RDFFormat.TURTLE);

// Common alternative for JSON-LD
map.put("jsonld", RDFFormat.JSONLD);
map.put("json-ld", RDFFormat.JSONLD);

// Common alternative for RDF/XML
map.put("rdfxml", RDFFormat.RDFXML);
map.put("xml", RDFFormat.RDFXML);

return Collections.unmodifiableMap(map);
}

/**
* Creates and returns a default {@link WriterConfig} instance.
* This configuration enables pretty-printing for human-readable output.
* Deprecated JSON-LD specific settings have been removed.
*
* @return A {@link WriterConfig} instance with default serialization settings.
*/
private static WriterConfig createDefaultConfig() {
WriterConfig config = new WriterConfig();

config.set(BasicWriterSettings.PRETTY_PRINT, true);


return config;
}

/**
* Returns a set of string identifiers for all supported RDF serialization formats.
* These identifiers can be used with the {@link #serialize(Model, OutputStream, String)}
* and {@link #getRdfFormat(String)} methods.
*
* @return A {@link Set} of {@link String} representing the supported RDF format identifiers.
*/
public static Set<String> getSupportedFormats() {
return FORMAT_MAP.keySet();
}

/**
* Serializes an RDF4J {@link Model} to the specified {@link OutputStream} in Turtle format.
* The serialization uses the default writer configuration (e.g., pretty-printing enabled).
*
* @param model The RDF4J {@link Model} to serialize. Must not be {@code null}.
* @param outputStream The {@link OutputStream} to write the serialized data to. Must not be {@code null}.
* @throws IOException If an I/O error occurs during serialization.
* @throws NullPointerException If {@code model} or {@code outputStream} is {@code null}.
* @see #serialize(Model, OutputStream, RDFFormat)
*/
public static void serializeToTurtle(Model model, OutputStream outputStream) throws IOException {
serialize(model, outputStream, RDFFormat.TURTLE);
}

/**
* Serializes an RDF4J {@link Model} to the specified {@link OutputStream} in JSON-LD format.
* The serialization uses the default writer configuration (e.g., pretty-printing enabled).
*
* @param model The RDF4J {@link Model} to serialize. Must not be {@code null}.
* @param outputStream The {@link OutputStream} to write the serialized data to. Must not be {@code null}.
* @throws IOException If an I/O error occurs during serialization.
* @throws NullPointerException If {@code model} or {@code outputStream} is {@code null}.
* @see #serialize(Model, OutputStream, RDFFormat)
*/
public static void serializeToJsonLd(Model model, OutputStream outputStream) throws IOException {
serialize(model, outputStream, RDFFormat.JSONLD);
}

/**
* Serializes an RDF4J {@link Model} to the specified {@link OutputStream} in RDF/XML format.
* The serialization uses the default writer configuration (e.g., pretty-printing enabled).
*
* @param model The RDF4J {@link Model} to serialize. Must not be {@code null}.
* @param outputStream The {@link OutputStream} to write the serialized data to. Must not be {@code null}.
* @throws IOException If an I/O error occurs during serialization.
* @throws NullPointerException If {@code model} or {@code outputStream} is {@code null}.
* @see #serialize(Model, OutputStream, RDFFormat)
*/
public static void serializeToRdfXml(Model model, OutputStream outputStream) throws IOException {
serialize(model, outputStream, RDFFormat.RDFXML);
}


/**
* Resolves an {@link RDFFormat} from a given string identifier.
* The lookup is case-insensitive.
*
* @param formatString The string representing the desired RDF format (e.g., "turtle", "jsonld", "rdfxml", "ntriples").
* Must not be {@code null}.
* @return The corresponding {@link RDFFormat} enum.
* @throws IllegalArgumentException If the provided {@code formatString} is not recognized as a supported format.
* @throws NullPointerException If {@code formatString} is {@code null}.
*/
public static RDFFormat getRdfFormat(String formatString) throws IllegalArgumentException {
Objects.requireNonNull(formatString, "Format string cannot be null");
RDFFormat format = FORMAT_MAP.get(formatString.toLowerCase());
if (format == null) {
throw new IllegalArgumentException("Unsupported format: " + formatString +
". Supported formats: " + getSupportedFormats());
}
return format;
}

/**
* Serializes an RDF4J {@link Model} to a specified {@link OutputStream},
* with the format determined dynamically by a string identifier.
* This method is useful when the target format is known at runtime.
*
* @param model The RDF4J {@link Model} to serialize. Must not be {@code null}.
* @param outputStream The {@link OutputStream} to write the serialized data to. Must not be {@code null}.
* @param formatString The string identifier of the desired RDF format (e.g., "turtle", "jsonld", "rdfxml", "ntriples").
* Must not be {@code null}.
* @throws IOException If an I/O error occurs during serialization or if the underlying
* {@link Rio #write(Model, OutputStream, RDFFormat, WriterConfig)} call fails.
* @throws IllegalArgumentException If the provided {@code formatString} is not recognized.
* @throws NullPointerException If {@code model}, {@code outputStream}, or {@code formatString} is {@code null}.
*/
public static void serialize(Model model, OutputStream outputStream, String formatString) throws IOException {
Objects.requireNonNull(model, "Model cannot be null");
Objects.requireNonNull(outputStream, "OutputStream cannot be null");

RDFFormat format = getRdfFormat(formatString);
serialize(model, outputStream, format);
}

/**
* Internal method to perform the actual serialization using RDF4J Rio.
* This method applies the {@link #DEFAULT_CONFIG}.
*
* @param model The RDF4J {@link Model} to serialize.
* @param outputStream The {@link OutputStream} to write the serialized data to.
* @param format The {@link RDFFormat} to use for serialization.
* @throws IOException If an I/O error occurs during serialization.
*/
private static void serialize(Model model, OutputStream outputStream, RDFFormat format) throws IOException {
try {
Rio.write(model, outputStream, format, DEFAULT_CONFIG);
} catch (Exception e) {

throw new IOException("Failed to serialize RDF model to " + format.getName(), e);
}
}

}
63 changes: 60 additions & 3 deletions src/main/java/fr/inria/corese/core/next/impl/temp/CoreseModel.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package fr.inria.corese.core.next.impl.temp;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
Expand All @@ -20,11 +22,17 @@
import fr.inria.corese.core.next.api.Statement;
import fr.inria.corese.core.next.api.Value;
import fr.inria.corese.core.next.api.base.model.AbstractModel;
import fr.inria.corese.core.next.api.base.model.serialization.Rdf4jSerializationUtil;

import org.eclipse.rdf4j.model.impl.TreeModel;


/**
* CoreseModel provides an implementation of the RDF Model interface
* backed by a Corese Graph instance. It supports basic RDF operations
* such as add, remove, contains, filtering, and namespace management.
* This class has been extended to include a method for serializing
* its content into various RDF4J formats using Rdf4jSerializationUtil.
*/
public class CoreseModel extends AbstractModel {

Expand Down Expand Up @@ -139,6 +147,8 @@ public boolean add(Resource subject, IRI predicate, Value object, Resource... co
for (Node coreseContext : coreseContexts) {
if (coreseContext != null) {
changed |= this.addEdgeToGraph(coreseSubj, coresePred, coreseObj, coreseContext);
} else {
changed |= this.addEdgeToGraph(coreseSubj, coresePred, coreseObj, null);
}
}
return changed;
Expand Down Expand Up @@ -228,7 +238,8 @@ protected void removeFilteredTermIteration(

@Override
public Iterator<Statement> iterator() {
return getFilterIterator(null, null, null);

return getFilterIterator(null, null, null, (Resource[]) null);
}

@Override
Expand Down Expand Up @@ -294,7 +305,7 @@ private Iterable<Edge> selectEdgesFromCorese(Node subject, Node predicate, Node
/**
* Add one statement ({@code subj}, {@code pred}, {@code obj}, {@code context})
* in the Corese graph.
*
*
* @param subject Subject of the statement.
* @param predicate Predicate of the statement.
* @param object Object of the statement.
Expand Down Expand Up @@ -327,7 +338,7 @@ private boolean addEdgeToGraph(Node subject, Node predicate, Node object, Node c
* specified, statements with a context matching one of these will match. Note:
* to match statements without an associated context, specify the value null and
* explicitly cast it to type Resource.
*
*
* @param subject The subject of the statements to match, null to match
* statements with any subject.
* @param predicate The Predicate of the statements to match, null to match
Expand Down Expand Up @@ -394,4 +405,50 @@ public void remove() {
return new CoreseModelIterator(statements.iterator());
}

/**
* Serializes this CoreseModel to the specified OutputStream in a given RDF4J format.
* This method first converts the CoreseModel's statements into an
* org.eclipse.rdf4j.model.Model, then uses Rdf4jSerializationUtil for serialization.
*
* @param outputStream The OutputStream to write the serialized data to. Must not be null.
* @param formatString The string identifier of the desired RDF format (e.g., "turtle", "jsonld", "rdfxml"). Must not be null.
* @throws IOException If an I/O error occurs during serialization or if an unsupported Corese value type is encountered.
* @throws IllegalArgumentException If the provided formatString is not recognized by Rdf4jSerializationUtil.
* @throws NullPointerException If outputStream or formatString is null.
*/
public void serializeToRdf4jFormat(OutputStream outputStream, String formatString) throws IOException {
Objects.requireNonNull(outputStream, "OutputStream cannot be null");
Objects.requireNonNull(formatString, "Format string cannot be null");


org.eclipse.rdf4j.model.Model rdf4jModel = new TreeModel();

for (fr.inria.corese.core.next.api.Namespace ns : this.getNamespaces()) {
rdf4jModel.setNamespace(ns.getPrefix(), ns.getName());
}


for (Statement coreseStatement : this) {


org.eclipse.rdf4j.model.Resource rdf4jSubject = (org.eclipse.rdf4j.model.Resource) converter.valuetoRdf4jValue(converter.toCoreseNode(coreseStatement.getSubject()).getDatatypeValue());
org.eclipse.rdf4j.model.IRI rdf4jPredicate = (org.eclipse.rdf4j.model.IRI) converter.valuetoRdf4jValue(converter.toCoreseNode(coreseStatement.getPredicate()).getDatatypeValue());
org.eclipse.rdf4j.model.Value rdf4jObject = converter.valuetoRdf4jValue(converter.toCoreseNode(coreseStatement.getObject()).getDatatypeValue());

org.eclipse.rdf4j.model.Resource rdf4jContext = null;
if (coreseStatement.getContext() != null) {
rdf4jContext = converter.resourcetoRdf4jValueContext(converter.toCoreseNode(coreseStatement.getContext()).getDatatypeValue());
}


if (rdf4jContext != null) {
rdf4jModel.add(rdf4jSubject, rdf4jPredicate, rdf4jObject, rdf4jContext);
} else {
rdf4jModel.add(rdf4jSubject, rdf4jPredicate, rdf4jObject);
}
}


Rdf4jSerializationUtil.serialize(rdf4jModel, outputStream, formatString);
}
}
Loading