diff --git a/.gitignore b/.gitignore index a500424cd..c1877fba4 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,7 @@ target/ /dist/ /nbdist/ /.nb-gradle/ +.continue/ # Logs and coverage reports *.log @@ -82,7 +83,9 @@ gradle/gradle-daemon-jvm.properties # Other build directories and generated files /bin/ +/out/ # Fichiers de logs logs/ *.log +.sonarlint/ diff --git a/build.gradle.kts b/build.gradle.kts index 3d245eb25..b8e91e7e1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,25 +33,33 @@ sonar { } } +// === Generated sources directories === +val javaccGeneratedDir = layout.buildDirectory.dir("generated-src/javacc").get().asFile +val antlrGeneratedDir = layout.buildDirectory.dir("generated-src/antlr").get().asFile +val antlrPackageDir = layout.buildDirectory.dir("generated-src/antlr/fr/inria/corese/core/next/impl/parser/antlr").get().asFile + // JavaCC configuration javacc { configs { register("sparqlCorese") { inputFile = file("src/main/java/fr/inria/corese/core/sparql/triple/javacc1/sparql_corese.jj") packageName = "fr.inria.corese.core.sparql.triple.javacc1" + outputDir = javaccGeneratedDir } } } -// Ajoute les fichiers générés par JavaCC comme source Java +// Configure source sets to include generated sources sourceSets { main { java { - srcDir(layout.buildDirectory.dir("generated-src/javacc")) + srcDir(javaccGeneratedDir) + srcDir(antlrGeneratedDir) } } } +// Ensure JavaCC generation happens before compilation tasks.named("compileJava") { dependsOn("javaccSparqlCorese") } @@ -118,6 +126,13 @@ dependencies { antlr("org.antlr:antlr4:4.13.2") // Antlr for parsing (ANTLR 4) implementation("org.antlr:antlr4-runtime:4.13.2") // Antlr runtime for parsing + + // === JSONLD + implementation("com.apicatalog:titanium-json-ld:1.6.0") + implementation("com.apicatalog:titanium-rdf-api:1.0.0") + implementation("org.eclipse.parsson:parsson:1.1.7") + implementation("jakarta.json:jakarta.json-api:2.1.3") + // === HTTP and XML === implementation("org.glassfish.jersey.core:jersey-client:3.1.10") // HTTP client (Jersey) implementation("org.glassfish.jersey.inject:jersey-hk2:3.1.10") // Dependency injection for Jersey @@ -128,6 +143,8 @@ dependencies { implementation("org.json:json:20250517") // JSON processing implementation("com.typesafe:config:1.4.3") // Configuration library (Typesafe Config) + + // === Test dependencies === testImplementation(platform("org.junit:junit-bom:5.13.2")) // JUnit BOM for consistent test versions testImplementation("org.junit.jupiter:junit-jupiter:5.13.2") // JUnit Jupiter API and engine @@ -200,7 +217,7 @@ publishing { id.set("pierremaillot") name.set("Pierre Maillot") email.set("pierre.maillot@inria.fr") - url.set("https://maillpierre.github.io/personal-page/") + url.set("https://w3id.org/people/pierremaillot") organization.set("Inria") organizationUrl.set("http://www.inria.fr/") } @@ -329,34 +346,50 @@ tasks.withType().configureEach { // === Antlr generated sources configuration === -// Path where Antlr will generate sources -val generatedSourcesPath = "src/main/generated" - -// Add the generated sources directory to the main source set -sourceSets["main"].java.srcDir(file(generatedSourcesPath)) - // Configure the Antlr task to generate parser code with specific arguments tasks.named("generateGrammarSource") { arguments.addAll(listOf("-visitor", "-long-messages", "-package", "fr.inria.corese.core.next.impl.parser.antlr")) - outputDirectory = file("$buildDir/generated-src/antlr/main") - outputs.dirs(outputDirectory) + outputDirectory = antlrPackageDir + inputs.files(fileTree("src/main/antlr")) + outputs.dir(antlrPackageDir) } -// Ensure Java compilation depends on Antlr code generation +// Ensure Java compilation depends on both JavaCC and Antlr code generation tasks.named("compileJava") { - dependsOn("generateGrammarSource" /*, "copyAntlrGenerated" */) + dependsOn("generateGrammarSource", "javaccSparqlCorese") } -// Ensure sources JAR includes generated sources and depends on Antlr code generation +// Ensure sources JAR includes generated sources and depends on code generation tasks.named("sourcesJar") { - dependsOn("generateGrammarSource" /*, "copyAntlrGenerated" */) - from(generatedSourcesPath) + dependsOn("generateGrammarSource", "javaccSparqlCorese") + from(javaccGeneratedDir) + from(antlrGeneratedDir) includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } // Clean up generated sources on clean tasks.clean { doLast { - file(generatedSourcesPath).deleteRecursively() + delete(javaccGeneratedDir) + delete(antlrGeneratedDir) } } + +// Ensure generated directories exist before generation +tasks.register("createGeneratedDirs") { + doLast { + javaccGeneratedDir.mkdirs() + antlrGeneratedDir.mkdirs() + antlrPackageDir.mkdirs() + } +} + +// Make generation tasks depend on directory creation +tasks.named("generateGrammarSource") { + dependsOn("createGeneratedDirs") +} + +tasks.named("javaccSparqlCorese") { + dependsOn("createGeneratedDirs") +} diff --git a/src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java b/src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java deleted file mode 100644 index b30177181..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.inria.corese.core.next.api; - -import fr.inria.corese.core.next.impl.common.serialization.RdfFormat; - -/** - * Factory interface for creating {@link RdfSerializer} instances. - * This interface defines a contract for classes that are responsible - * for providing appropriate RDF serializers based on the desired - * {@link RdfFormat}, a {@link Model} to be serialized, and - * {@link SerializationConfig}. - * Implementations of this factory can manage the instantiation - * and configuration of various RDF serializers, promoting - * loose coupling and extensibility in the serialization process. - */ -public interface SerializerFactory { - - - RdfSerializer createSerializer(RdfFormat format, Model model, SerializationConfig config); -} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/AbstractIOOptions.java b/src/main/java/fr/inria/corese/core/next/api/base/io/AbstractIOOptions.java new file mode 100644 index 000000000..e8a820c58 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/AbstractIOOptions.java @@ -0,0 +1,17 @@ +package fr.inria.corese.core.next.api.base.io; + +import fr.inria.corese.core.next.api.io.IOOptions; + +/** + * Abstract class for parser/serializers that sets up the necessity of implementing a builder pattern. + */ +public abstract class AbstractIOOptions implements IOOptions { + + public abstract static class Builder< T extends IOOptions> { + protected Builder() { + + } + + public abstract T build(); + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/FileFormat.java b/src/main/java/fr/inria/corese/core/next/api/base/io/FileFormat.java similarity index 97% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/FileFormat.java rename to src/main/java/fr/inria/corese/core/next/api/base/io/FileFormat.java index 8242799b9..59867eaa2 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/FileFormat.java +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/FileFormat.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.api.base.io; import java.util.List; import java.util.Objects; diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormat.java b/src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java similarity index 87% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormat.java rename to src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java index 98dc9171d..bcd84f5a6 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormat.java +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.api.base.io; import java.util.List; import java.util.Locale; @@ -11,12 +11,12 @@ * This class also acts as a central registry for all known RDF formats, * providing static constants for common formats and utility methods for lookup. */ -public class RdfFormat extends FileFormat { +public class RDFFormat extends FileFormat { private final boolean supportsNamespaces; private final boolean supportsNamedGraphs; - public static final RdfFormat TURTLE = new RdfFormat( + public static final RDFFormat TURTLE = new RDFFormat( "Turtle", List.of("ttl"), List.of("text/turtle"), @@ -24,35 +24,35 @@ public class RdfFormat extends FileFormat { false); - public static final RdfFormat NTRIPLES = new RdfFormat( + public static final RDFFormat NTRIPLES = new RDFFormat( "N-Triples", List.of("nt"), List.of("application/n-triples", "text/plain"), false, false); - public static final RdfFormat NQUADS = new RdfFormat( + public static final RDFFormat NQUADS = new RDFFormat( "N-Quads", List.of("nq"), List.of("application/n-quads"), false, true); - public static final RdfFormat JSONLD = new RdfFormat( + public static final RDFFormat JSONLD = new RDFFormat( "JSON-LD", List.of("jsonld"), List.of("application/ld+json", "application/json"), true, true); - public static final RdfFormat RDFXML = new RdfFormat( + public static final RDFFormat RDFXML = new RDFFormat( "RDF/XML", List.of("rdf", "xml"), List.of("application/rdf+xml"), true, false); - public static final RdfFormat TRIG = new RdfFormat( + public static final RDFFormat TRIG = new RDFFormat( "TriG", List.of("trig"), List.of("application/trig"), @@ -70,7 +70,7 @@ public class RdfFormat extends FileFormat { * @param supportsNamedGraphs Whether the format supports named graphs. * serialization. */ - public RdfFormat( + public RDFFormat( String name, List extensions, List mimeTypes, @@ -104,7 +104,7 @@ public boolean supportsNamedGraphs() { * @param name The name of the format (e.g., "Turtle"). * @return An Optional containing the matching RdfFormat if found. */ - public static Optional byName(String name) { + public static Optional byName(String name) { String n = name.toLowerCase(Locale.ROOT); return all().stream() .filter(format -> format.getName().equalsIgnoreCase(n)) @@ -117,7 +117,7 @@ public static Optional byName(String name) { * @param extension The file extension (e.g., "ttl"). * @return An Optional containing the matching RdfFormat if found. */ - public static Optional byExtension(String extension) { + public static Optional byExtension(String extension) { String ext = extension.toLowerCase(Locale.ROOT); return all().stream() .filter(format -> format.getExtensions().stream() @@ -131,7 +131,7 @@ public static Optional byExtension(String extension) { * @param mimeType The MIME type (e.g., "text/turtle"). * @return An Optional containing the matching RdfFormat if found. */ - public static Optional byMimeType(String mimeType) { + public static Optional byMimeType(String mimeType) { String mime = mimeType.toLowerCase(Locale.ROOT); return all().stream() .filter(format -> format.getMimeTypes().stream() @@ -144,7 +144,7 @@ public static Optional byMimeType(String mimeType) { * * @return An unmodifiable List of all RdfFormat constants. */ - public static List all() { + public static List all() { return List.of(TURTLE, NTRIPLES, NQUADS, JSONLD, RDFXML, TRIG); } @@ -162,7 +162,7 @@ public String toString() { public boolean equals(Object obj) { if (this == obj) return true; - if (!(obj instanceof RdfFormat other)) + if (!(obj instanceof RDFFormat other)) return false; return getName().equalsIgnoreCase(other.getName()) && getExtensions().equals(other.getExtensions()) diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java new file mode 100644 index 000000000..d5016e189 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java @@ -0,0 +1,66 @@ +package fr.inria.corese.core.next.api.base.io.parser; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; +import fr.inria.corese.core.next.impl.exception.ParsingErrorException; + +import java.io.InputStream; +import java.io.Reader; +import java.util.Objects; + +/** + * Abstract class for RDFParser that set up the inner Model and ValueFactory + */ +public abstract class AbstractRDFParser implements RDFParser { + + private final Model model; + private final ValueFactory valueFactory; + private IOOptions config; + + public IOOptions getConfig() { + return config; + } + + public void setConfig(IOOptions config) { + this.config = config; + } + + protected AbstractRDFParser(Model model, ValueFactory factory) { + this(model, factory, null); + } + + protected AbstractRDFParser(Model model, ValueFactory factory, IOOptions config) { + Objects.requireNonNull(model); + Objects.requireNonNull(factory); + this.model = model; + this.valueFactory = factory; + this.config = config; + } + + @Override + public void parse(InputStream in) { + parse(in, null); + } + + @Override + public void parse(Reader reader) { + parse(reader, null); + } + + /** + * @return the model populated by the parser + */ + protected Model getModel() { + return model; + } + + /** + * @return the value factory used by the parser + */ + protected ValueFactory getValueFactory() { + return valueFactory; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParserFactory.java new file mode 100644 index 000000000..babc77fa8 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParserFactory.java @@ -0,0 +1,28 @@ +package fr.inria.corese.core.next.api.base.io.parser; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.api.io.parser.RDFParserFactory; + +/** + * Abstract base class for {@link RDFParserFactory}s. + */ +public abstract class AbstractRDFParserFactory implements RDFParserFactory { + + protected AbstractRDFParserFactory() { + } + + /** + * Creates a new RDF parser for the given RDF format and model. + * @param format The {@link RDFFormat} to use for parsing. + * @param model The {@link Model} to which the parsed data will be added. + * @param factory The {@link ValueFactory} factory to use for creating RDF values. + * @return + */ + @Override + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { + return createRDFParser(format, model, factory, null); + } +} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java deleted file mode 100644 index 379fba182..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.inria.corese.core.next.api.base.parser; - -import java.nio.charset.Charset; -import java.util.*; -import fr.inria.corese.core.next.api.IRI; - -public interface RDFFormat { - - /** - * Gets the name of this file format. - * - * @return A human-readable format name, e.g. "PLAIN TEXT". - */ - String getName(); - - - /** - * Gets the default MIME type for this file format. - * - * @return A MIME type string, e.g. "text/plain". - */ - String getDefaultMIMEType() ; - - - /** - * Checks if the specified MIME type matches the FileFormat's default MIME type. The MIME types are compared - * ignoring upper/lower-case differences. - * - * @param mimeType The MIME type to compare to the FileFormat's default MIME type. - * @return true if the specified MIME type matches the FileFormat's default MIME type. - */ - boolean hasDefaultMIMEType(String mimeType); - - /** - * Gets the file format's MIME types. - * - * @return An unmodifiable list of MIME type strings, e.g. "text/plain". - */ - List getMIMETypes(); - - - - /** - * Checks if specified MIME type matches one of the FileFormat's MIME types. The MIME types are compared ignoring - * upper/lower-case differences. - * - * @param mimeType The MIME type to compare to the FileFormat's MIME types. - * @return true if the specified MIME type matches one of the FileFormat's MIME types. - */ - boolean hasMIMEType(String mimeType); - - /** - * Gets the default file name extension for this file format. - * - * @return A file name extension (excluding the dot), e.g. "txt", or null if there is no common file - * extension for the format. - */ - String getDefaultFileExtension(); - - /** - * Checks if the specified file name extension matches the FileFormat's default file name extension. The file name - * extension MIME types are compared ignoring upper/lower-case differences. - * - * @param extension The file extension to compare to the FileFormat's file extension. - * @return true if the file format has a default file name extension and if it matches the specified - * extension, false otherwise. - */ - boolean hasDefaultFileExtension(String extension); - - /** - * Gets the file format's file extensions. - * - * @return An unmodifiable list of file extension strings, e.g. "txt". - */ - List getFileExtensions(); - - /** - * Checks if the FileFormat's file extension is equal to the specified file extension. The file extensions are - * compared ignoring upper/lower-case differences. - * - * @param extension The file extension to compare to the FileFormat's file extension. - * @return true if the specified file extension is equal to the FileFormat's file extension. - */ - boolean hasFileExtension(String extension); - - /** - * Get the (default) charset for this file format. - * - * @return the (default) charset for this file format, or null if this format does not have a default charset. - */ - Charset getCharset(); - - /** - * Checks if the FileFormat has a (default) charset. - * - * @return true if the FileFormat has a (default) charset. - */ - boolean hasCharset(); - - /** - * Return true if the RDFFormat supports the encoding of namespace/prefix information. - */ - boolean supportsNamespaces(); - - /** - * Return true if the RDFFormat supports the encoding of contexts/named graphs. - */ - boolean supportsContexts(); - - /** - * Return true if the RDFFormat supports the encoding of RDF-star triples natively. - */ - boolean supportsRDFStar(); -} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java deleted file mode 100644 index d8d99d8b0..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java +++ /dev/null @@ -1,255 +0,0 @@ -package fr.inria.corese.core.next.api.base.parser; - -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; - -public enum RDFFormats implements RDFFormat { - - TURTLE("Turtle", - List.of("text/turtle"), - List.of("ttl"), - true, - false, - false), - N3("N3", - List.of("text/n3"), - List.of("n3"), - true, - false, - false), - RDF_XML("RDF/XML", - List.of("application/rdf+xml"), - List.of("rdf", "xml"), - true, - false, - false), - JSON_LD("JSON-LD", - List.of("application/ld+json"), - List.of("jsonld", "json"), - true, - true, - false), - N_TRIPLES("N-Triples", - List.of("application/n-triples"), - List.of("nt"), - false, - false, - false), - TRIG("TriG", - List.of("application/trig"), - List.of("trig"), - true, - true, - false), - NQUADS("N-Quads", - List.of("application/n-quads"), - List.of("nq"), - true, - true, - false); - - private static final boolean DEFAULT_SUPPORTS_NAMESPACES = true; - private static final boolean DEFAULT_SUPPORTS_CONTEXTS = true; - private static final boolean DEFAULT_SUPPORTS_RDF_STAR = false; - - /** - * The file format human-readable name. - */ - private final String name; - - /** - * The file format's MIME types. The first item in the list is interpreted as the default MIME type for the format. - */ - private final List mimeTypes; - - /** - * The file format's (default) charset. - */ - private final Charset charset; - - /** - * The file format's file extensions. The first item in the list is interpreted as the default file extension for - * the format. - */ - private final List fileExtensions; - - /** - * Flag indicating whether the RDFFormat can encode namespace information. - */ - private final boolean supportsNamespaces; - - /** - * Flag indicating whether the RDFFormat can encode context information (ex: Graphs or quads). - */ - private final boolean supportsContexts; - - /** - * Flag indicating whether the RDFFormat can encode RDF-star triples natively. - */ - private final boolean supportsRDFStar; - - RDFFormats(String name, - List mimeTypes, - Charset charset, - List fileExtensions, - boolean supportsNamespaces, - boolean supportsContexts, - boolean supportsRDFStar) { - this.name = name; - this.mimeTypes = mimeTypes; - this.charset = charset; - this.fileExtensions = fileExtensions; - this.supportsNamespaces = supportsNamespaces; - this.supportsContexts = supportsContexts; - this.supportsRDFStar = supportsRDFStar; - } - - RDFFormats(String name, - List mimeTypes, - Charset charset, - List fileExtensions) { - this(name, mimeTypes, charset, fileExtensions, DEFAULT_SUPPORTS_NAMESPACES, DEFAULT_SUPPORTS_CONTEXTS, DEFAULT_SUPPORTS_RDF_STAR); - } - - RDFFormats(String name, - List mimeTypes, - List fileExtensions) { - this(name, mimeTypes, StandardCharsets.UTF_8, fileExtensions, DEFAULT_SUPPORTS_NAMESPACES, DEFAULT_SUPPORTS_CONTEXTS, DEFAULT_SUPPORTS_RDF_STAR); - } - - RDFFormats(String name, - List mimeTypes, - List fileExtensions, - boolean supportsNamespaces, - boolean supportsContexts, - boolean supportsRDFStar) { - this(name, mimeTypes, StandardCharsets.UTF_8, fileExtensions, supportsNamespaces, supportsContexts, supportsRDFStar); - } - - @Override - public String getName() { - return name; - } - - @Override - public String getDefaultMIMEType() { - return mimeTypes.get(0); - } - - @Override - public boolean hasDefaultMIMEType(String mimeType) { - return getDefaultMIMEType().equalsIgnoreCase(mimeType); - } - - @Override - public List getMIMETypes() { - return Collections.unmodifiableList(mimeTypes); - } - - @Override - public boolean hasMIMEType(String mimeType) { - if (mimeType == null) { - return false; - } - String type = mimeType; - if (mimeType.indexOf(';') > 0) { - type = mimeType.substring(0, mimeType.indexOf(';')); - } - for (String mt : this.mimeTypes) { - if (mt.equalsIgnoreCase(mimeType)) { - return true; - } - if (mimeType != type && mt.equalsIgnoreCase(type)) { - return true; - } - } - - return false; - } - - @Override - public String getDefaultFileExtension() { - if (fileExtensions.isEmpty()) { - return null; - } else { - return fileExtensions.get(0); - } - } - - @Override - public boolean hasDefaultFileExtension(String extension) { - String ext = getDefaultFileExtension(); - return ext != null && ext.equalsIgnoreCase(extension); - } - - @Override - public List getFileExtensions() { - return Collections.unmodifiableList(fileExtensions); - } - - @Override - public boolean hasFileExtension(String extension) { - for (String ext : fileExtensions) { - if (ext.equalsIgnoreCase(extension)) { - return true; - } - } - - return false; - } - - @Override - public Charset getCharset() { - return charset; - } - - @Override - public boolean hasCharset() { - return charset != null; - } - - @Override - public boolean supportsNamespaces() { - return supportsNamespaces; - } - - @Override - public boolean supportsContexts() { - return supportsContexts; - } - - @Override - public boolean supportsRDFStar() { - return supportsRDFStar; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64); - - sb.append(name); - - sb.append(" (mimeTypes="); - for (int i = 0; i < mimeTypes.size(); i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(mimeTypes.get(i)); - } - - sb.append("; ext="); - for (int i = 0; i < fileExtensions.size(); i++) { - if (i > 0) { - sb.append(", "); - } - sb.append(fileExtensions.get(i)); - } - - sb.append(")"); - - return sb.toString(); - } - -} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java deleted file mode 100644 index 9124ee5e8..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.inria.corese.core.next.api.base.parser; - -import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.ValueFactory; - -public interface RDFParserFactory { - - /** - * Creates a new RDF parser for the specified format and model. - * - * @param format The RDF format to use for parsing. - * @param model The model to which the parsed data will be added. - * @return A new instance of an RDF parser for the specified format and model. - */ - RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory); - -} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java new file mode 100644 index 000000000..f36446291 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java @@ -0,0 +1,7 @@ +package fr.inria.corese.core.next.api.io; + +/** + * Super-interface for configuration objects for IO operations (i.e. parsing, serialization). + */ +public interface IOOptions { +} diff --git a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java similarity index 75% rename from src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java rename to src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index cf8da275c..fab2aaebf 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -1,8 +1,17 @@ -package fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.IOOptions; import java.io.InputStream; import java.io.Reader; +/** + * An interface for parsing RDF data from an InputStream or Reader and adding statements to a model. + * + * @see RDFParserFactory + * @see RDFFormat + */ public interface RDFParser { /** @@ -10,6 +19,9 @@ public interface RDFParser { */ RDFFormat getRDFFormat(); + void setConfig(IOOptions config); + IOOptions getConfig(); + /** * Parses RDF data from the specified InputStream or Reader and adds it to the model. * diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserBaseIRIOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserBaseIRIOptions.java new file mode 100644 index 000000000..e593843fb --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserBaseIRIOptions.java @@ -0,0 +1,15 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.io.IOOptions; + +/** + * Options for RDF parsers that support a base IRI. + */ +public interface RDFParserBaseIRIOptions extends RDFParserOptions, IOOptions { + + /** + * + * @return the base IRI used to resolve relative IRIs + */ + String getBase(); +} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java new file mode 100644 index 000000000..c82293bb4 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java @@ -0,0 +1,32 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.base.io.RDFFormat; + +/** + * A factory for creating RDF parsers. + */ +public interface RDFParserFactory { + + + /** + * Creates a new RDF parser for the specified format and model. + * + * @param format The RDF format to use for parsing. + * @param model The model to which the parsed data will be added. + * @return A new instance of an RDF parser for the specified format and model. + */ + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory); + + /** + * Creates a new RDF parser for the specified format and model. + * @param format The RDF format to use for parsing. + * @param model The model to which the parsed data will be added. + * @param factory The value factory to use for creating RDF values. + * @param config The configuration to use for parsing. + * @return A new instance of an RDF parser for the specified format and model. + */ + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory, RDFParserOptions config); + +} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserOptions.java new file mode 100644 index 000000000..428c59c66 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserOptions.java @@ -0,0 +1,9 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.io.IOOptions; + +/** + * Options for RDF parsers + */ +public interface RDFParserOptions extends IOOptions { +} diff --git a/src/main/java/fr/inria/corese/core/next/api/RdfSerializer.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java similarity index 74% rename from src/main/java/fr/inria/corese/core/next/api/RdfSerializer.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java index 39d1f2dbc..6eb592a0e 100644 --- a/src/main/java/fr/inria/corese/core/next/api/RdfSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java @@ -1,20 +1,22 @@ -package fr.inria.corese.core.next.api; +package fr.inria.corese.core.next.api.io.serialization; +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.base.io.RDFFormat; import fr.inria.corese.core.next.impl.exception.SerializationException; import java.io.Writer; /** - * Factory interface for creating {@link RdfSerializer} instances. + * Factory interface for creating {@link RDFSerializer} instances. * This interface defines a contract for classes that are responsible * for providing appropriate RDF serializers based on the desired - * {@link fr.inria.corese.core.next.impl.common.serialization.RdfFormat}, a {@link Model} to be serialized, and - * {@link SerializationConfig}. + * {@link RDFFormat}, a {@link Model} to be serialized, and + * {@link SerializationOption}. * Implementations of this factory can manage the instantiation * and configuration of various RDF serializers, promoting * loose coupling and extensibility in the serialization process. */ -public interface RdfSerializer { +public interface RDFSerializer { /** * A serializer that converts a {@link Model} instance diff --git a/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java new file mode 100644 index 000000000..fe8f8257f --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java @@ -0,0 +1,12 @@ +package fr.inria.corese.core.next.api.io.serialization; + +/** + * Options for RDF parsers that support adding a prefix to blank nodes ids. + */ +public interface RDFSerializerBNPrefixOptions { + + /** + * @return the prefix used for blank nodes ids in the serialization. + */ + String getBlankNodePrefix(); +} diff --git a/src/main/java/fr/inria/corese/core/next/api/SerializationConfig.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java similarity index 82% rename from src/main/java/fr/inria/corese/core/next/api/SerializationConfig.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java index 47b9f8cbe..692dc6237 100644 --- a/src/main/java/fr/inria/corese/core/next/api/SerializationConfig.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.api; +package fr.inria.corese.core.next.api.io.serialization; /** @@ -9,6 +9,6 @@ * Implementations of this interface (e.g., SerializerConfig) will define the * specific parameters and settings relevant to a particular serialization process. */ -public interface SerializationConfig { +public interface SerializationOption { } diff --git a/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java new file mode 100644 index 000000000..594c4f87d --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java @@ -0,0 +1,20 @@ +package fr.inria.corese.core.next.api.io.serialization; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.base.io.RDFFormat; + +/** + * Factory interface for creating {@link RDFSerializer} instances. + * This interface defines a contract for classes that are responsible + * for providing appropriate RDF serializers based on the desired + * {@link RDFFormat}, a {@link Model} to be serialized, and + * {@link SerializationOption}. + * Implementations of this factory can manage the instantiation + * and configuration of various RDF serializers, promoting + * loose coupling and extensibility in the serialization process. + */ +public interface SerializerFactory { + + + RDFSerializer createSerializer(RDFFormat format, Model model, SerializationOption config); +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/config/CoreConfig.java b/src/main/java/fr/inria/corese/core/next/impl/config/CoreConfig.java index 5d2c05f92..230ce00f2 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/config/CoreConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/config/CoreConfig.java @@ -1,6 +1,7 @@ package fr.inria.corese.core.next.impl.config; -import com.typesafe.config.*; +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; /** * Configuration class for Corese Core diff --git a/src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java b/src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java index cc6bf4eee..1d948cbd7 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java +++ b/src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java @@ -1,6 +1,12 @@ package fr.inria.corese.core.next.impl.exception; -public class ParsingErrorException extends RuntimeException { + +import fr.inria.corese.core.next.api.base.exception.CoreseException; + +/** + * Exception thrown when an error occurs during parsing + */ +public class ParsingErrorException extends CoreseException { private static final long serialVersionUID = -2053549958572141648L; diff --git a/src/main/java/fr/inria/corese/core/next/impl/exception/SerializationException.java b/src/main/java/fr/inria/corese/core/next/impl/exception/SerializationException.java index ee622a195..87f8a0d6b 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/exception/SerializationException.java +++ b/src/main/java/fr/inria/corese/core/next/impl/exception/SerializationException.java @@ -1,15 +1,21 @@ package fr.inria.corese.core.next.impl.exception; +import fr.inria.corese.core.next.api.base.exception.CoreseException; + /** * Exception thrown during RDF serialization or deserialization failures. * This exception can carry format-specific details (e.g., NTriples, JSON-LD, XML, etc.), * as well as information about the location of the error within the data stream. */ -public class SerializationException extends Exception { +public class SerializationException extends CoreseException { private final String formatName; private final int lineNumber; private final int columnNumber; + public SerializationException(String message, String formatName) { + this(message, formatName, -1, -1, null); + } + /** * Constructs a new {@code SerializationException} with the specified detail message, * format name, and cause. Line and column numbers are set to -1 (unknown). diff --git a/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java b/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java index b44687d51..645f51d3a 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java +++ b/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java @@ -1,6 +1,11 @@ package fr.inria.corese.core.next.impl.exception; -public class UnsupportedFileFormatException extends Exception { +import fr.inria.corese.core.next.api.base.exception.CoreseException; + +/** + * Exception thrown when a file format is not supported. + */ +public class UnsupportedFileFormatException extends CoreseException { private static final long serialVersionUID = 7963163989802143570L; diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java b/src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java new file mode 100644 index 000000000..1663be302 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java @@ -0,0 +1,216 @@ +package fr.inria.corese.core.next.impl.io.option; + +import com.apicatalog.jsonld.JsonLdOptions; +import com.apicatalog.jsonld.JsonLdVersion; +import fr.inria.corese.core.next.api.IRI; +import fr.inria.corese.core.next.api.base.io.AbstractIOOptions; +import fr.inria.corese.core.next.api.io.parser.RDFParserBaseIRIOptions; +import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; + +import java.net.URI; +import java.time.Duration; + +/** + * Wrapper around the JsonLdOptions class for the Titanium JSONLD parser and serializer. + * @see JsonLdOptions + */ +public class TitaniumJSONLDProcessorOption extends AbstractIOOptions implements RDFParserOptions, RDFParserBaseIRIOptions { + + private final Builder builder; + + protected TitaniumJSONLDProcessorOption(Builder builder) { + this.builder = builder; + } + + /** + * @return it true, the serializer will compact arrays of length 1 with a single object item will be compacted to use only that object instead. See standard. + */ + public boolean compactsArrays() { + return this.builder.options.isCompactArrays(); + } + + /** + * @return if true, the serializer will compact IRIs to be relative to document base. See standard. + */ + public boolean compactsToRelative() { + return this.builder.options.isCompactToRelative(); + } + + /** + * @return If true, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary. See standard. + */ + public boolean isExtractAllScripts() { + return this.builder.options.isExtractAllScripts(); + } + + public boolean omitsDefault() { + return this.builder.options.isOmitDefault(); + } + + public boolean omitGraphs() { + return this.builder.options.isOmitGraph(); + } + + /** + * + * @return If true, the serializer will produce ordered JSON-LD. See standard. + */ + public boolean isOrdered() { + return this.builder.options.isOrdered(); + } + + /** + * + * @return the version of the JSON-LD standard used for processing. See standard. + */ + public JsonLdVersion getProcessingMode() { + return this.builder.options.getProcessingMode(); + } + + /** + * @return the processing timeout + */ + public Duration getTimeout() { + return this.builder.options.getTimeout(); + } + + /** + * @return If true, the serializer will produce JSON-LD using native types. See standard. + */ + public boolean usesNativeTypes() { + return this.builder.options.isUseNativeTypes(); + } + + /** + * @return If true, the serializer will produce JSON-LD using RDF type. See standard. + */ + public boolean usesRdfType() { + return this.builder.options.isUseRdfType(); + } + + /** + * + * @return the inner JsonLdOptions object. + */ + public JsonLdOptions getJsonLdOptions() { + return this.builder.options; + } + + @Override + public String getBase() { + return this.builder.options.getBase().toString(); + } + + public static class Builder extends AbstractIOOptions.Builder { + + private final JsonLdOptions options = new JsonLdOptions(); + + @Override + public TitaniumJSONLDProcessorOption build() { + return new TitaniumJSONLDProcessorOption(this); + } + + /** + * @param base the base IRI to use for resolving relative IRIs. + * @return this builder + */ + public Builder base(String base) { + this.options.setBase(URI.create(base)); + return this; + } + + /** + * @param baseIRI the base IRI to use for resolving relative IRIs. + * @return this builder + */ + public Builder base(IRI baseIRI) { + this.options.setBase(URI.create(baseIRI.stringValue())); + return this; + } + + /** + * + * @param compactArrays if true, arrays of length 1 with a single object item will be compacted to use only that object instead. + * @return this builder + */ + public Builder compactArrays(boolean compactArrays) { + this.options.setCompactArrays(compactArrays); + return this; + } + + /** + * @param compactToRelative if true, compact IRIs to be relative to document base. + * @return this builder + */ + public Builder compactToRelative(boolean compactToRelative) { + this.options.setCompactToRelative(compactToRelative); + return this; + } + + /** + * @param extractAllScripts If set to true, when extracting JSON-LD script elements from HTML, unless a specific fragment identifier is targeted, extracts all encountered JSON-LD script elements using an array form, if necessary. + * @return this builder + */ + public Builder extractAllScripts(boolean extractAllScripts) { + this.options.setExtractAllScripts(extractAllScripts); + return this; + } + + public Builder omitGraph(boolean omitGraph) { + this.options.setOmitGraph(omitGraph); + return this; + } + + public Builder omitDefault(boolean omitDefault) { + this.options.setOmitDefault(omitDefault); + return this; + } + + /** + * + * @param ordered If set to true, certain algorithm processing steps where indicated are ordered lexicographically. + * @return this builder + */ + public Builder ordered(boolean ordered) { + this.options.setOrdered(ordered); + return this; + } + + /** + * @param timeout the processing timeout. + * @return this builder + */ + public Builder timeout(Duration timeout) { + this.options.setTimeout(timeout); + return this; + } + + /** + * @param useRdfType if true, use rdf:type instead of @type in serialization. + * @return this builder + */ + public Builder useRdfType(boolean useRdfType) { + this.options.setUseRdfType(useRdfType); + return this; + } + + /** + * @param useNativeTypes Causes the Serialize RDF as JSON-LD Algorithm to use native JSON values in value objects avoiding the need for an explicitly @type. + * @return this builder + */ + public Builder useNativeTypes(boolean useNativeTypes) { + this.options.setUseNativeTypes(useNativeTypes); + return this; + } + + /** + * + * @param processingMode the version of the JSON-LD specification to use. + * @return this builder + */ + public Builder processingMode(JsonLdVersion processingMode) { + this.options.setProcessingMode(processingMode); + return this; + } + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java new file mode 100644 index 000000000..081cb1296 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java @@ -0,0 +1,56 @@ +package fr.inria.corese.core.next.impl.io.parser; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.base.io.parser.AbstractRDFParserFactory; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; +import fr.inria.corese.core.next.impl.io.parser.jsonld.JSONLDParser; +import fr.inria.corese.core.next.impl.io.parser.turtle.ANTLRTurtleParser; + +/** + * Factory class for creating RDF parsers. Generates according to the RDFFormat provided. + */ +public class ParserFactory extends AbstractRDFParserFactory { + + public ParserFactory() { + super(); + } + + /** + * Creates an RDF parser for the given format, model, value factory, and configuration. + * @param format The RDF format to use for parsing. + * @param model The model to which the parsed data will be added. + * @param factory The value factory to use for creating RDF values. + * @param config The configuration to use for parsing. + * @return An RDF parser for the given format, model, value factory, and configuration. + */ + @Override + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory, RDFParserOptions config) { + if(format == RDFFormat.JSONLD) { + return new JSONLDParser(model, factory, config); + } else if(format == RDFFormat.TURTLE) { + return new ANTLRTurtleParser(model, factory, config); + } + throw new IllegalArgumentException("Unsupported format: " + format); + } + + /** + * Creates an RDF parser for the given format, model, and value factory. + * @param format The {@link RDFFormat} to use for parsing. + * @param model The {@link Model} to which the parsed data will be added. + * @param factory The {@link ValueFactory} factory to use for creating RDF values. + * @return An RDF parser for the given format, model, and value factory. + */ + @Override + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { + if(format == RDFFormat.JSONLD) { + return new JSONLDParser(model, factory); + } else if(format == RDFFormat.TURTLE) { + return new ANTLRTurtleParser(model, factory); + } + throw new IllegalArgumentException("Unsupported format: " + format); + } + +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParser.java new file mode 100644 index 000000000..6a066e801 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParser.java @@ -0,0 +1,155 @@ +package fr.inria.corese.core.next.impl.io.parser.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.processor.ToRdfProcessor; +import com.apicatalog.rdf.api.RdfConsumerException; +import com.apicatalog.rdf.api.RdfQuadConsumer; +import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.base.io.parser.AbstractRDFParser; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.impl.common.literal.XSD; +import fr.inria.corese.core.next.impl.common.util.IRIUtils; +import fr.inria.corese.core.next.impl.exception.ParsingErrorException; +import fr.inria.corese.core.next.impl.io.option.TitaniumJSONLDProcessorOption; + +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; + +/** + * Parser for JSON-LD RDF files. This parser is based on the Titanium JSON-LD library. + * + * @see fr.inria.corese.core.next.impl.io.parser.ParserFactory + * @see Titanium JSON-LD + */ +public class JSONLDParser extends AbstractRDFParser { + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JSONLDParser.class); + + private static final String JSONLD_JAVA_DEFAULT_GRAPH = "@default"; + + public JSONLDParser(Model model, ValueFactory factory) { + super(model, factory, new TitaniumJSONLDProcessorOption.Builder().build()); + } + + public JSONLDParser(Model model, ValueFactory factory, IOOptions config) { + super(model, factory, config); + } + + @Override + public RDFFormat getRDFFormat() { + return RDFFormat.JSONLD; + } + + /** + * Parse the given input stream as JSON-LD. + * If baseURI is null, the base URI defined in the option for this parser will be used. + * @param in The InputStream to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + * @throws ParsingErrorException + */ + @Override + public void parse(InputStream in, String baseURI) { + try { + parseJSONLDDocument(JsonDocument.of(in), baseURI); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + /** + * Parse the given reader as JSON-LD. + * If baseURI is null, the base URI defined in the option for this parser will be used. + * @param reader The Reader to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + */ + @Override + public void parse(Reader reader, String baseURI) { + try { + parseJSONLDDocument(JsonDocument.of(reader), baseURI); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + private void parseJSONLDDocument(Document document, String baseURI) { + try { + JsonLdOptions options = new JsonLdOptions(); + if(this.getConfig() instanceof TitaniumJSONLDProcessorOption) { + options = ((TitaniumJSONLDProcessorOption) this.getConfig()).getJsonLdOptions(); + } + if(baseURI != null && !baseURI.isEmpty()) { + options.setBase(URI.create(baseURI)); + } + RdfQuadConsumer consumer = getConsumer(); + + ToRdfProcessor.toRdf(consumer, document, options); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + private RdfQuadConsumer getConsumer() { + return new RdfQuadConsumer() { + @Override + public RdfQuadConsumer quad(String subject, String predicate, String object, String datatype, String language, String direction, String graph) throws RdfConsumerException { + // Subject + Resource subjResource = null; + if (RdfQuadConsumer.isBlank(subject)) { + subjResource = getValueFactory().createBNode(subject); + } else { + subjResource = getValueFactory().createIRI(subject); + } + + IRI predicateIRI = getValueFactory().createIRI(predicate); + + // Object + Value objValue = null; + // Object is a BN + if (RdfQuadConsumer.isBlank(object)) { + objValue = getValueFactory().createBNode(object); + // Object is a Literal + } else if (RdfQuadConsumer.isLiteral(datatype, language, direction)) { + if (RdfQuadConsumer.isLangString(datatype, language, direction)) { + objValue = getValueFactory().createLiteral(object, language); + } else if( ! datatype.equals(XSD.STRING.toString()) ){ + objValue = getValueFactory().createLiteral(object, getValueFactory().createIRI(datatype)); + } else { + objValue = getValueFactory().createLiteral(object); + } + // Object is a IRI + } else if(IRIUtils.isStandardIRI(object)) { + objValue = getValueFactory().createIRI(object); + } else { + throw new RdfConsumerException("Invalid object: " + object); + } + + // Graph + Resource graphResource = null; + if(graph != null) { + if (RdfQuadConsumer.isBlank(graph)) { + graphResource = getValueFactory().createBNode(graph); + } else if (!graph.equals(JSONLD_JAVA_DEFAULT_GRAPH) && IRIUtils.isStandardIRI(graph)) { + graphResource = getValueFactory().createIRI(graph); + } else { + throw new ParsingErrorException("Invalid graph: " + graph); + } + } + + Statement statement = null; + if(graphResource == null) { + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue); + } else { + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue, graphResource); + } + getModel().add(statement); + + return this; + } + }; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java index 7fe167569..0d45617c4 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java @@ -1,10 +1,10 @@ package fr.inria.corese.core.next.impl.io.parser.turtle; import fr.inria.corese.core.next.api.ValueFactory; -import fr.inria.corese.core.next.api.base.parser.RDFParser; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.base.io.parser.AbstractRDFParser; import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.base.parser.RDFFormat; -import fr.inria.corese.core.next.api.base.parser.RDFFormats; +import fr.inria.corese.core.next.api.io.IOOptions; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; @@ -20,20 +20,40 @@ import java.io.InputStreamReader; import java.io.Reader; -public class ANTLRTurtleParser implements RDFParser { - - private final Model model; - private final RDFFormat format = RDFFormats.TURTLE; - private final ValueFactory factory; +/** + * Parser for Turtle RDF files. + * @see fr.inria.corese.core.next.impl.io.parser.ParserFactory + * @see Turtle + */ +public class ANTLRTurtleParser extends AbstractRDFParser { public ANTLRTurtleParser(Model model, ValueFactory factory) { - this.model = model; - this.factory = factory; + super(model, factory); + } + + public ANTLRTurtleParser(Model model, ValueFactory factory, IOOptions config) { + super(model, factory, config); } @Override public RDFFormat getRDFFormat() { - return format; + return RDFFormat.TURTLE; + } + + /** + * @param config we are not using any config in this parser implementation + */ + @Override + public void setConfig(IOOptions config) { + // nothing to do + } + + /** + * @return null, we are not using any config in this parser implementation + */ + @Override + public IOOptions getConfig() { + return null; } @Override @@ -66,7 +86,7 @@ public void parse(Reader reader, String baseURI) { TurtleParser parser = new TurtleParser(tokens); ParseTreeWalker walker = new ParseTreeWalker(); ParseTree tree = parser.turtleDoc(); - TurtleListenerImpl listener = new TurtleListenerImpl(model, baseURI, factory); + TurtleListenerImpl listener = new TurtleListenerImpl(getModel(), getValueFactory(), this.getConfig()); walker.walk((ParseTreeListener) listener, tree); diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java index ae3f28f95..684677b3e 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java @@ -1,21 +1,20 @@ package fr.inria.corese.core.next.impl.io.parser.turtle; import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.api.io.parser.RDFParserBaseIRIOptions; import fr.inria.corese.core.next.impl.common.literal.XSD; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; import fr.inria.corese.core.next.impl.parser.antlr.TurtleBaseListener; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; -import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; -import fr.inria.corese.core.next.impl.temp.CoreseIRI; import fr.inria.corese.core.next.impl.temp.ModelNamespace; -import fr.inria.corese.core.next.impl.temp.literal.CoreseBNode; -import org.antlr.v4.runtime.ParserRuleContext; -import org.antlr.v4.runtime.tree.ErrorNode; -import org.antlr.v4.runtime.tree.TerminalNode; import java.util.HashMap; import java.util.Map; +/** + * Listener for the ANTLR4 generated parser for Turtle. + */ public class TurtleListenerImpl extends TurtleBaseListener { private final Model model; @@ -26,9 +25,12 @@ public class TurtleListenerImpl extends TurtleBaseListener { private Resource currentSubject; private IRI currentPredicate; - public TurtleListenerImpl(Model model, String baseURI, ValueFactory factory) { + public TurtleListenerImpl(Model model, ValueFactory factory, IOOptions options) { this.model = model; - this.baseURI = baseURI != null ? baseURI : ""; + this.baseURI = ""; + if(options != null && options instanceof RDFParserBaseIRIOptions) { + this.baseURI = ((RDFParserBaseIRIOptions) options).getBase(); + } this.factory = factory; } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java deleted file mode 100644 index 1c9a9de66..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.inria.corese.core.next.impl.io.parser.turtle; - -import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.ValueFactory; -import fr.inria.corese.core.next.api.base.parser.RDFFormat; -import fr.inria.corese.core.next.api.base.parser.RDFFormats; -import fr.inria.corese.core.next.api.base.parser.RDFParser; -import fr.inria.corese.core.next.api.base.parser.RDFParserFactory; - -public class TurtleParserFactory implements RDFParserFactory { - - public TurtleParserFactory() { - super(); - } - - @Override - public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { - if (!format.equals(RDFFormats.TURTLE)) { - throw new IllegalArgumentException("Unsupported format : " + format); - } - return new ANTLRTurtleParser(model, factory); - } -} diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java similarity index 53% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactory.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java index 166badef4..ed7e35d65 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java @@ -1,10 +1,20 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.RdfSerializer; -import fr.inria.corese.core.next.api.SerializationConfig; -import fr.inria.corese.core.next.api.SerializerFactory; -import fr.inria.corese.core.next.impl.common.serialization.config.*; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.api.io.serialization.SerializationOption; +import fr.inria.corese.core.next.api.io.serialization.SerializerFactory; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsSerializer; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesSerializer; +import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlOption; +import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlSerializer; +import fr.inria.corese.core.next.impl.io.serialization.trig.TriGOption; +import fr.inria.corese.core.next.impl.io.serialization.trig.TriGSerializer; +import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleOption; +import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleSerializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,12 +26,12 @@ /** * Default implementation of {@link SerializerFactory}. - * This factory is responsible for creating instances of {@link RdfSerializer} - * based on the requested {@link RdfFormat}. It uses a registry pattern + * This factory is responsible for creating instances of {@link RDFSerializer} + * based on the requested {@link RDFFormat}. It uses a registry pattern * to map each format to its corresponding serializer constructor, * providing a flexible and extensible way to manage serializer instances. * - *

It adapts the generic {@link SerializationConfig} provided to the specific + *

It adapts the generic {@link SerializationOption} provided to the specific * configuration type expected by each serializer in the hierarchy, with a fallback * to default configurations if an incompatible type is provided.

*/ @@ -29,65 +39,65 @@ public class DefaultSerializerFactory implements SerializerFactory { private static final Logger logger = LoggerFactory.getLogger(DefaultSerializerFactory.class); - private final Map> registry; + private final Map> registry; /** * Constructs a {@code DefaultSerializerFactory} and populates its registry - * with constructors for all known {@link RdfFormat} implementations. - * Each constructor attempts to cast the generic {@link SerializationConfig} to the + * with constructors for all known {@link RDFFormat} implementations. + * Each constructor attempts to cast the generic {@link SerializationOption} to the * specific configuration type required by the serializer. If the cast is not possible, * it falls back to the format's default configuration. */ public DefaultSerializerFactory() { - Map> tempRegistry = new HashMap<>(); + Map> tempRegistry = new HashMap<>(); - tempRegistry.put(RdfFormat.TURTLE, (model, genericConfig) -> { - if (genericConfig instanceof TurtleConfig specificConfig) { + tempRegistry.put(RDFFormat.TURTLE, (model, genericConfig) -> { + if (genericConfig instanceof TurtleOption specificConfig) { return new TurtleSerializer(model, specificConfig); } else { logger.warn("Provided config for TURTLE is not TurtleConfig (was {}). Using default TurtleConfig.", genericConfig.getClass().getSimpleName()); - return new TurtleSerializer(model, TurtleConfig.defaultConfig()); + return new TurtleSerializer(model, TurtleOption.defaultConfig()); } }); - tempRegistry.put(RdfFormat.NTRIPLES, (model, genericConfig) -> { - if (genericConfig instanceof NTriplesConfig specificConfig) { + tempRegistry.put(RDFFormat.NTRIPLES, (model, genericConfig) -> { + if (genericConfig instanceof NTriplesOption specificConfig) { return new NTriplesSerializer(model, specificConfig); } else { logger.warn("Provided config for NTRIPLES is not NTriplesConfig (was {}). Using default NTriplesConfig.", genericConfig.getClass().getSimpleName()); - return new NTriplesSerializer(model, NTriplesConfig.defaultConfig()); + return new NTriplesSerializer(model, NTriplesOption.defaultConfig()); } }); - tempRegistry.put(RdfFormat.NQUADS, (model, genericConfig) -> { - if (genericConfig instanceof NQuadsConfig specificConfig) { + tempRegistry.put(RDFFormat.NQUADS, (model, genericConfig) -> { + if (genericConfig instanceof NQuadsOption specificConfig) { return new NQuadsSerializer(model, specificConfig); } else { logger.warn("Provided config for NQUADS is not NQuadsConfig (was {}). Using default NQuadsConfig.", genericConfig.getClass().getSimpleName()); - return new NQuadsSerializer(model, NQuadsConfig.defaultConfig()); + return new NQuadsSerializer(model, NQuadsOption.defaultConfig()); } }); - tempRegistry.put(RdfFormat.TRIG, (model, genericConfig) -> { - if (genericConfig instanceof TriGConfig specificConfig) { + tempRegistry.put(RDFFormat.TRIG, (model, genericConfig) -> { + if (genericConfig instanceof TriGOption specificConfig) { return new TriGSerializer(model, specificConfig); } else { logger.warn("Provided config for TRIG is not TriGConfig (was {}). Using default TriGConfig.", genericConfig.getClass().getSimpleName()); - return new TriGSerializer(model, TriGConfig.defaultConfig()); + return new TriGSerializer(model, TriGOption.defaultConfig()); } }); - tempRegistry.put(RdfFormat.RDFXML, (model, genericConfig) -> { - if (genericConfig instanceof XmlConfig specificConfig) { + tempRegistry.put(RDFFormat.RDFXML, (model, genericConfig) -> { + if (genericConfig instanceof XmlOption specificConfig) { return new XmlSerializer(model, specificConfig); } else { - logger.warn("Provided config for RDFXML is not RdfXmlConfig (was {}). Using default RdfXmlConfig.", + logger.warn("Provided config for RDFXML is not RDFXmlConfig (was {}). Using default RDFXmlConfig.", genericConfig.getClass().getSimpleName()); - return new XmlSerializer(model, XmlConfig.defaultConfig()); + return new XmlSerializer(model, XmlOption.defaultConfig()); } }); @@ -95,26 +105,26 @@ public DefaultSerializerFactory() { } /** - * Creates an {@link RdfSerializer} instance for the specified format, model, and configuration. + * Creates an {@link RDFSerializer} instance for the specified format, model, and configuration. * - * @param format the {@link RdfFormat} for which to create the serializer. Must not be null. + * @param format the {@link RDFFormat} for which to create the serializer. Must not be null. * @param model the {@link Model} to be serialized. Must not be null. - * @param config the {@link SerializationConfig} to apply during serialization. Must not be null. - * @return a new instance of {@link RdfSerializer} configured for the specified format. + * @param config the {@link SerializationOption} to apply during serialization. Must not be null. + * @return a new instance of {@link RDFSerializer} configured for the specified format. * @throws NullPointerException if any of the arguments (format, model, config) are null. * @throws IllegalArgumentException if the provided format is not supported by this factory. */ @Override - public RdfSerializer createSerializer(RdfFormat format, Model model, SerializationConfig config) { + public RDFSerializer createSerializer(RDFFormat format, Model model, SerializationOption config) { - Objects.requireNonNull(format, "RdfFormat cannot be null"); + Objects.requireNonNull(format, "RDFFormat cannot be null"); Objects.requireNonNull(model, "Model cannot be null"); Objects.requireNonNull(config, "SerializationConfig cannot be null"); - BiFunction constructor = registry.get(format); + BiFunction constructor = registry.get(format); if (constructor == null) { - throw new IllegalArgumentException("Unsupported RdfFormat: " + format.getName()); + throw new IllegalArgumentException("Unsupported RDFFormat: " + format.getName()); } return constructor.apply(model, config); diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractGraphSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractGraphSerializer.java similarity index 91% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractGraphSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractGraphSerializer.java index 2c091dd79..d38b98b71 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractGraphSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractGraphSerializer.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.impl.common.serialization.base; +package fr.inria.corese.core.next.impl.io.serialization.base; import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; import fr.inria.corese.core.next.impl.common.literal.RDF; -import fr.inria.corese.core.next.impl.common.serialization.config.*; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.*; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,11 +28,11 @@ * *

Note: Many features related to compact syntax, pretty-printing, and advanced * prefix management are specific to Turtle Trig formats and require the - * provided {@link AbstractSerializerConfig} to be an instance of - * {@link AbstractTFamilyConfig} at runtime. An {@link IllegalStateException} + * provided {@link AbstractSerializerOption} to be an instance of + * {@link AbstractSerializerOption} at runtime. An {@link IllegalStateException} * will be thrown if an incompatible configuration is used for such features.

*/ -public abstract class AbstractGraphSerializer implements RdfSerializer { +public abstract class AbstractGraphSerializer implements RDFSerializer { /** * Logger for this class, used to log potential issues or information during serialization. @@ -39,7 +40,7 @@ public abstract class AbstractGraphSerializer implements RdfSerializer { protected static final Logger logger = LoggerFactory.getLogger(AbstractGraphSerializer.class); protected final Model model; - protected final AbstractSerializerConfig config; + protected final AbstractSerializerOption option; protected final Map iriToPrefixMapping; protected final Map prefixToIriMapping; protected final Set consumedBlankNodes; @@ -49,12 +50,12 @@ public abstract class AbstractGraphSerializer implements RdfSerializer { * Constructs a new abstract TriG/Turtle serializer instance. * * @param model the {@link Model} to serialize. Must not be null. - * @param config the {@link AbstractSerializerConfig} to use for serialization. Must not be null. + * @param option the {@link AbstractSerializerOption} to use for serialization. Must not be null. * @throws NullPointerException if the provided model or configuration is null. */ - protected AbstractGraphSerializer(Model model, AbstractSerializerConfig config) { + protected AbstractGraphSerializer(Model model, AbstractSerializerOption option) { this.model = Objects.requireNonNull(model, "The model cannot be null"); - this.config = Objects.requireNonNull(config, "The configuration cannot be null"); + this.option = Objects.requireNonNull(option, "The configuration cannot be null"); this.iriToPrefixMapping = new HashMap<>(); this.prefixToIriMapping = new HashMap<>(); this.consumedBlankNodes = new HashSet<>(); @@ -69,20 +70,20 @@ protected AbstractGraphSerializer(Model model, AbstractSerializerConfig config) * @return The config cast to AbstractTFamilyConfig. * @throws IllegalStateException if the config is not an instance of AbstractTFamilyConfig. */ - private AbstractTFamilyConfig getTFamilyConfig() { - if (!(config instanceof AbstractTFamilyConfig)) { - throw new IllegalStateException("Current serializer configuration is not an instance of AbstractTFamilyConfig. " + + private AbstractTFamilyOption getTFamilyOption() { + if (!(option instanceof AbstractTFamilyOption)) { + throw new IllegalStateException("Current serializer configuration is not an instance of AbstractTFamilyOption. " + "Features like prefixes, compact syntax, and pretty-printing are only available for T-Family formats."); } - return (AbstractTFamilyConfig) config; + return (AbstractTFamilyOption) option; } /** * Initializes prefix mappings by adding custom prefixes from the configuration. */ private void initializePrefixes() { - if (config instanceof AbstractTFamilyConfig && getTFamilyConfig().usePrefixes()) { - for (Map.Entry entry : getTFamilyConfig().getCustomPrefixes().entrySet()) { + if (option instanceof AbstractTFamilyOption && getTFamilyOption().usePrefixes()) { + for (Map.Entry entry : getTFamilyOption().getCustomPrefixes().entrySet()) { addPrefixMapping(entry.getValue(), entry.getKey()); } } @@ -136,15 +137,15 @@ public void write(Writer writer) throws SerializationException { * @throws IOException if an I/O error occurs. */ protected void writeHeader(Writer writer) throws IOException { - if (config.getBaseIRI() != null) { + if (option.getBaseIRI() != null) { writer.write(String.format("@base <%s> .%s", - config.getBaseIRI(), - config.getLineEnding())); + option.getBaseIRI(), + option.getLineEnding())); } - if (config instanceof AbstractTFamilyConfig - && getTFamilyConfig().usePrefixes() - && getTFamilyConfig().autoDeclarePrefixes()) { + if (option instanceof AbstractSerializerOption + && getTFamilyOption().usePrefixes() + && getTFamilyOption().autoDeclarePrefixes()) { collectUsedNamespaces(); } @@ -156,7 +157,7 @@ && getTFamilyConfig().autoDeclarePrefixes()) { * if auto-declaration is enabled and they are not already mapped. */ protected void collectUsedNamespaces() { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractSerializerOption tFamilyConfig = getTFamilyOption(); Set namespaces = model.stream() .flatMap(stmt -> { @@ -192,7 +193,7 @@ protected void collectUsedNamespaces() { * @throws IOException if an I/O error occurs. */ protected void writePrefixDeclarations(Writer writer) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); List prefixes = new ArrayList<>(prefixToIriMapping.keySet()); @@ -204,11 +205,11 @@ protected void writePrefixDeclarations(Writer writer) throws IOException { writer.write(String.format("@prefix %s: <%s> .%s", prefix, prefixToIriMapping.get(prefix), - config.getLineEnding())); + option.getLineEnding())); } - if (!prefixes.isEmpty() || config.getBaseIRI() != null) { - writer.write(config.getLineEnding()); + if (!prefixes.isEmpty() || option.getBaseIRI() != null) { + writer.write(option.getLineEnding()); } } @@ -223,7 +224,7 @@ protected void writeSimpleStatements(Writer writer) throws IOException { for (Statement stmt : model) { if (!isConsumed(stmt.getSubject())) { writeStatement(writer, stmt); - writer.write(config.getLineEnding()); + writer.write(option.getLineEnding()); } } } @@ -237,7 +238,7 @@ protected void writeSimpleStatements(Writer writer) throws IOException { * @throws IOException if an I/O error occurs. */ protected void writeStatement(Writer writer, Statement stmt) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); String indent = tFamilyConfig.prettyPrint() ? tFamilyConfig.getIndent() : SerializationConstants.EMPTY_STRING; writer.write(indent); @@ -265,7 +266,7 @@ protected void writeStatement(Writer writer, Statement stmt) throws IOException * @throws IOException if an I/O error occurs. */ protected void writePredicate(Writer writer, Value predicate) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); if (tFamilyConfig.useRdfTypeShortcut() && predicate.stringValue().equals(SerializationConstants.RDF_TYPE)) { writer.write(SerializationConstants.RDF_TYPE_SHORTCUT); } else { @@ -301,11 +302,11 @@ protected void writeValue(Writer writer, Value value) throws IOException { currentlyWritingBlankNodes.add(bNode); boolean handled = false; - if (config instanceof AbstractTFamilyConfig && getTFamilyConfig().useCollections() && bNode.isBNode()) { + if (option instanceof AbstractSerializerOption && getTFamilyOption().useCollections() && bNode.isBNode()) { handled = writeRDFList(writer, bNode); } - if (!handled && config instanceof AbstractTFamilyConfig && getTFamilyConfig().getBlankNodeStyle() == BlankNodeStyleEnum.ANONYMOUS && bNode.isBNode()) { // getBlankNodeStyle is on AbstractTFamilyConfig + if (!handled && option instanceof AbstractSerializerOption && getTFamilyOption().getBlankNodeStyle() == BlankNodeStyleEnum.ANONYMOUS && bNode.isBNode()) { // getBlankNodeStyle is on AbstractTFamilyConfig List properties = model.stream() .filter(stmt -> stmt.getSubject().equals(bNode)) .toList(); @@ -335,12 +336,12 @@ protected void writeValue(Writer writer, Value value) throws IOException { * @throws IOException if an I/O error occurs. */ protected void writeIRI(Writer writer, IRI iri) throws IOException { - if (config.isStrictMode() && config.validateURIs()) { + if (option.isStrictMode() && option.validateURIs()) { validateIRI(iri); } String prefixed = null; - if (config instanceof AbstractTFamilyConfig && getTFamilyConfig().usePrefixes()) { + if (option instanceof AbstractSerializerOption && getTFamilyOption().usePrefixes()) { prefixed = getPrefixedName(iri.stringValue()); } @@ -364,8 +365,8 @@ protected void writeLiteral(Writer writer, Literal literal) throws IOException { String value = literal.stringValue(); boolean useTripleQuotes = false; - if (config instanceof AbstractTFamilyConfig) { - useTripleQuotes = getTFamilyConfig().shouldUseTripleQuotes(value); + if (option instanceof AbstractSerializerOption) { + useTripleQuotes = getTFamilyOption().shouldUseTripleQuotes(value); } @@ -417,9 +418,9 @@ protected boolean shouldWriteDatatype(Literal literal) { return false; } - return config.getLiteralDatatypePolicy() == LiteralDatatypePolicyEnum.ALWAYS_TYPED || + return option.getLiteralDatatypePolicy() == LiteralDatatypePolicyEnum.ALWAYS_TYPED || (!datatype.stringValue().equals(SerializationConstants.XSD_STRING) && - config.getLiteralDatatypePolicy() == LiteralDatatypePolicyEnum.MINIMAL); + option.getLiteralDatatypePolicy() == LiteralDatatypePolicyEnum.MINIMAL); } /** @@ -431,7 +432,7 @@ protected boolean shouldWriteDatatype(Literal literal) { * @throws IOException if an I/O error occurs. */ protected void writeInlineBlankNode(Writer writer, List properties) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); String currentIndent = tFamilyConfig.prettyPrint() ? tFamilyConfig.getIndent() : SerializationConstants.EMPTY_STRING; String propIndent = tFamilyConfig.prettyPrint() ? currentIndent + tFamilyConfig.getIndent() : ""; @@ -451,7 +452,7 @@ protected void writeInlineBlankNode(Writer writer, List properties) t firstProperty = false; if (tFamilyConfig.prettyPrint()) { - writer.write(config.getLineEnding() + propIndent); + writer.write(option.getLineEnding() + propIndent); } else { writer.write(SerializationConstants.SPACE); } @@ -462,7 +463,7 @@ protected void writeInlineBlankNode(Writer writer, List properties) t } if (tFamilyConfig.prettyPrint() && !properties.isEmpty() && !firstProperty) { - writer.write(config.getLineEnding() + currentIndent); + writer.write(option.getLineEnding() + currentIndent); } writer.write(SerializationConstants.BLANK_NODE_END); @@ -477,7 +478,7 @@ protected void writeInlineBlankNode(Writer writer, List properties) t * @throws IOException if an I/O error occurs. */ protected void writeOptimizedStatements(Writer writer) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); Map> bySubject = tFamilyConfig.sortSubjects() ? new TreeMap<>(Comparator.comparing(Resource::stringValue)) : @@ -504,7 +505,7 @@ protected void writeOptimizedStatements(Writer writer) throws IOException { if (!firstPredicate) { writer.write(SerializationConstants.SEMICOLON); if (tFamilyConfig.prettyPrint()) { - writer.write(config.getLineEnding() + indent + tFamilyConfig.getIndent()); + writer.write(option.getLineEnding() + indent + tFamilyConfig.getIndent()); } else { writer.write(SerializationConstants.SPACE); } @@ -519,7 +520,7 @@ protected void writeOptimizedStatements(Writer writer) throws IOException { if (!firstObject) { writer.write(SerializationConstants.COMMA); if (tFamilyConfig.prettyPrint()) { - writer.write(config.getLineEnding() + indent + tFamilyConfig.getIndent() + tFamilyConfig.getIndent()); + writer.write(option.getLineEnding() + indent + tFamilyConfig.getIndent() + tFamilyConfig.getIndent()); } else { writer.write(SerializationConstants.SPACE); } @@ -531,7 +532,7 @@ protected void writeOptimizedStatements(Writer writer) throws IOException { } writer.write(SerializationConstants.SPACE + SerializationConstants.POINT); - writer.write(config.getLineEnding()); + writer.write(option.getLineEnding()); } } @@ -545,7 +546,7 @@ protected void writeOptimizedStatements(Writer writer) throws IOException { * @throws IOException if an I/O error occurs. */ protected boolean writeRDFList(Writer writer, Resource listHead) throws IOException { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractSerializerOption tFamilyConfig = getTFamilyOption(); List items = new ArrayList<>(); Resource current = listHead; @@ -634,7 +635,7 @@ protected boolean isConsumed(Value value) { * @return A {@link Set} of {@link Resource} representing the blank nodes that will be serialized inline. */ protected Set precomputeInlineBlankNodesAndLists() { - AbstractTFamilyConfig tFamilyConfig = getTFamilyConfig(); + AbstractTFamilyOption tFamilyConfig = getTFamilyOption(); Set precomputed = new HashSet<>(); for (Statement stmt : model) { @@ -892,7 +893,7 @@ protected void validateValue(Value value) { throw new IllegalArgumentException("Value cannot be null in {} format when strictMode is enabled." + getFormatName()); } - if (config.isStrictMode() && value.isLiteral()) { + if (option.isStrictMode() && value.isLiteral()) { validateLiteral((Literal) value); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractLineBasedSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractLineBasedSerializer.java similarity index 96% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractLineBasedSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractLineBasedSerializer.java index 264501d26..5f3ae0be4 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/base/AbstractLineBasedSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/base/AbstractLineBasedSerializer.java @@ -1,11 +1,11 @@ -package fr.inria.corese.core.next.impl.common.serialization.base; +package fr.inria.corese.core.next.impl.io.serialization.base; import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; import fr.inria.corese.core.next.impl.common.literal.RDF; -// Changed import from SerializerConfig to AbstractSerializerConfig -import fr.inria.corese.core.next.impl.common.serialization.config.AbstractSerializerConfig; -import fr.inria.corese.core.next.impl.common.serialization.config.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractSerializerOption; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +23,7 @@ * Contains all the common logic for writing statements line by line. * Subclasses only need to implement how to handle the context part. */ -public abstract class AbstractLineBasedSerializer implements RdfSerializer { +public abstract class AbstractLineBasedSerializer implements RDFSerializer { /** * Logger for this class, used for logging potential issues or information during serialization. @@ -31,16 +31,16 @@ public abstract class AbstractLineBasedSerializer implements RdfSerializer { private static final Logger logger = LoggerFactory.getLogger(AbstractLineBasedSerializer.class); protected final Model model; - protected final AbstractSerializerConfig config; + protected final AbstractSerializerOption config; /** * Constructs a new line-based serializer. * * @param model the {@link Model} to be serialized. Must not be null. - * @param config the {@link AbstractSerializerConfig} to use for serialization. Must not be null. + * @param config the {@link AbstractSerializerOption} to use for serialization. Must not be null. * @throws NullPointerException if the provided model or config is null. */ - protected AbstractLineBasedSerializer(Model model, AbstractSerializerConfig config) { + protected AbstractLineBasedSerializer(Model model, AbstractSerializerOption config) { this.model = Objects.requireNonNull(model, "Model cannot be null"); this.config = Objects.requireNonNull(config, "Configuration cannot be null"); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java new file mode 100644 index 000000000..c654e00f4 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java @@ -0,0 +1,60 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import com.apicatalog.jsonld.JsonLd; +import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.api.FromRdfApi; +import com.apicatalog.jsonld.document.RdfDocument; +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.option.TitaniumJSONLDProcessorOption; + +import java.io.IOException; +import java.io.Writer; +import java.util.Objects; + +/** + * Serializer for JSON-LD format. This serializer uses the Titanium library. + * @see Titanium JSON-LD + */ +public class JSONLDSerializer implements RDFSerializer { + + private Model model; + private IOOptions config; + + /** + * Constructor. + * @param model the model to serialize + * @param config the options for the serialization + */ + public JSONLDSerializer(Model model, IOOptions config) { + this.model = Objects.requireNonNull(model); + this.config = Objects.requireNonNull(config); + } + + /** + * Constructor for a JSON-LD with default options. + * @param model + */ + public JSONLDSerializer(Model model) { + this(model, new TitaniumJSONLDProcessorOption.Builder().build()); + } + + @Override + public void write(Writer writer) throws SerializationException { + TitaniumRDFDatasetSerializationAdapter adapter = new TitaniumRDFDatasetSerializationAdapter(model); + + try { + FromRdfApi fromRdfApi = JsonLd.fromRdf(RdfDocument.of(adapter)); + if(this.config instanceof TitaniumJSONLDProcessorOption options) { + fromRdfApi.options(options.getJsonLdOptions()); + } + + jakarta.json.JsonArray jsonArray = fromRdfApi.get(); + writer.write(jsonArray.toString()); + } catch (JsonLdError | IOException e) { + throw new SerializationException("Error during serialization", "JSONLD", e); + } + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/TitaniumRDFDatasetSerializationAdapter.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/TitaniumRDFDatasetSerializationAdapter.java new file mode 100644 index 000000000..80dcffdb1 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/TitaniumRDFDatasetSerializationAdapter.java @@ -0,0 +1,477 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import com.apicatalog.rdf.*; +import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.literal.CoreDatatype; +import fr.inria.corese.core.next.impl.common.util.IRIUtils; +import fr.inria.corese.core.next.impl.common.vocabulary.RDF; +import fr.inria.corese.core.next.impl.common.vocabulary.XSD; +import fr.inria.corese.core.next.impl.exception.SerializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAmount; +import java.util.*; + +import static fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants.DEFAULT_GRAPH_IRI; + +/** + * Adapter class from Model to RdfDataset for usage in the JSON-LD serialization process using the titanium library. + * @see Titanium RDF API + */ +public class TitaniumRDFDatasetSerializationAdapter implements RdfDataset { + + private static final Logger logger = LoggerFactory.getLogger(TitaniumRDFDatasetSerializationAdapter.class); + private Model model; + + public TitaniumRDFDatasetSerializationAdapter(Model model) { + this.model = model; + } + + @Override + public RdfGraph getDefaultGraph() { + return new RdfGraph() { + @Override + public boolean contains(RdfTriple triple) { + return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject())); + } + + @Override + public List toList() { + return model.stream().map(TitaniumRDFDatasetSerializationAdapter.this::toRdfTriple).toList(); + } + }; + } + + @Override + public RdfDataset add(RdfNQuad nquad) { + return this; + } + + @Override + public RdfDataset add(RdfTriple triple) { + return this; + } + + @Override + public List toList() { + List resultStatement = this.model.stream().toList(); + return resultStatement.stream().map(this::toRdfNQuad).toList(); + } + + @Override + public Set getGraphNames() { + HashSet result = new HashSet<>(); + this.model.contexts().forEach(context -> { + if(context != null) { + result.add(toRdfResource(context)); + } + }); + return result; + } + + @Override + public Optional getGraph(RdfResource graphName) { + return Optional.of(new RdfGraph() { + @Override + public boolean contains(RdfTriple triple) { + Resource graphResource = null; + if (graphName != null && !graphName.getValue().equals(DEFAULT_GRAPH_IRI)) { + graphResource = toResource(graphName); + } + return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject()), graphResource); + } + + @Override + public List toList() { + List result = new ArrayList<>(); + Resource graphResource = null; + if (graphName != null && !graphName.getValue().equals(DEFAULT_GRAPH_IRI)) { + graphResource = toResource(graphName); + } + model.getStatements(null, null, null, graphResource).forEach(statement -> result.add(toRdfNQuad(statement))); + return result; + } + }); + } + + @Override + public int size() { + return this.model.size(); + } + + /** + * Converts a Corese statement to a titanium RDF NQuad + * @param statement the statement to convert + * @return the converted statement + */ + private RdfNQuad toRdfNQuad(Statement statement) { + return new RdfNQuad() { + @Override + public Optional getGraphName() { + return Optional.of(toRdfResource(statement.getContext())); + } + + @Override + public RdfResource getSubject() { + return toRdfResource(statement.getSubject()); + } + + @Override + public RdfResource getPredicate() { + return toRdfResource(statement.getPredicate()); + } + + @Override + public RdfValue getObject() { + return toRdfValue(statement.getObject()); + } + }; + } + + /** + * Converts a Corese statement to a titanium RDF triple + * @param statement the statement to convert + * @return the converted statement + */ + private RdfTriple toRdfTriple(Statement statement) { + return new RdfTriple() { + @Override + public RdfResource getSubject() { + return toRdfResource(statement.getSubject()); + } + + @Override + public RdfResource getPredicate() { + return toRdfResource(statement.getPredicate()); + } + + @Override + public RdfValue getObject() { + return toRdfValue(statement.getObject()); + } + }; + } + + /** + * Converts a Corese resource to a titanium RDF resource + * @param resource the resource to convert + * @return the converted resource + */ + private RdfResource toRdfResource(Resource resource) { + if (resource != null && (! (resource.isBNode() || resource.isIRI()))) { + throw new SerializationException("Unknown resource type " + resource, "JSON-LD"); + } else if (resource == null) { + return null; + } + return new RdfResource() { + @Override + public boolean isIRI() { + return resource.isIRI(); + } + + @Override + public boolean isBlankNode() { + return resource.isBNode(); + } + + @Override + public String getValue() { + return resource.stringValue(); + } + }; + } + + /** + * Converts a Corese value to a titanium RDF value + * @param value the value to convert + * @return the converted value + */ + private RdfValue toRdfValue(Value value) { + if (value.isIRI()) { + return toRdfIRI((IRI) value); + } else if (value.isBNode()) { + return toRdfBlankNode((BNode) value); + } else if (value.isLiteral()) { + return toRdfLiteral((Literal) value); + } else { + throw new SerializationException("Unknown value type " + value.stringValue(), "JSON-LD"); + } + } + + /** + * Converts a Corese IRI to a titanium RDF Resource + * @param iri the IRI to convert + * @return the converted IRI + */ + private RdfResource toRdfIRI(IRI iri) { + return new RdfResource() { + @Override + public boolean isIRI() { + return true; + } + @Override + public String getValue() { + return iri.stringValue(); + } + }; + } + + /** + * Converts a Corese BNode to a titanium RDF Resource + * @param bnode the BNode to convert + * @return the converted BNode + */ + private RdfResource toRdfBlankNode(BNode bnode) { + return new RdfResource() { + @Override + public boolean isBlankNode() { + return true; + } + @Override + public String getValue() { + return bnode.stringValue(); + } + }; + } + + /** + * Converts a Corese Literal to a titanium RDF Literal + * @param literal the Literal to convert + * @return the converted Literal + */ + private RdfLiteral toRdfLiteral(Literal literal) { + return new RdfLiteral() { + @Override + public boolean isLiteral() { + return true; + } + + @Override + public String getValue() { + return literal.getLabel(); + } + + @Override + public String getDatatype() { + if (literal.getDatatype() != null + && ! (literal.getDatatype().equals(XSD.xsdString.getIRI()) + || (literal.getDatatype().equals(RDF.langString.getIRI()) + && literal.getLanguage().isPresent()) + ) + ) { + return literal.getDatatype().stringValue(); + } else if (literal.getLanguage().isPresent()) { + return RDF.langString.getIRI().stringValue(); + } else { + return XSD.xsdString.getIRI().stringValue(); + } + } + + @Override + public Optional getLanguage() { + return literal.getLanguage(); + } + }; + } + + /** + * Convert a Titanium RdfValue to a Corese Value + * @param value the Titanium RdfValue + * @return the Corese Value + */ + private Value toValue(RdfValue value) { + if (value.isIRI()) { + return toIRI((RdfResource) value); + } else if (value.isLiteral()) { + return toLiteral((RdfLiteral) value); + } else if (value.isBlankNode()) { + return toBNode((RdfResource) value); + } else { + throw new SerializationException("Unknown value type " + value.getValue(), "JSON-LD"); + } + } + + /** + * Convert a Titanium RdfResource to a Corese Resource + * @param resource the Titanium RdfResource + * @return the Corese Resource + */ + private Resource toResource(RdfResource resource) { + if (resource.isIRI()) { + return toIRI(resource); + } else if (resource.isBlankNode()) { + return toBNode(resource); + } else { + throw new SerializationException("Unknown resource type " + resource.getValue(), "JSON-LD"); + } + } + + /** + * Convert a Titanium RdfResource to a Corese IRI + * @param resource the Titanium RdfResource + * @return the Corese IRI + */ + private IRI toIRI(RdfResource resource) { + if(resource.isIRI()) { + return stringToIRI(resource.getValue()); + } + return null; + } + + /** + * Convert a Titanium RdfResource to a Corese BNode + * @param resource the Titanium RdfResource + * @return the Corese BNode + */ + private BNode toBNode(RdfResource resource) { + if(resource.isBlankNode()) { + return new BNode() { + @Override + public String stringValue() { + return resource.getValue(); + } + + @Override + public String getID() { + return resource.getValue(); + } + }; + } + return null; + } + + /** + * Convert a Titanium RdfLiteral to a Corese Literal + * @param literal the Titanium RdfLiteral + * @return the Corese Literal + */ + private Literal toLiteral(RdfLiteral literal) { + return new Literal() { + @Override + public String stringValue() { + return literal.getValue(); + } + + @Override + public String getLabel() { + return literal.getValue(); + } + + @Override + public Optional getLanguage() { + return literal.getLanguage(); + } + + @Override + public IRI getDatatype() { + return stringToIRI(literal.getDatatype()); + } + + @Override + public boolean booleanValue() { + return literal.getValue().equalsIgnoreCase("true"); + } + + @Override + public byte byteValue() { + return Byte.parseByte(literal.getValue()); + } + + @Override + public short shortValue() { + return Short.parseShort(literal.getValue()); + } + + @Override + public int intValue() { + return Integer.parseInt(literal.getValue()); + } + + @Override + public long longValue() { + return Long.parseLong(literal.getValue()); + } + + @Override + public BigInteger integerValue() { + return BigInteger.valueOf(Long.parseLong(literal.getValue())); + } + + @Override + public BigDecimal decimalValue() { + return BigDecimal.valueOf(Double.parseDouble(literal.getValue())); + } + + @Override + public float floatValue() { + return Float.parseFloat(literal.getValue()); + } + + @Override + public double doubleValue() { + return Double.parseDouble(literal.getValue()); + } + + @Override + public TemporalAccessor temporalAccessorValue() { + return LocalDateTime.parse(literal.getValue()); + } + + @Override + public TemporalAmount temporalAmountValue() { + return Duration.parse(literal.getValue()); + } + + @Override + public XMLGregorianCalendar calendarValue() { + try { + return DatatypeFactory.newInstance().newXMLGregorianCalendar(literal.getValue()); + } catch (DatatypeConfigurationException e) { + throw new SerializationException("Literal couldn't be converted to XMLGregorianCalendar", "JSON-LD", e); + } + } + + @Override + public CoreDatatype getCoreDatatype() { + return () -> stringToIRI(literal.getDatatype()); + } + }; + } + + /** + * Converts a string to an IRI. + * + * @param iri the string to convert + * @return the IRI + */ + private IRI stringToIRI(String iri) { + if (iri == null || !IRIUtils.isStandardIRI(iri)) { + throw new SerializationException("Invalid IRI: " + iri, "JSON-LD"); + } + return new IRI() { + @Override + public String getNamespace() { + return IRIUtils.guessNamespace(iri); + } + + @Override + public String getLocalName() { + return IRIUtils.guessLocalName(iri); + } + + @Override + public String stringValue() { + return iri; + } + }; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOption.java similarity index 70% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOption.java index f39c1e630..577b52c74 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOption.java @@ -1,30 +1,32 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.nquads; + +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractNFamilyOption; /** * Configuration for N-Quads serialization format. - * This class extends {@link AbstractNFamilyConfig} and provides specific defaults + * This class extends {@link AbstractNFamilyOption} and provides specific defaults * and options tailored for N-Quads, which extends N-Quads with named graphs. * *

Use the {@link Builder} class to create instances of {@code NQuadsConfig}. * A predefined default configuration is available via {@link #defaultConfig()}.

*/ -public class NQuadsConfig extends AbstractNFamilyConfig { +public class NQuadsOption extends AbstractNFamilyOption { /** * Protected constructor to be used by the {@link Builder}. * * @param builder The builder instance containing the desired configuration values. */ - protected NQuadsConfig(Builder builder) { + protected NQuadsOption(Builder builder) { super(builder); } /** - * Public Builder for {@link NQuadsConfig}. + * Public Builder for {@link NQuadsOption}. * Provides a fluent API for constructing {@code NQuadsConfig} instances with default values * specific to the N-Quads format. */ - public static class Builder extends AbstractNFamilyConfig.AbstractNFamilyBuilder { + public static class Builder extends AbstractNFamilyOption.AbstractNFamilyBuilder { /** * Default constructor initializes all options with their default values for N-Quads. */ @@ -33,13 +35,13 @@ public Builder() { } /** - * Builds and returns a new {@link NQuadsConfig} instance with the current builder settings. + * Builds and returns a new {@link NQuadsOption} instance with the current builder settings. * * @return A new {@code NQuadsConfig} instance. */ @Override - public NQuadsConfig build() { - return new NQuadsConfig(this); + public NQuadsOption build() { + return new NQuadsOption(this); } } @@ -50,12 +52,12 @@ public NQuadsConfig build() { * * @return A {@code NQuadsConfig} instance with default settings. */ - public static NQuadsConfig defaultConfig() { + public static NQuadsOption defaultConfig() { return new Builder().build(); } /** - * Returns a new builder instance for {@link NQuadsConfig}. + * Returns a new builder instance for {@link NQuadsOption}. * This allows for fluent construction of custom N-Quads configurations. * * @return A new {@code Builder} instance. diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializer.java similarity index 82% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializer.java index af2a67c66..8ba08d2c2 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializer.java @@ -1,11 +1,11 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.nquads; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Resource; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.impl.common.serialization.base.AbstractLineBasedSerializer; -import fr.inria.corese.core.next.impl.common.serialization.config.NQuadsConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.base.AbstractLineBasedSerializer; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,24 +27,24 @@ public class NQuadsSerializer extends AbstractLineBasedSerializer { /** * Constructs a new {@code NQuadsSerializer} instance with the specified model and default N-Quads configuration. - * The default configuration is obtained from {@link NQuadsConfig#defaultConfig()}. + * The default configuration is obtained from {@link NQuadsOption#defaultConfig()}. * * @param model the {@link Model} to be serialized. Must not be null. * @throws NullPointerException if the provided model is null. */ public NQuadsSerializer(Model model) { - this(model, NQuadsConfig.defaultConfig()); + this(model, NQuadsOption.defaultConfig()); } /** * Constructs a new {@code NQuadsSerializer} instance with the specified model and custom configuration. * * @param model the {@link Model} to be serialized. Must not be null. - * @param config the {@link NQuadsConfig} to use for serialization. Must not be null. + * @param config the {@link NQuadsOption} to use for serialization. Must not be null. * This config object should be an instance of {@code NQuadsConfig} or a subclass thereof. * @throws NullPointerException if the provided model or config is null. */ - public NQuadsSerializer(Model model, NQuadsConfig config) { + public NQuadsSerializer(Model model, NQuadsOption config) { super(model, config); Objects.requireNonNull(config, "NQuadsConfig cannot be null"); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOption.java similarity index 66% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOption.java index b3818ed50..d67cc7a52 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOption.java @@ -1,30 +1,32 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; + +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractNFamilyOption; /** * Configuration for N-Triples serialization format. - * This class extends {@link AbstractNFamilyConfig} and provides specific defaults + * This class extends {@link AbstractNFamilyOption} and provides specific defaults * and options tailored for N-Triples, which is a simple, line-oriented format. * *

Use the {@link Builder} class to create instances of {@code NTriplesConfig}. * A predefined default configuration is available via {@link #defaultConfig()}.

*/ -public class NTriplesConfig extends AbstractNFamilyConfig { +public class NTriplesOption extends AbstractNFamilyOption { /** * Protected constructor to be used by the {@link Builder}. * * @param builder The builder instance containing the desired configuration values. */ - protected NTriplesConfig(Builder builder) { + protected NTriplesOption(Builder builder) { super(builder); } /** - * Public Builder for {@link NTriplesConfig}. + * Public Builder for {@link NTriplesOption}. * Provides a fluent API for constructing {@code NTriplesConfig} instances with default values * specific to the N-Triples format. */ - public static class Builder extends AbstractNFamilyConfig.AbstractNFamilyBuilder { + public static class Builder extends AbstractNFamilyOption.AbstractNFamilyBuilder { /** * Default constructor initializes all options with their default values for N-Triples. */ @@ -34,13 +36,13 @@ public Builder() { } /** - * Builds and returns a new {@link NTriplesConfig} instance with the current builder settings. + * Builds and returns a new {@link NTriplesOption} instance with the current builder settings. * * @return A new {@code NTriplesConfig} instance. */ @Override - public NTriplesConfig build() { - return new NTriplesConfig(this); + public NTriplesOption build() { + return new NTriplesOption(this); } } @@ -51,17 +53,17 @@ public NTriplesConfig build() { * * @return A {@code NTriplesConfig} instance with default settings. */ - public static NTriplesConfig defaultConfig() { + public static NTriplesOption defaultConfig() { return new Builder().build(); } /** - * Returns a new builder instance for {@link NTriplesConfig}. + * Returns a new builder instance for {@link NTriplesOption}. * This allows for fluent construction of custom N-Triples configurations. * * @return A new {@code Builder} instance. */ - public static NTriplesConfig.Builder builder() { - return new NTriplesConfig.Builder(); + public static NTriplesOption.Builder builder() { + return new NTriplesOption.Builder(); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializer.java similarity index 85% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializer.java index aaefc3f4f..fcd71b079 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializer.java @@ -1,10 +1,10 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Resource; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.impl.common.serialization.base.AbstractLineBasedSerializer; -import fr.inria.corese.core.next.impl.common.serialization.config.NTriplesConfig; +import fr.inria.corese.core.next.impl.io.serialization.base.AbstractLineBasedSerializer; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,24 +26,24 @@ public class NTriplesSerializer extends AbstractLineBasedSerializer { /** * Constructs a new {@code NTriplesSerializer} instance with the specified model and default configuration. - * The default configuration is obtained from {@link NTriplesConfig#defaultConfig()}. + * The default configuration is obtained from {@link NTriplesOption#defaultConfig()}. * * @param model the {@link Model} to be serialized. Must not be null. * @throws NullPointerException if the provided model is null. */ public NTriplesSerializer(Model model) { - this(model, NTriplesConfig.defaultConfig()); + this(model, NTriplesOption.defaultConfig()); } /** * Constructs a new {@code NTriplesSerializer} instance with the specified model and custom configuration. * * @param model the {@link Model} to be serialized. Must not be null. - * @param config the {@link NTriplesConfig} to use for serialization. Must not be null. + * @param config the {@link NTriplesOption} to use for serialization. Must not be null. * This config object should be an instance of {@code NTriplesConfig} or a subclass thereof. * @throws NullPointerException if the provided model or config is null. */ - public NTriplesSerializer(Model model, NTriplesConfig config) { + public NTriplesSerializer(Model model, NTriplesOption config) { super(model, config); Objects.requireNonNull(config, "NTriplesConfig cannot be null"); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractNFamilyConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractNFamilyOption.java similarity index 80% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractNFamilyConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractNFamilyOption.java index 34f6f3d61..0ebf8efc3 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractNFamilyConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractNFamilyOption.java @@ -1,8 +1,8 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; /** * An abstract base class for serialization configurations of N-Family RDF formats (e.g., N-Triples, N-Quads). - * This class extends {@link AbstractSerializerConfig} and provides a common foundation + * This class extends {@link AbstractSerializerOption} and provides a common foundation * for formats that typically have simpler, line-based structures and specific default behaviors * regarding literal datatypes and character escaping. * @@ -10,7 +10,7 @@ * nested {@link AbstractNFamilyBuilder}. Subclasses are expected to extend this * configuration and its builder to add format-specific options.

*/ -public abstract class AbstractNFamilyConfig extends AbstractSerializerConfig { +public abstract class AbstractNFamilyOption extends AbstractSerializerOption { /** * Protected constructor to be used by concrete builder implementations. @@ -19,14 +19,14 @@ public abstract class AbstractNFamilyConfig extends AbstractSerializerConfig { * * @param builder The builder instance containing the desired configuration values. */ - protected AbstractNFamilyConfig(AbstractNFamilyBuilder builder) { + protected AbstractNFamilyOption(AbstractNFamilyBuilder builder) { super(builder); } /** - * An abstract base builder for {@link AbstractNFamilyConfig}. + * An abstract base builder for {@link AbstractNFamilyOption}. * This builder provides methods for setting N-Family serialization configuration options. - * It extends {@link AbstractSerializerConfig.AbstractBuilder} and uses a recursive type + * It extends {@link AbstractSerializerOption.AbstractBuilder} and uses a recursive type * parameter (`S`) to allow concrete subclass builders to return their own specific type, * enabling fluent API chaining. * @@ -36,7 +36,7 @@ protected AbstractNFamilyConfig(AbstractNFamilyBuilder builder) { * @param The type of the concrete builder extending this abstract builder. */ public abstract static class AbstractNFamilyBuilder> - extends AbstractSerializerConfig.AbstractBuilder { + extends AbstractSerializerOption.AbstractBuilder { /** * Default constructor for the builder. @@ -52,11 +52,11 @@ protected AbstractNFamilyBuilder() { } /** - * Builds and returns a new {@link AbstractNFamilyConfig} instance with the current builder settings. + * Builds and returns a new {@link AbstractNFamilyOption} instance with the current builder settings. * This method must be implemented by concrete builder subclasses to return their specific configuration type. * * @return A new {@code AbstractNFamilyConfig} instance or a subclass instance. */ - public abstract AbstractNFamilyConfig build(); + public abstract AbstractNFamilyOption build(); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractSerializerConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java similarity index 94% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractSerializerConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java index 6ed99d68e..e1a51ef5b 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractSerializerConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java @@ -1,7 +1,7 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; -import fr.inria.corese.core.next.api.SerializationConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.api.io.serialization.SerializationOption; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.util.Objects; @@ -14,7 +14,7 @@ * nested {@link AbstractBuilder}. Subclasses are expected to extend this * configuration and its builder to add format-specific options.

*/ -public abstract class AbstractSerializerConfig implements SerializationConfig { +public abstract class AbstractSerializerOption implements SerializationOption { /** * The policy for how literal datatypes are printed. @@ -71,7 +71,7 @@ public abstract class AbstractSerializerConfig implements SerializationConfig { * @param builder The builder instance containing the desired configuration values. * @throws NullPointerException if any required field from the builder is null. */ - protected AbstractSerializerConfig(AbstractBuilder builder) { + protected AbstractSerializerOption(AbstractBuilder builder) { this.literalDatatypePolicy = Objects.requireNonNull(builder.literalDatatypePolicy, "Literal datatype policy cannot be null"); this.escapeUnicode = builder.escapeUnicode; this.trailingDot = builder.trailingDot; @@ -168,7 +168,7 @@ public boolean includeContext() { } /** - * An abstract base builder for {@link AbstractSerializerConfig}. + * An abstract base builder for {@link AbstractSerializerOption}. * This builder provides methods for setting common serialization configuration options. * It uses a recursive type parameter (`S`) to allow concrete subclass builders * to return their own specific type, enabling fluent API chaining. @@ -289,12 +289,12 @@ public S includeContext(boolean include) { } /** - * Builds and returns a new {@link AbstractSerializerConfig} instance with the current builder settings. + * Builds and returns a new {@link AbstractSerializerOption} instance with the current builder settings. * This method must be implemented by concrete builder subclasses to return their specific configuration type. * * @return A new {@code AbstractSerializerConfig} instance or a subclass instance. */ - public abstract AbstractSerializerConfig build(); + public abstract AbstractSerializerOption build(); /** * Helper method to return the concrete builder instance for fluent API chaining. diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractTFamilyConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractTFamilyOption.java similarity index 96% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractTFamilyConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractTFamilyOption.java index 4c22d8805..ca15e9787 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/AbstractTFamilyConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractTFamilyOption.java @@ -1,6 +1,6 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.util.Collections; import java.util.HashMap; @@ -9,14 +9,14 @@ /** * An abstract base class for serialization configurations of Turtle Trig RDF formats (e.g., Turtle, TriG). - * This class extends {@link AbstractSerializerConfig} and introduces parameters specific to + * This class extends {@link AbstractSerializerOption} and introduces parameters specific to * formats that utilize syntax sugar, pretty-printing, and collection syntax. * *

It enforces the use of the Builder pattern for construction through its * nested {@link AbstractTFamilyBuilder}. Subclasses are expected to extend this * configuration and its builder to add format-specific options.

*/ -public abstract class AbstractTFamilyConfig extends AbstractSerializerConfig { +public abstract class AbstractTFamilyOption extends AbstractSerializerOption { /** * Whether prefix declarations (e.g., `@prefix`, `PREFIX`) should be used for compact IRIs. @@ -105,7 +105,7 @@ public abstract class AbstractTFamilyConfig extends AbstractSerializerConfig { * @throws NullPointerException if any required field from the builder is null. * @throws IllegalArgumentException if incompatible options (e.g., escapeUnicode and useMultilineLiterals) are enabled. */ - protected AbstractTFamilyConfig(AbstractTFamilyBuilder builder) { + protected AbstractTFamilyOption(AbstractTFamilyBuilder builder) { super(builder); this.usePrefixes = builder.usePrefixes; @@ -297,16 +297,16 @@ public boolean shouldUseInlineBlankNodes() { } /** - * An abstract base builder for {@link AbstractTFamilyConfig}. + * An abstract base builder for {@link AbstractTFamilyOption}. * This builder provides methods for setting Turtle Trig serialization configuration options. - * It extends {@link AbstractSerializerConfig.AbstractBuilder} and uses a recursive type + * It extends {@link AbstractSerializerOption.AbstractBuilder} and uses a recursive type * parameter (`S`) to allow concrete subclass builders to return their own specific type, * enabling fluent API chaining. * * @param The type of the concrete builder extending this abstract builder. */ public abstract static class AbstractTFamilyBuilder> - extends AbstractSerializerConfig.AbstractBuilder { + extends AbstractSerializerOption.AbstractBuilder { protected boolean usePrefixes = true; protected boolean autoDeclarePrefixes = true; @@ -515,11 +515,11 @@ public S sortPredicates(boolean sortPredicates) { } /** - * Builds and returns a new {@link AbstractTFamilyConfig} instance with the current builder settings. + * Builds and returns a new {@link AbstractTFamilyOption} instance with the current builder settings. * This method must be implemented by concrete builder subclasses to return their specific configuration type. * * @return A new {@code AbstractTFamilyConfig} instance or a subclass instance. */ - public abstract AbstractTFamilyConfig build(); + public abstract AbstractTFamilyOption build(); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/BlankNodeStyleEnum.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/BlankNodeStyleEnum.java similarity index 82% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/BlankNodeStyleEnum.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/BlankNodeStyleEnum.java index ef04f0744..996901cd8 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/BlankNodeStyleEnum.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/BlankNodeStyleEnum.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; /** * Defines the style for serializing blank nodes. diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/LiteralDatatypePolicyEnum.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/LiteralDatatypePolicyEnum.java similarity index 86% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/LiteralDatatypePolicyEnum.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/LiteralDatatypePolicyEnum.java index b79a60eb0..3f4d80807 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/LiteralDatatypePolicyEnum.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/LiteralDatatypePolicyEnum.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; /** * Defines the policy for serializing literal datatypes. diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/PrefixOrderingEnum.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/PrefixOrderingEnum.java similarity index 86% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/PrefixOrderingEnum.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/PrefixOrderingEnum.java index 76f0aa6c1..9a45b7f28 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/PrefixOrderingEnum.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/PrefixOrderingEnum.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.option; /** * Defines the ordering policy for prefix declarations. diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlOption.java similarity index 93% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlOption.java index 37aba7e28..38c297fc2 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlOption.java @@ -1,6 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.rdfxml; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractSerializerOption; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.util.Collections; import java.util.HashMap; @@ -9,13 +12,13 @@ /** * Configuration for RDF/XML serialization format. - * This class extends {@link AbstractSerializerConfig} directly as RDF/XML has + * This class extends {@link AbstractSerializerOption} directly as RDF/XML has * distinct serialization characteristics not shared by the Turtle or N-Family formats. * *

Use the {@link Builder} class to create instances of {@code XmlConfig}. * A predefined default configuration is available via {@link #defaultConfig()}.

*/ -public class XmlConfig extends AbstractSerializerConfig { +public class XmlOption extends AbstractSerializerOption { /** * Whether prefix declarations (e.g., `xmlns:prefix="uri"`) should be used for compact IRIs. @@ -75,7 +78,7 @@ public class XmlConfig extends AbstractSerializerConfig { * * @param builder The builder instance containing the desired configuration values. */ - protected XmlConfig(Builder builder) { + protected XmlOption(Builder builder) { super(builder); this.usePrefixes = builder.usePrefixes; @@ -183,11 +186,11 @@ public boolean useMultilineLiterals() { /** - * Public Builder for {@link XmlConfig}. + * Public Builder for {@link XmlOption}. * Provides a fluent API for constructing {@code XmlConfig} instances with default values * specific to the RDF/XML format. */ - public static class Builder extends AbstractSerializerConfig.AbstractBuilder { + public static class Builder extends AbstractSerializerOption.AbstractBuilder { protected boolean usePrefixes = true; protected boolean autoDeclarePrefixes = true; protected PrefixOrderingEnum prefixOrdering = PrefixOrderingEnum.ALPHABETICAL; @@ -347,13 +350,13 @@ public Builder useMultilineLiterals(boolean useMultilineLiterals) { } /** - * Builds and returns a new {@link XmlConfig} instance with the current builder settings. + * Builds and returns a new {@link XmlOption} instance with the current builder settings. * * @return A new {@code XmlConfig} instance. */ @Override - public XmlConfig build() { - return new XmlConfig(this); + public XmlOption build() { + return new XmlOption(this); } } @@ -364,7 +367,7 @@ public XmlConfig build() { * * @return A {@code XmlConfig} instance with default settings. */ - public static XmlConfig defaultConfig() { + public static XmlOption defaultConfig() { return new Builder().build(); } } \ No newline at end of file diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializer.java similarity index 96% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializer.java index b79e9d3d1..e61d61aaa 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializer.java @@ -1,10 +1,10 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.rdfxml; import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.impl.common.serialization.config.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.PrefixOrderingEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.XmlConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,12 +32,12 @@ *

Advanced features such as handling XML schemata, specific RDF/XML graph structures (e.g., rdf:Bag, rdf:Seq, rdf:Alt), * and full blank node syntax optimization are simplified in this version.

*/ -public class XmlSerializer implements RdfSerializer { +public class XmlSerializer implements RDFSerializer { private static final Logger logger = LoggerFactory.getLogger(XmlSerializer.class); private final Model model; - private final XmlConfig config; + private final XmlOption config; private final Map iriToPrefixMapping; private final Map prefixToIriMapping; private final Map blankNodeIds; @@ -46,23 +46,23 @@ public class XmlSerializer implements RdfSerializer { /** * Constructs a new {@code XmlSerializer} instance with the specified model and default configuration. - * The default configuration is obtained from {@link XmlConfig#defaultConfig()}. + * The default configuration is obtained from {@link XmlOption#defaultConfig()}. * * @param model the {@link Model} to serialize. Must not be null. * @throws NullPointerException if the provided model is null. */ public XmlSerializer(Model model) { - this(model, XmlConfig.defaultConfig()); + this(model, XmlOption.defaultConfig()); } /** * Constructs a new {@code XmlSerializer} instance with the specified model and custom configuration. * * @param model the {@link Model} to serialize. Must not be null. - * @param config the {@link XmlConfig} to use for serialization. Must not be null. + * @param config the {@link XmlOption} to use for serialization. Must not be null. * @throws NullPointerException if the provided model or configuration is null. */ - public XmlSerializer(Model model, XmlConfig config) { + public XmlSerializer(Model model, XmlOption config) { this.model = Objects.requireNonNull(model, "Model cannot be null"); this.config = Objects.requireNonNull(config, "Configuration cannot be null"); this.iriToPrefixMapping = new HashMap<>(); diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOption.java similarity index 69% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOption.java index aa0a2821c..de84a78dc 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOption.java @@ -1,35 +1,37 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.trig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractTFamilyOption; +import fr.inria.corese.core.next.impl.io.serialization.option.BlankNodeStyleEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.util.HashMap; import java.util.Map; /** * Configuration for TriG serialization format. - * This class extends {@link AbstractTFamilyConfig} and provides specific defaults + * This class extends {@link AbstractTFamilyOption} and provides specific defaults * and options tailored for TriG, which extends Turtle with named graphs. * *

Use the {@link Builder} class to create instances of {@code TriGConfig}. * A predefined default configuration is available via {@link #defaultConfig()}.

*/ -public class TriGConfig extends AbstractTFamilyConfig { +public class TriGOption extends AbstractTFamilyOption { /** * Protected constructor to be used by the {@link Builder}. * * @param builder The builder instance containing the desired configuration values. */ - protected TriGConfig(Builder builder) { + protected TriGOption(Builder builder) { super(builder); } /** - * Public Builder for {@link TriGConfig}. + * Public Builder for {@link TriGOption}. * Provides a fluent API for constructing {@code TriGConfig} instances with default values * specific to the TriG format. */ - public static class Builder extends AbstractTFamilyConfig.AbstractTFamilyBuilder { + public static class Builder extends AbstractTFamilyOption.AbstractTFamilyBuilder { /** * Default constructor initializes all options with their default values for TriG. */ @@ -48,13 +50,13 @@ public Builder() { } /** - * Builds and returns a new {@link TriGConfig} instance with the current builder settings. + * Builds and returns a new {@link TriGOption} instance with the current builder settings. * * @return A new {@code TriGConfig} instance. */ @Override - public TriGConfig build() { - return new TriGConfig(this); + public TriGOption build() { + return new TriGOption(this); } } @@ -65,17 +67,17 @@ public TriGConfig build() { * * @return A {@code TriGConfig} instance with default settings. */ - public static TriGConfig defaultConfig() { + public static TriGOption defaultConfig() { return new Builder().build(); } /** - * Returns a new builder instance for {@link TriGConfig}. + * Returns a new builder instance for {@link TriGOption}. * This allows for fluent construction of custom TriG configurations. * * @return A new {@code Builder} instance. */ - public static TriGConfig.Builder builder() { - return new TriGConfig.Builder(); + public static TriGOption.Builder builder() { + return new TriGOption.Builder(); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializer.java similarity index 93% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializer.java index d68303ff2..4fe2d9605 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializer.java @@ -1,12 +1,11 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.trig; import fr.inria.corese.core.next.api.IRI; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Resource; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.impl.common.serialization.base.AbstractGraphSerializer; -import fr.inria.corese.core.next.impl.common.serialization.config.TriGConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.base.AbstractGraphSerializer; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.io.IOException; import java.io.Writer; @@ -38,24 +37,24 @@ public class TriGSerializer extends AbstractGraphSerializer { /** * Constructs a new {@code TriGSerializer} instance with the specified model and default configuration. - * The default configuration is returned by {@link TriGConfig#defaultConfig()}. + * The default configuration is returned by {@link TriGOption#defaultConfig()}. * * @param model the {@link Model} to serialize. Must not be null. * @throws NullPointerException if the provided model is null. */ public TriGSerializer(Model model) { - this(model, TriGConfig.defaultConfig()); + this(model, TriGOption.defaultConfig()); } /** * Constructs a new {@code TriGSerializer} instance with the specified model and custom configuration. * * @param model the {@link Model} to serialize. Must not be null. - * @param config the {@link TriGConfig} to use for serialization. Must not be null. + * @param config the {@link TriGOption} to use for serialization. Must not be null. * This config object should be an instance of {@code TriGConfig} or a subclass thereof. * @throws NullPointerException if the provided model or configuration is null. */ - public TriGSerializer(Model model, TriGConfig config) { + public TriGSerializer(Model model, TriGOption config) { super(model, config); Objects.requireNonNull(config, "TriGConfig cannot be null"); } @@ -77,12 +76,12 @@ protected String getFormatName() { * @return The config cast to TriGConfig. * @throws IllegalStateException if the config is not an instance of TriGConfig. */ - private TriGConfig getTriGConfig() { - if (!(config instanceof TriGConfig)) { + private TriGOption getTriGConfig() { + if (!(option instanceof TriGOption)) { throw new IllegalStateException("Current serializer configuration is not an instance of TriGConfig. " + "TriGSerializer requires a TriGConfig instance."); } - return (TriGConfig) config; + return (TriGOption) option; } /** @@ -94,7 +93,7 @@ private TriGConfig getTriGConfig() { */ @Override protected void doWriteStatements(Writer writer) throws IOException { - TriGConfig trigConfig = getTriGConfig(); + TriGOption trigConfig = getTriGConfig(); if (trigConfig.includeContext()) { writeStatementsWithContext(writer); @@ -114,7 +113,7 @@ protected void doWriteStatements(Writer writer) throws IOException { * @throws IOException if an I/O error occurs. */ private void writeStatementsWithContext(Writer writer) throws IOException { - TriGConfig trigConfig = getTriGConfig(); + TriGOption trigConfig = getTriGConfig(); Map> byContext = new LinkedHashMap<>(); model.stream() @@ -257,7 +256,7 @@ protected String escapeLiteralString(String value) { sb.append(SerializationConstants.BACK_SLASH).append(SerializationConstants.BACK_SLASH); break; default: - if (config.escapeUnicode() && (c <= 0x1F || c == 0x7F || (c >= 0x80 && c <= 0xFFFF))) { + if (option.escapeUnicode() && (c <= 0x1F || c == 0x7F || (c >= 0x80 && c <= 0xFFFF))) { sb.append(String.format("\\u%04X", (int) c)); } else if (Character.isHighSurrogate(c)) { int codePoint = value.codePointAt(i); diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOption.java similarity index 69% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOption.java index 739169e9c..e5eed8c0c 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOption.java @@ -1,35 +1,37 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.turtle; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractTFamilyOption; +import fr.inria.corese.core.next.impl.io.serialization.option.BlankNodeStyleEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import java.util.HashMap; import java.util.Map; /** * Configuration for Turtle serialization format. - * This class extends {@link AbstractTFamilyConfig} and provides specific defaults + * This class extends {@link AbstractTFamilyOption} and provides specific defaults * and options tailored for Turtle, such as using collections and anonymous blank nodes. * *

Use the {@link Builder} class to create instances of {@code TurtleConfig}. * A predefined default configuration is available via {@link #defaultConfig()}.

*/ -public class TurtleConfig extends AbstractTFamilyConfig { +public class TurtleOption extends AbstractTFamilyOption { /** * Protected constructor to be used by the {@link Builder}. * * @param builder The builder instance containing the desired configuration values. */ - protected TurtleConfig(Builder builder) { + protected TurtleOption(Builder builder) { super(builder); } /** - * Public Builder for {@link TurtleConfig}. + * Public Builder for {@link TurtleOption}. * Provides a fluent API for constructing {@code TurtleConfig} instances with default values * specific to the Turtle format. */ - public static class Builder extends AbstractTFamilyConfig.AbstractTFamilyBuilder { + public static class Builder extends AbstractTFamilyOption.AbstractTFamilyBuilder { /** * Default constructor initializes all options with their default values for Turtle. */ @@ -50,13 +52,13 @@ public Builder() { } /** - * Builds and returns a new {@link TurtleConfig} instance with the current builder settings. + * Builds and returns a new {@link TurtleOption} instance with the current builder settings. * * @return A new {@code TurtleConfig} instance. */ @Override - public TurtleConfig build() { - return new TurtleConfig(this); + public TurtleOption build() { + return new TurtleOption(this); } } @@ -67,18 +69,18 @@ public TurtleConfig build() { * * @return A {@code TurtleConfig} instance with default settings. */ - public static TurtleConfig defaultConfig() { + public static TurtleOption defaultConfig() { return new Builder().build(); } /** - * Returns a new builder instance for {@link TurtleConfig}. + * Returns a new builder instance for {@link TurtleOption}. * This allows for fluent construction of custom Turtle configurations. * * @return A new {@code Builder} instance. */ - public static TurtleConfig.Builder builder() { - return new TurtleConfig.Builder(); + public static TurtleOption.Builder builder() { + return new TurtleOption.Builder(); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializer.java similarity index 90% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializer.java index d1316920f..0d7fe4918 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializer.java @@ -1,10 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.turtle; import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.impl.common.serialization.base.AbstractGraphSerializer; -import fr.inria.corese.core.next.impl.common.serialization.config.TurtleConfig; -import fr.inria.corese.core.next.impl.common.serialization.config.AbstractTFamilyConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.base.AbstractGraphSerializer; +import fr.inria.corese.core.next.impl.io.serialization.option.AbstractTFamilyOption; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,23 +38,23 @@ public class TurtleSerializer extends AbstractGraphSerializer { /** * Constructs a new {@code TurtleSerializer} instance with the specified model and default configuration. - * The default configuration is returned by {@link TurtleConfig#defaultConfig()}. + * The default configuration is returned by {@link TurtleOption#defaultConfig()}. * * @param model the {@link Model} to serialize. Must not be null. * @throws NullPointerException if the provided model is null. */ public TurtleSerializer(Model model) { - this(model, TurtleConfig.defaultConfig()); + this(model, TurtleOption.defaultConfig()); } /** * Constructs a new {@code TurtleSerializer} instance with the specified model and custom configuration. * * @param model the {@link Model} to serialize. Must not be null. - * @param config the {@link TurtleConfig} to use for serialization. Must not be null. + * @param config the {@link TurtleOption} to use for serialization. Must not be null. * @throws NullPointerException if the provided model or configuration is null. */ - public TurtleSerializer(Model model, TurtleConfig config) { + public TurtleSerializer(Model model, TurtleOption config) { super(model, config); Objects.requireNonNull(config, "TurtleConfig cannot be null"); } @@ -80,7 +79,7 @@ protected String getFormatName() { */ @Override protected void doWriteStatements(Writer writer) throws IOException { - AbstractTFamilyConfig tFamilyConfig = (AbstractTFamilyConfig) config; + AbstractTFamilyOption tFamilyConfig = (AbstractTFamilyOption) option; if (tFamilyConfig.useCompactTriples() && tFamilyConfig.groupBySubject()) { writeOptimizedStatements(writer); @@ -146,7 +145,7 @@ protected String escapeLiteralString(String value) { sb.append(SerializationConstants.BACK_SLASH).append(SerializationConstants.BACK_SLASH); break; default: - if (config.escapeUnicode() && (c <= 0x1F || c == 0x7F || (c >= 0x80 && c <= 0xFFFF))) { + if (option.escapeUnicode() && (c <= 0x1F || c == 0x7F || (c >= 0x80 && c <= 0xFFFF))) { sb.append(String.format("\\u%04X", (int) c)); } else if (Character.isHighSurrogate(c)) { int codePoint = value.codePointAt(i); diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/util/SerializationConstants.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/util/SerializationConstants.java similarity index 96% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/util/SerializationConstants.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/util/SerializationConstants.java index ef560f804..dda97db5f 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/util/SerializationConstants.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/util/SerializationConstants.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization.util; +package fr.inria.corese.core.next.impl.io.serialization.util; import fr.inria.corese.core.next.impl.common.vocabulary.OWL; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; @@ -105,4 +105,6 @@ private SerializationConstants() { public static final String QUOT_ENTITY = """; public static final String APOS_ENTITY = "'"; + public static final String DEFAULT_GRAPH_IRI = "http://ns.inria.fr/corese/default-graph"; + } diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java index 66501ab85..9d6ff57a1 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java +++ b/src/main/java/fr/inria/corese/core/next/impl/temp/CoreseValueConverter.java @@ -120,7 +120,7 @@ public Value toRdf4jValue(Node node) { return factory.createLiteral(dt.getLabel(), dt.getLang()); } if (dt.getDatatypeURI() != null) { - return factory.createLiteral(dt.getLabel(), dt.getDatatypeURI()); + return factory.createLiteral(dt.getLabel(), factory.createIRI(dt.getDatatypeURI())); } return factory.createLiteral(dt.getLabel()); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java index 5e4cd2eb9..d3408b855 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java +++ b/src/main/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTyped.java @@ -11,6 +11,10 @@ import fr.inria.corese.core.next.impl.exception.IncorrectOperationException; import fr.inria.corese.core.next.impl.temp.CoreseIRI; import fr.inria.corese.core.sparql.api.IDatatype; +import fr.inria.corese.core.sparql.datatype.CoreseGeneric; +import fr.inria.corese.core.sparql.datatype.CoreseString; + +import static fr.inria.corese.core.next.impl.common.vocabulary.XSD.xsdString; /** * An implementation of the {@code xsd:string} datatype used by Corese. @@ -25,37 +29,29 @@ public class CoreseTyped extends AbstractStringLiteral implements CoreseDatatype /** * The Corese object representing the string literal in the old API. */ - private final fr.inria.corese.core.sparql.datatype.CoreseString coreseObject; + private final CoreseString coreseObject; /** * The core datatype of this literal. */ private CoreDatatype coreDatatype; - /** - * The value of the string literal. - */ - private String value; - /** - * The datatype IRI of the literal. - */ - private IRI dataype; /** * Constructs a {@link CoreseTyped} instance from an {@link IDatatype} Corese * object. * The Corese object should be an instance of - * {@link fr.inria.corese.core.sparql.datatype.CoreseString}. + * {@link CoreseString}. * * @param coreseObject The {@link IDatatype} Corese object representing the * string literal. * @throws IncorrectOperationException If the provided {@link IDatatype} is not * a - * {@link fr.inria.corese.core.sparql.datatype.CoreseString}. + * {@link CoreseString}. */ public CoreseTyped(IDatatype coreseObject) { - super(new CoreseIRI(coreseObject.getDatatypeURI())); - if (coreseObject instanceof fr.inria.corese.core.sparql.datatype.CoreseString) { - this.coreseObject = (fr.inria.corese.core.sparql.datatype.CoreseString) coreseObject; + super(coreseObject.getDatatypeURI() != null && ! coreseObject.getDatatypeURI().isEmpty() ? new CoreseIRI(coreseObject.getDatatypeURI()) : new CoreseIRI(xsdString.getIRI())); + if (coreseObject instanceof CoreseString) { + this.coreseObject = (CoreseString) coreseObject; } else { throw new IncorrectOperationException("Cannot create CoreseString from a non-string Corese object"); } @@ -68,10 +64,9 @@ public CoreseTyped(IDatatype coreseObject) { * @param value The string value for the literal. */ public CoreseTyped(String value) { - this(new fr.inria.corese.core.sparql.datatype.CoreseString(value)); + this(new CoreseString(value)); this.coreDatatype = XSD.STRING; this.datatype = XSD.STRING.getIRI(); - this.value = value; } /** @@ -85,8 +80,7 @@ public CoreseTyped(String value) { * @param datatype The datatype IRI for the literal. */ public CoreseTyped(String value, IRI datatype) { - this(new fr.inria.corese.core.sparql.datatype.CoreseString(value)); - this.value = value; + this(new CoreseGeneric(value, datatype == null ? xsdString.getIRI().stringValue() : datatype.stringValue())); if (datatype == null) { this.datatype = XSD.STRING.getIRI(); this.coreDatatype = XSD.STRING; @@ -105,9 +99,8 @@ public CoreseTyped(String value, IRI datatype) { * @param coreDatatype The core datatype for the literal. */ public CoreseTyped(String value, CoreDatatype coreDatatype) { - this(new fr.inria.corese.core.sparql.datatype.CoreseString(value)); + this(new CoreseString(value)); this.datatype = coreDatatype.getIRI(); - this.value = value; this.coreDatatype = Objects.requireNonNull(coreDatatype); this.datatype = coreDatatype.getIRI(); } @@ -128,7 +121,7 @@ public CoreseTyped(String value, CoreDatatype coreDatatype) { * {@code null}. */ public CoreseTyped(String value, IRI datatype, CoreDatatype coreDatatype) { - this(new fr.inria.corese.core.sparql.datatype.CoreseString(value)); + this(new CoreseString(value)); if (datatype == null || coreDatatype == null) { throw new IncorrectOperationException("Datatype and CoreDatatype cannot be null"); @@ -138,7 +131,6 @@ public CoreseTyped(String value, IRI datatype, CoreDatatype coreDatatype) { throw new IncorrectOperationException("Datatype IRI does not match CoreDatatype's IRI"); } - this.value = value; this.datatype = datatype; this.coreDatatype = coreDatatype; } diff --git a/src/main/java/fr/inria/corese/core/producer/DataFrom.java b/src/main/java/fr/inria/corese/core/producer/DataFrom.java index 2dbc4dbfd..a103f1618 100644 --- a/src/main/java/fr/inria/corese/core/producer/DataFrom.java +++ b/src/main/java/fr/inria/corese/core/producer/DataFrom.java @@ -49,11 +49,14 @@ DataFrom from(Node node) { return this; } + /** + * WARNING: This function takes a list of nodes and sets the from field to the first node in the list. + */ DataFrom from(List list) { setFrom(list); if (list != null && list.size() == 1) { setOneFrom(true); - setFromNode(graph.getGraphNode(getFrom().get(0))); + setFromNode(graph.getGraphNode(getFrom().getFirst())); if (getFromNode() == null) { setOneFrom(false); } diff --git a/src/main/java/fr/inria/corese/core/util/Property.java b/src/main/java/fr/inria/corese/core/util/Property.java index 1543f67f5..ba2d239bc 100644 --- a/src/main/java/fr/inria/corese/core/util/Property.java +++ b/src/main/java/fr/inria/corese/core/util/Property.java @@ -228,7 +228,6 @@ public static void define(String name, String value) { } static void basicSet(Value value, boolean b) { - logger.debug("{} = {}", value, b); getSingleton().getBooleanProperty().put(value, b); switch (value) { @@ -430,7 +429,6 @@ static void basicSet(Value value, boolean b) { } static void basicSet(Value value, String... str) { - logger.debug("{} = {}", value, str); switch (value) { case FEDERATE_BLACKLIST: getSingleton().blacklist(str); @@ -442,7 +440,6 @@ static void basicSet(Value value, String... str) { } static void basicSet(Value value, String str) { - logger.debug("{} = {}", value, str); getSingleton().getStringProperty().put(value, str); switch (value) { @@ -549,7 +546,6 @@ static void basicSet(Value value, String str) { } static void basicSet(Value value, int n) { - logger.debug("{} = {}", value, n); getSingleton().getIntegerProperty().put(value, n); switch (value) { @@ -687,10 +683,8 @@ private void imports() throws IOException { String importPath = expand(name); if (getImports().containsKey(importPath)) { - logger.info("Skip import: " + importPath); } else { getImports().put(importPath, importPath); - logger.info("Import: " + importPath); try (FileReader importReader = new FileReader(importPath)) { getProperties().load(importReader); } @@ -712,7 +706,7 @@ void defineProperty() { try { define(name, value); } catch (Exception e) { - logger.info("Incorrect Property: " + name + " " + value); + logger.error("Incorrect Property: " + name + " " + value); } } } @@ -774,7 +768,6 @@ void split(String list) { for (String str : list.split(SEP)) { alist.add(NSManager.nsm().toNamespace(str)); } - logger.info("Split: " + alist); FederateVisitor.DEFAULT_SPLIT = alist; } @@ -805,11 +798,6 @@ private void defineVariableMap() { for (Pair pair : getValueListBasic(Value.VARIABLE)) { String variable = varName(pair.getKey()); - if (getVariableMap().containsKey(variable)) { - logger.info("Overload variable: " + variable); - } - logger.info(String.format("variable: %s=%s", variable, expand(pair.getValue()))); - getVariableMap().put(variable, expand(pair.getValue())); } } @@ -848,7 +836,6 @@ void queryPlan(String str) { } void defineFederation(String path) { - logger.info("federation: " + path); QueryProcess exec = QueryProcess.create(Graph.create()); try { Graph g = exec.defineFederation(path); @@ -861,7 +848,7 @@ void loadFunction(String str) { QueryProcess exec = QueryProcess.create(); for (String name : str.split(SEP)) { try { - exec.imports(str); + exec.imports(name); } catch (EngineException ex) { logger.error(ex.toString()); } @@ -923,7 +910,6 @@ void loadList(Graph g, String path) { for (String name : path.split(SEP)) { try { String file = expand(name); - logger.info("Load: " + file); ld.parse(file.strip()); } catch (LoadException ex) { logger.error(ex.toString()); @@ -939,7 +925,6 @@ void variable() { for (Pair pair : getValueListBasic(Value.LDSCRIPT_VARIABLE)) { String variable = pair.getKey().strip(); String val = pair.getValue().strip(); - logger.info(String.format("ldscript variable: %s=%s", variable, val)); IDatatype dt = DatatypeMap.newValue(val); Binding.setStaticVariable(variable, dt); } diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/FileFormatTest.java b/src/test/java/fr/inria/corese/core/next/api/base/io/FileFormatTest.java similarity index 70% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/FileFormatTest.java rename to src/test/java/fr/inria/corese/core/next/api/base/io/FileFormatTest.java index 2e3308e18..92302b3d7 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/FileFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/api/base/io/FileFormatTest.java @@ -1,27 +1,19 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.api.base.io; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.*; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Stream; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.DisplayNameGeneration; -import org.junit.jupiter.api.DisplayNameGenerator; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for {@link FileFormat}. + * Unit tests for {@link fr.inria.corese.core.next.api.base.io.FileFormat}. * *

* Coverage : @@ -64,7 +56,7 @@ void constructor_sets_all_fields(String name, List extensions, List mimeTypes) { - FileFormat format = new FileFormat(name, extensions, mimeTypes); + fr.inria.corese.core.next.api.base.io.FileFormat format = new fr.inria.corese.core.next.api.base.io.FileFormat(name, extensions, mimeTypes); assertAll("All getters reflect constructor arguments", () -> assertEquals(name, format.getName(), "name"), @@ -88,31 +80,31 @@ class Constructor_argument_validation { @Test void null_name_throws_NPE() { assertThrows(NullPointerException.class, - () -> new FileFormat(null, EXT, MIME)); + () -> new fr.inria.corese.core.next.api.base.io.FileFormat(null, EXT, MIME)); } @Test void null_extensions_throws_NPE() { assertThrows(NullPointerException.class, - () -> new FileFormat("Turtle", null, MIME)); + () -> new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", null, MIME)); } @Test void null_mimeTypes_throws_NPE() { assertThrows(NullPointerException.class, - () -> new FileFormat("Turtle", EXT, null)); + () -> new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", EXT, null)); } @Test void empty_extensions_throws_IAE() { assertThrows(IllegalArgumentException.class, - () -> new FileFormat("Turtle", List.of(), MIME)); + () -> new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", List.of(), MIME)); } @Test void empty_mimeTypes_throws_IAE() { assertThrows(IllegalArgumentException.class, - () -> new FileFormat("Turtle", EXT, List.of())); + () -> new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", EXT, List.of())); } } @@ -126,7 +118,7 @@ void internal_lists_are_immutable_and_defensively_copied() { // Build mutable lists List ext = new ArrayList<>(List.of("ttl")); List mime = new ArrayList<>(List.of("text/turtle")); - FileFormat format = new FileFormat("Turtle", ext, mime); + fr.inria.corese.core.next.api.base.io.FileFormat format = new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", ext, mime); // Mutate originals AFTER construction ext.add("bad"); @@ -152,11 +144,11 @@ void internal_lists_are_immutable_and_defensively_copied() { @Nested class Equals_and_hashCode_contract { - private final FileFormat base = new FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); + private final fr.inria.corese.core.next.api.base.io.FileFormat base = new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); @Test void symmetry_and_case_insensitivity() { - FileFormat sameDifferentCase = new FileFormat("tUrTlE", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat sameDifferentCase = new fr.inria.corese.core.next.api.base.io.FileFormat("tUrTlE", List.of("ttl"), List.of("text/turtle")); assertEquals(base, sameDifferentCase); assertEquals(sameDifferentCase, base); @@ -165,9 +157,9 @@ void symmetry_and_case_insensitivity() { @Test void transitivity() { - FileFormat a = new FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); - FileFormat b = new FileFormat("TURTLE", List.of("ttl"), List.of("text/turtle")); - FileFormat c = new FileFormat("turtle", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat a = new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat b = new fr.inria.corese.core.next.api.base.io.FileFormat("TURTLE", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat c = new fr.inria.corese.core.next.api.base.io.FileFormat("turtle", List.of("ttl"), List.of("text/turtle")); assertAll( () -> assertEquals(a, b), @@ -177,9 +169,9 @@ void transitivity() { @Test void inequality_when_any_field_differs() { - FileFormat diffName = new FileFormat("N-Triples", List.of("ttl"), List.of("text/turtle")); - FileFormat diffExt = new FileFormat("Turtle", List.of("nt"), List.of("text/turtle")); - FileFormat diffMime = new FileFormat("Turtle", List.of("ttl"), List.of("application/n-triples")); + fr.inria.corese.core.next.api.base.io.FileFormat diffName = new fr.inria.corese.core.next.api.base.io.FileFormat("N-Triples", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat diffExt = new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", List.of("nt"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat diffMime = new fr.inria.corese.core.next.api.base.io.FileFormat("Turtle", List.of("ttl"), List.of("application/n-triples")); assertAll( () -> assertNotEquals(base, diffName), @@ -197,7 +189,7 @@ void inequality_when_any_field_differs() { */ @Test void toString_contains_all_relevant_information() { - FileFormat format = new FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); + fr.inria.corese.core.next.api.base.io.FileFormat format = new FileFormat("Turtle", List.of("ttl"), List.of("text/turtle")); String out = format.toString(); assertTrue( diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormatTest.java b/src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java similarity index 77% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormatTest.java rename to src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java index 28f5da4b1..e5859edfa 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/RdfFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.api.base.io; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -8,7 +8,7 @@ import static org.junit.jupiter.api.Assertions.*; -class RdfFormatTest { +class RDFFormatTest { @Test @@ -20,7 +20,7 @@ void constructorAndGetters() { boolean supportsNamespaces = true; boolean supportsNamedGraphs = false; - RdfFormat format = new RdfFormat(name, extensions, mimeTypes, supportsNamespaces, supportsNamedGraphs); + RDFFormat format = new RDFFormat(name, extensions, mimeTypes, supportsNamespaces, supportsNamedGraphs); assertEquals(name, format.getName(), "Name should match constructor argument"); assertEquals(extensions, format.getExtensions(), "Extensions list should match constructor argument"); @@ -38,7 +38,7 @@ void constructorThrowsForNullName() { List extensions = List.of("tf"); List mimeTypes = List.of("text/plain"); assertThrows(NullPointerException.class, - () -> new RdfFormat(null, extensions, mimeTypes, true, false), + () -> new RDFFormat(null, extensions, mimeTypes, true, false), "Constructor should throw NPE for null name"); } @@ -47,7 +47,7 @@ void constructorThrowsForNullName() { void constructorThrowsForNullExtensions() { List mimeTypes = List.of("text/plain"); assertThrows(NullPointerException.class, - () -> new RdfFormat("Test", null, mimeTypes, true, false), + () -> new RDFFormat("Test", null, mimeTypes, true, false), "Constructor should throw NPE for null extensions list"); } @@ -57,7 +57,7 @@ void constructorThrowsForNullExtensions() { void constructorThrowsForNullMimeTypes() { List extensions = List.of("tf"); assertThrows(NullPointerException.class, - () -> new RdfFormat("Test", extensions, null, true, false), + () -> new RDFFormat("Test", extensions, null, true, false), "Constructor should throw NPE for null mimeTypes list"); } @@ -65,7 +65,7 @@ void constructorThrowsForNullMimeTypes() { @Test @DisplayName("toString() should return a meaningful string representation") void testToString() { - RdfFormat format = RdfFormat.TURTLE; + RDFFormat format = RDFFormat.TURTLE; String expected = "Turtle [extensions: ttl, mimeTypes: text/turtle, prefixes: true, namedGraphs: false]"; assertEquals(expected, format.toString(), "toString() should match expected format"); @@ -74,7 +74,7 @@ void testToString() { @Test @DisplayName("equals() should return true for identical objects") void equalsIdenticalObjects() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, false); assertEquals(format1, format1, "Object should be equal to itself"); } @@ -82,8 +82,8 @@ void equalsIdenticalObjects() { @Test @DisplayName("equals() should return true for logically equal objects") void equalsLogicallyEqualObjects() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("test", List.of("t"), List.of("text/t"), true, false); // Name case-insensitive + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("test", List.of("t"), List.of("text/t"), true, false); // Name case-insensitive assertEquals(format1, format2, "Objects with same properties (case-insensitive name) should be equal"); } @@ -91,8 +91,8 @@ void equalsLogicallyEqualObjects() { @Test @DisplayName("equals() should return false for objects with different names") void equalsDifferentNames() { - RdfFormat format1 = new RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("Test2", List.of("t"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test1", List.of("t"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("Test2", List.of("t"), List.of("text/t"), true, false); assertNotEquals(format1, format2, "Objects with different names should not be equal"); } @@ -100,8 +100,8 @@ void equalsDifferentNames() { @Test @DisplayName("equals() should return false for objects with different extensions") void equalsDifferentExtensions() { - RdfFormat format1 = new RdfFormat("Test", List.of("t1"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("Test", List.of("t2"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t1"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("Test", List.of("t2"), List.of("text/t"), true, false); assertNotEquals(format1, format2, "Objects with different extensions should not be equal"); } @@ -109,8 +109,8 @@ void equalsDifferentExtensions() { @Test @DisplayName("equals() should return false for objects with different mimeTypes") void equalsDifferentMimeTypes() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t1"), true, false); - RdfFormat format2 = new RdfFormat("Test", List.of("t"), List.of("text/t2"), true, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t1"), true, false); + RDFFormat format2 = new RDFFormat("Test", List.of("t"), List.of("text/t2"), true, false); assertNotEquals(format1, format2, "Objects with different mimeTypes should not be equal"); } @@ -118,8 +118,8 @@ void equalsDifferentMimeTypes() { @Test @DisplayName("equals() should return false for objects with different supportsNamespaces") void equalsDifferentSupportsNamespaces() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("Test", List.of("t"), List.of("text/t"), false, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("Test", List.of("t"), List.of("text/t"), false, false); assertNotEquals(format1, format2, "Objects with different supportsNamespaces should not be equal"); } @@ -127,8 +127,8 @@ void equalsDifferentSupportsNamespaces() { @Test @DisplayName("equals() should return false for objects with different supportsNamedGraphs") void equalsDifferentSupportsNamedGraphs() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, true); - RdfFormat format2 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, true); + RDFFormat format2 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, false); assertNotEquals(format1, format2, "Objects with different supportsNamedGraphs should not be equal"); } @@ -136,8 +136,8 @@ void equalsDifferentSupportsNamedGraphs() { @Test @DisplayName("hashCode() should be consistent with equals()") void hashCodeConsistency() { - RdfFormat format1 = new RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test", List.of("t"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("test", List.of("t"), List.of("text/t"), true, false); assertEquals(format1, format2, "Objects should be equal"); assertEquals(format1.hashCode(), format2.hashCode(), "Hash codes must be equal for equal objects"); @@ -146,8 +146,8 @@ void hashCodeConsistency() { @Test @DisplayName("hashCode() should return different values for unequal objects (high probability)") void hashCodeDifference() { - RdfFormat format1 = new RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); - RdfFormat format2 = new RdfFormat("Test2", List.of("t"), List.of("text/t"), true, false); + RDFFormat format1 = new RDFFormat("Test1", List.of("t"), List.of("text/t"), true, false); + RDFFormat format2 = new RDFFormat("Test2", List.of("t"), List.of("text/t"), true, false); assertNotEquals(format1.hashCode(), format2.hashCode(), "Hash codes should ideally be different for unequal objects"); } @@ -156,7 +156,7 @@ void hashCodeDifference() { @Test @DisplayName("TURTLE constant should be correctly defined") void turtleConstant() { - RdfFormat turtle = RdfFormat.TURTLE; + RDFFormat turtle = RDFFormat.TURTLE; assertNotNull(turtle, "TURTLE constant should not be null"); assertEquals("Turtle", turtle.getName()); @@ -169,7 +169,7 @@ void turtleConstant() { @Test @DisplayName("NTRIPLES constant should be correctly defined") void nTriplesConstant() { - RdfFormat ntriples = RdfFormat.NTRIPLES; + RDFFormat ntriples = RDFFormat.NTRIPLES; assertNotNull(ntriples, "NTRIPLES constant should not be null"); assertEquals("N-Triples", ntriples.getName()); @@ -182,7 +182,7 @@ void nTriplesConstant() { @Test @DisplayName("NQUADS constant should be correctly defined") void nQuadsConstant() { - RdfFormat nquads = RdfFormat.NQUADS; + RDFFormat nquads = RDFFormat.NQUADS; assertNotNull(nquads, "NQUADS constant should not be null"); assertEquals("N-Quads", nquads.getName()); @@ -195,7 +195,7 @@ void nQuadsConstant() { @Test @DisplayName("JSONLD constant should be correctly defined") void jsonLdConstant() { - RdfFormat jsonld = RdfFormat.JSONLD; + RDFFormat jsonld = RDFFormat.JSONLD; assertNotNull(jsonld, "JSONLD constant should not be null"); assertEquals("JSON-LD", jsonld.getName()); @@ -208,7 +208,7 @@ void jsonLdConstant() { @Test @DisplayName("RDFXML constant should be correctly defined") void rdfXmlConstant() { - RdfFormat rdfxml = RdfFormat.RDFXML; + RDFFormat rdfxml = RDFFormat.RDFXML; assertNotNull(rdfxml, "RDFXML constant should not be null"); assertEquals("RDF/XML", rdfxml.getName()); @@ -222,7 +222,7 @@ void rdfXmlConstant() { @Test @DisplayName("TRIG constant should be correctly defined") void trigConstant() { - RdfFormat trig = RdfFormat.TRIG; + RDFFormat trig = RDFFormat.TRIG; assertNotNull(trig, "TRIG constant should not be null"); assertEquals("TriG", trig.getName()); @@ -235,16 +235,16 @@ void trigConstant() { @Test @DisplayName("byName() should find existing format by name (case-insensitive)") void byNameFound() { - Optional format = RdfFormat.byName("TuRtLe"); + Optional format = RDFFormat.byName("TuRtLe"); assertTrue(format.isPresent(), "Turtle format should be found by name"); - assertEquals(RdfFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); + assertEquals(RDFFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); } @Test @DisplayName("byName() should return empty Optional for non-existent name") void byNameNotFound() { - Optional format = RdfFormat.byName("NonExistentFormat"); + Optional format = RDFFormat.byName("NonExistentFormat"); assertFalse(format.isPresent(), "Non-existent format should not be found"); } @@ -252,20 +252,20 @@ void byNameNotFound() { @Test @DisplayName("byExtension() should find existing format by extension (case-insensitive)") void byExtensionFound() { - Optional format = RdfFormat.byExtension("TTL"); + Optional format = RDFFormat.byExtension("TTL"); assertTrue(format.isPresent(), "Turtle format should be found by extension"); - assertEquals(RdfFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); + assertEquals(RDFFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); - Optional rdfXmlFormat = RdfFormat.byExtension("XML"); + Optional rdfXmlFormat = RDFFormat.byExtension("XML"); assertTrue(rdfXmlFormat.isPresent()); - assertEquals(RdfFormat.RDFXML, rdfXmlFormat.get()); + assertEquals(RDFFormat.RDFXML, rdfXmlFormat.get()); } @Test @DisplayName("byExtension() should return empty Optional for non-existent extension") void byExtensionNotFound() { - Optional format = RdfFormat.byExtension("xyz"); + Optional format = RDFFormat.byExtension("xyz"); assertFalse(format.isPresent(), "Non-existent extension should not find a format"); } @@ -273,21 +273,21 @@ void byExtensionNotFound() { @Test @DisplayName("byMimeType() should find existing format by MIME type (case-insensitive)") void byMimeTypeFound() { - Optional format = RdfFormat.byMimeType("text/TuRtLe"); + Optional format = RDFFormat.byMimeType("text/TuRtLe"); assertTrue(format.isPresent(), "Turtle format should be found by MIME type"); - assertEquals(RdfFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); + assertEquals(RDFFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); - Optional nTriplesFormat = RdfFormat.byMimeType("text/plain"); + Optional nTriplesFormat = RDFFormat.byMimeType("text/plain"); assertTrue(nTriplesFormat.isPresent()); - assertEquals(RdfFormat.NTRIPLES, nTriplesFormat.get()); + assertEquals(RDFFormat.NTRIPLES, nTriplesFormat.get()); } @Test @DisplayName("byMimeType() should return empty Optional for non-existent MIME type") void byMimeTypeNotFound() { - Optional format = RdfFormat.byMimeType("application/x-unknown"); + Optional format = RDFFormat.byMimeType("application/x-unknown"); assertFalse(format.isPresent(), "Non-existent MIME type should not find a format"); } @@ -295,19 +295,19 @@ void byMimeTypeNotFound() { @Test @DisplayName("all() should return a list containing all predefined formats") void allFormats() { - List allFormats = RdfFormat.all(); + List allFormats = RDFFormat.all(); assertNotNull(allFormats, "List of all formats should not be null"); assertEquals(6, allFormats.size(), "List should contain 5 predefined formats"); // TURTLE, NTRIPLES, NQUADS, JSONLD, RDFXML, TRIG - assertTrue(allFormats.contains(RdfFormat.TURTLE)); - assertTrue(allFormats.contains(RdfFormat.NTRIPLES)); - assertTrue(allFormats.contains(RdfFormat.NQUADS)); - assertTrue(allFormats.contains(RdfFormat.JSONLD)); - assertTrue(allFormats.contains(RdfFormat.RDFXML)); - assertTrue(allFormats.contains(RdfFormat.TRIG)); + assertTrue(allFormats.contains(RDFFormat.TURTLE)); + assertTrue(allFormats.contains(RDFFormat.NTRIPLES)); + assertTrue(allFormats.contains(RDFFormat.NQUADS)); + assertTrue(allFormats.contains(RDFFormat.JSONLD)); + assertTrue(allFormats.contains(RDFFormat.RDFXML)); + assertTrue(allFormats.contains(RDFFormat.TRIG)); - assertThrows(UnsupportedOperationException.class, () -> allFormats.add(RdfFormat.TURTLE), + assertThrows(UnsupportedOperationException.class, () -> allFormats.add(RDFFormat.TURTLE), "The list returned by all() should be unmodifiable"); } } \ No newline at end of file diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/CircularJSONLDIOTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/CircularJSONLDIOTest.java new file mode 100644 index 000000000..5aa7c5305 --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/CircularJSONLDIOTest.java @@ -0,0 +1,28 @@ +package fr.inria.corese.core.next.impl.io; + +import org.junit.jupiter.api.Test; + +/** + * Tests the parser and serializer for the format JSON-LD + */ +public class CircularJSONLDIOTest { + + @Test + public void basicJSONLDString() { + // TODO: implement this test + } + + @Test + public void basicJSONLDFile() { + // TODO: implement this test + } + + @Test + public void jsonldWithBlankNodes() { + // TODO: implement this test + } + + @Test void jsonldWithNamedGraphs() { + // TODO: implement this test + } +} diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java new file mode 100644 index 000000000..5b0ac465d --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java @@ -0,0 +1,96 @@ +package fr.inria.corese.core.next.impl.io.option; + +import com.apicatalog.jsonld.JsonLdVersion; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Tests to check that values are properly set + */ +class TitaniumJSONLDProcessorOptionTest { + + private TitaniumJSONLDProcessorOption optionAllTrue = new TitaniumJSONLDProcessorOption.Builder().base("http://example.org/AllTrue") + .extractAllScripts(true) + .compactToRelative(true) + .compactArrays(true) + .ordered(true) + .useRdfType(true) + .useNativeTypes(true) + .build(); + + private TitaniumJSONLDProcessorOption optionAllFalse = new TitaniumJSONLDProcessorOption.Builder().base("http://example.org/AllFalse") + .extractAllScripts(false) + .compactArrays(false) + .compactToRelative(false) + .ordered(false) + .useRdfType(false) + .useNativeTypes(false) + .build(); + + @Test + void isCompactArrays() { + assertTrue(optionAllTrue.compactsArrays()); + assertFalse(optionAllFalse.compactsArrays()); + } + + @Test + void isCompactToRelative() { + assertTrue(optionAllTrue.compactsToRelative()); + assertFalse(optionAllFalse.compactsToRelative()); + } + + @Test + void isExtractAllScripts() { + assertTrue(optionAllTrue.isExtractAllScripts()); + assertFalse(optionAllFalse.isExtractAllScripts()); + } + + @Test + void isOrdered() { + assertTrue(optionAllTrue.isOrdered()); + assertFalse(optionAllFalse.isOrdered()); + } + + @Test + void getProcessingMode() { + TitaniumJSONLDProcessorOption option10 = new TitaniumJSONLDProcessorOption.Builder().processingMode(JsonLdVersion.V1_0).build(); + TitaniumJSONLDProcessorOption option11 = new TitaniumJSONLDProcessorOption.Builder().processingMode(JsonLdVersion.V1_1).build(); + assertEquals(JsonLdVersion.V1_0, option10.getProcessingMode()); + assertEquals(JsonLdVersion.V1_1, option11.getProcessingMode()); + } + + @Test + void getTimeout() { + TitaniumJSONLDProcessorOption option10seconds = new TitaniumJSONLDProcessorOption.Builder().timeout(Duration.of(10, ChronoUnit.SECONDS)).build(); + assertNull(optionAllTrue.getTimeout()); + assertEquals(Duration.of(10, ChronoUnit.SECONDS), option10seconds.getTimeout()); + } + + @Test + void isUseNativeTypes() { + assertTrue(optionAllTrue.usesNativeTypes()); + assertFalse(optionAllFalse.usesNativeTypes()); + } + + @Test + void isUseRdfType() { + assertTrue(optionAllTrue.usesRdfType()); + assertFalse(optionAllFalse.usesRdfType()); + } + + @Test + void getJsonLdOptions() { + assertNotNull(optionAllTrue.getJsonLdOptions()); + assertNotNull(optionAllFalse.getJsonLdOptions()); + } + + @Test + void getBase() { + assertEquals("http://example.org/AllTrue", optionAllTrue.getBase()); + assertEquals("http://example.org/AllFalse", optionAllFalse.getBase()); + } +} \ No newline at end of file diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java new file mode 100644 index 000000000..08d7dbf72 --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java @@ -0,0 +1,313 @@ +package fr.inria.corese.core.next.impl.io.parser.jsonld; + +import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.impl.io.parser.ParserFactory; +import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; +import fr.inria.corese.core.next.impl.temp.CoreseModel; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayInputStream; +import java.io.Reader; +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.*; + +public class JSONLDParserTest { + + private static final Logger logger = LoggerFactory.getLogger(JSONLDParserTest.class); + private final ParserFactory factory = new ParserFactory(); + private final ValueFactory valueFactory = new CoreseAdaptedValueFactory(); + + @Test + void constructorNullModelThrowsTest() { + assertThrows(NullPointerException.class, () -> new JSONLDParser(null, valueFactory)); + } + + @Test + void constructorNullValueFactoryThrowsTest() { + assertThrows(NullPointerException.class, () -> new JSONLDParser(new CoreseModel(), null)); + } + + @Test + void constructorNullModelAndValueFactoryThrowsTest() { + assertThrows(NullPointerException.class, () -> new JSONLDParser(null, null)); + } + + @Test + void constructorConfigNoThrowsTest() { + assertDoesNotThrow(() -> new JSONLDParser(new CoreseModel(), valueFactory, null)); + } + + @Test + void getRDFFormatTest() { + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, new CoreseModel(), valueFactory); + assertEquals(RDFFormat.JSONLD, parser.getRDFFormat()); + } + + /** + * Test method for {@link JSONLDParser#parse(java.io.InputStream)}. No relative IRIs in this test. + */ + @Test + public void testParseInputStream() { + // taken from https://www.w3.org/TR/json-ld-api/#object-to-rdf-conversion + String sampleJsonLD = """ + { + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "knows": "http://xmlns.com/foaf/0.1/knows" + }, + "@id": "http://me.markus-lanthaler.com/", + "name": "Markus Lanthaler", + "knows": [ + { + "name": "Dave Longley" + } + ] + } + """; + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); + + assertEquals(3, model.size()); + IRI subject = valueFactory.createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = valueFactory.createLiteral("Markus Lanthaler"); + Literal nameDaveObject = valueFactory.createLiteral("Dave Longley"); + Statement daveNameStatement = valueFactory.createStatement(subject, namePredicate, nameMarkusObject); + + assertTrue(model.contains(daveNameStatement)); + assertTrue(model.contains(subject, knowsPredicate, null)); + assertTrue(model.contains(null, namePredicate, nameDaveObject)); + } + + /** + * Test method for {@link JSONLDParser#parse(java.io.InputStream, java.lang.String)}. A relative IRI is used in this test. + */ + @Test + public void testParseInputStreamString() { + // taken from https://www.w3.org/TR/json-ld-api/#object-to-rdf-conversion + String sampleJsonLD = """ + { + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "knows": "http://xmlns.com/foaf/0.1/knows" + }, + "@id": "", + "name": "Markus Lanthaler", + "knows": [ + { + "name": "Dave Longley" + } + ] + } + """; + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes()), "http://me.markus-lanthaler.com/"); + + assertEquals(3, model.size()); + IRI subject = valueFactory.createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = valueFactory.createLiteral("Markus Lanthaler"); + Literal nameDaveObject = valueFactory.createLiteral("Dave Longley"); + Statement daveNameStatement = valueFactory.createStatement(subject, namePredicate, nameMarkusObject); + + assertTrue(model.contains(daveNameStatement)); + assertTrue(model.contains(subject, knowsPredicate, null)); + assertTrue(model.contains(null, namePredicate, nameDaveObject)); + } + + /** + * Test of {@link JSONLDParser#parse(java.io.Reader, java.lang.String)}, of class JSONLDParser. No relative IRIs are used in this test. + */ + @Test + public void testParseReader() { + // taken from https://www.w3.org/TR/json-ld-api/#object-to-rdf-conversion + String sampleJsonLD = """ + { + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "knows": "http://xmlns.com/foaf/0.1/knows" + }, + "@id": "http://me.markus-lanthaler.com/", + "name": "Markus Lanthaler", + "knows": [ + { + "name": "Dave Longley" + } + ] + } + """; + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + parser.parse(new StringReader(sampleJsonLD)); + + assertEquals(3, model.size()); + IRI subject = valueFactory.createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = valueFactory.createLiteral("Markus Lanthaler"); + Literal nameDaveObject = valueFactory.createLiteral("Dave Longley"); + Statement daveNameStatement = valueFactory.createStatement(subject, namePredicate, nameMarkusObject); + + assertTrue(model.contains(daveNameStatement)); + assertTrue(model.contains(subject, knowsPredicate, null)); + assertTrue(model.contains(null, namePredicate, nameDaveObject)); + } + + /** + * Test of {@link JSONLDParser#parse(java.io.Reader, java.lang.String)}, of class JSONLDParser. A relative IRI is used in this test. + */ + @Test + public void testParseReaderString() { + // taken from https://www.w3.org/TR/json-ld-api/#object-to-rdf-conversion + String sampleJsonLD = """ + { + "@context": { + "name": "http://xmlns.com/foaf/0.1/name", + "knows": "http://xmlns.com/foaf/0.1/knows" + }, + "@id": "", + "name": "Markus Lanthaler", + "knows": [ + { + "name": "Dave Longley" + } + ] + } + """; + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + parser.parse(new StringReader(sampleJsonLD), "http://me.markus-lanthaler.com/"); + + assertEquals(3, model.size()); + IRI subject = valueFactory.createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = valueFactory.createLiteral("Markus Lanthaler"); + Literal nameDaveObject = valueFactory.createLiteral("Dave Longley"); + Statement daveNameStatement = valueFactory.createStatement(subject, namePredicate, nameMarkusObject); + + assertTrue(model.contains(daveNameStatement)); + assertTrue(model.contains(subject, knowsPredicate, null)); + assertTrue(model.contains(null, namePredicate, nameDaveObject)); + } + + /** + * Test parsing JSON-LD with blank nodes. + */ + @Test + public void testParseJsonLDWithBlankNodes() { + String sampleJsonLD = """ + { + "@context": { + "foaf": "http://xmlns.com/foaf/0.1/" + }, + + "@graph": + [ + { + "@id": "_:b0", + "foaf:knows": {"@id": "_:b1"} + }, + + { + "@id": "_:b1", + "foaf:knows": {"@id": "_:b0"} + } + ] + } + + """; + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + Reader reader = new StringReader(sampleJsonLD); + parser.parse(reader); + + assertEquals(2, model.size()); + BNode b0 = valueFactory.createBNode("b0"); + BNode b1 = valueFactory.createBNode("b1"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + assertTrue(model.contains(b0, knowsPredicate, b1)); + assertTrue(model.contains(b1, knowsPredicate, b0)); + } + + @Test + public void testParseJSONLDWithGraphs() { + // Taken from https://www.w3.org/TR/json-ld11/#named-graphs + String sampleJsonLD = """ + { + "@context": { + "generatedAt": { + "@id": "http://www.w3.org/ns/prov#generatedAtTime" + }, + "Person": { + "@id": "http://xmlns.com/foaf/0.1/Person" + }, + "name": { + "@id": "http://xmlns.com/foaf/0.1/name" + }, + "knows": {"@id": "http://xmlns.com/foaf/0.1/knows", "@type": "@id"} + }, + "@id": "http://example.org/foaf-graph", + "generatedAt": { + "@value": "2012-04-09T00:00:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "@graph": [ + { + "@id": "http://manu.sporny.org/about#manu", + "@type": "Person", + "name": "Manu Sporny", + "knows": "https://greggkellogg.net/foaf#me" + }, { + "@id": "https://greggkellogg.net/foaf#me", + "@type": "Person", + "name": "Gregg Kellogg", + "knows": "http://manu.sporny.org/about#manu" + } + ] + } + """; + + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); + parser.parse(new StringReader(sampleJsonLD)); + + assertEquals(7, model.size()); + Resource graphIRI = valueFactory.createIRI("http://example.org/foaf-graph"); + IRI generatedAt = valueFactory.createIRI("http://www.w3.org/ns/prov#generatedAtTime"); + IRI datetimeDatatype = valueFactory.createIRI("http://www.w3.org/2001/XMLSchema#dateTime"); + Literal generatedAtValue = valueFactory.createLiteral("2012-04-09T00:00:00", datetimeDatatype) ; + IRI manuIRI = valueFactory.createIRI("http://manu.sporny.org/about#manu"); + Literal manuName = valueFactory.createLiteral("Manu Sporny"); + IRI greggIRI = valueFactory.createIRI("https://greggkellogg.net/foaf#me"); + Literal greggName = valueFactory.createLiteral("Gregg Kellogg"); + IRI typeIRI = valueFactory.createIRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + IRI knowsPredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/knows"); + IRI personType = valueFactory.createIRI("http://xmlns.com/foaf/0.1/Person"); + IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); + + // . + assertTrue(model.contains(manuIRI, knowsPredicate, greggIRI, graphIRI)); + // "Gregg Kellogg" . + assertTrue(model.contains(greggIRI, namePredicate, greggName, graphIRI)); + // . + assertTrue(model.contains(greggIRI, knowsPredicate, manuIRI, graphIRI)); + // . + assertTrue(model.contains(manuIRI, typeIRI, personType, graphIRI)); + // "2012-04-09T00:00:00"^^ . + assertTrue(model.contains(graphIRI, generatedAt, generatedAtValue)); + // "Manu Sporny" . + assertTrue(model.contains(manuIRI, namePredicate, manuName, graphIRI)); + // . + assertTrue(model.contains(greggIRI, typeIRI, personType, graphIRI)); + } +} diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserTest.java similarity index 91% rename from src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java rename to src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserTest.java index 6d8f12c83..13a245645 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserTest.java @@ -2,7 +2,7 @@ import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.ValueFactory; -import fr.inria.corese.core.next.api.base.parser.RDFParser; +import fr.inria.corese.core.next.api.io.parser.RDFParser; import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; import fr.inria.corese.core.next.impl.temp.CoreseModel; import org.junit.jupiter.api.Test; @@ -11,7 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -public class ANTLRTurtleParserSpec { +public class ANTLRTurtleParserTest { private Model parseFromString(String turtleData, String baseURI) throws Exception { Model model = new CoreseModel(); ValueFactory factory = new CoreseAdaptedValueFactory(); diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplTest.java similarity index 93% rename from src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java rename to src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplTest.java index 3f7326452..7d7a15bc0 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplTest.java @@ -18,7 +18,7 @@ import static org.junit.jupiter.api.Assertions.*; -public class TurtleListenerImplSpec { +public class TurtleListenerImplTest { private Model parseAndPrintModel(String turtleData) throws Exception { ValueFactory factory = new CoreseAdaptedValueFactory(); @@ -30,20 +30,9 @@ private Model parseAndPrintModel(String turtleData) throws Exception { ParseTree tree = parser.turtleDoc(); Model model = new CoreseModel(); - TurtleListenerImpl listener = new TurtleListenerImpl(model, null, factory); + TurtleListenerImpl listener = new TurtleListenerImpl(model, factory, null); walker.walk((ParseTreeListener) listener, tree); - - /* - model.forEach(stmt -> { - System.out.println(stmt.getSubject().stringValue() + " " + - stmt.getPredicate().stringValue() + " " + - stmt.getObject().stringValue()); - }); - - */ - - return model; } diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactoryTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java similarity index 72% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactoryTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java index b6ad13c7e..cbc605952 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactoryTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java @@ -1,8 +1,14 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.RdfSerializer; -import fr.inria.corese.core.next.api.SerializationConfig; +import fr.inria.corese.core.next.api.base.io.RDFFormat; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.api.io.serialization.SerializationOption; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsSerializer; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesSerializer; +import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlSerializer; +import fr.inria.corese.core.next.impl.io.serialization.trig.TriGSerializer; +import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleSerializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,28 +21,28 @@ /** * Unit tests for the {@link DefaultSerializerFactory} class. * This class verifies that the factory correctly creates instances of - * various {@link RdfSerializer} implementations based on the provided - * {@link RdfFormat} and handles null inputs gracefully. + * various {@link RDFSerializer} implementations based on the provided + * {@link RDFFormat} and handles null inputs gracefully. */ class DefaultSerializerFactoryTest { private DefaultSerializerFactory factory; private Model mockModel; - private SerializationConfig mockConfig; + private SerializationOption mockConfig; @BeforeEach void setUp() { factory = new DefaultSerializerFactory(); mockModel = mock(Model.class); - mockConfig = mock(SerializationConfig.class); + mockConfig = mock(SerializationOption.class); } @Test @DisplayName("createSerializer should return TurtleSerializer for TURTLE format") void createSerializer_shouldReturnTurtleSerializer_forTurtleFormat() { try (MockedConstruction mockedConstruction = mockConstruction(TurtleSerializer.class)) { - RdfSerializer serializer = factory.createSerializer(RdfFormat.TURTLE, mockModel, mockConfig); + RDFSerializer serializer = factory.createSerializer(RDFFormat.TURTLE, mockModel, mockConfig); assertNotNull(serializer); assertTrue(serializer instanceof TurtleSerializer); @@ -48,7 +54,7 @@ void createSerializer_shouldReturnTurtleSerializer_forTurtleFormat() { @DisplayName("createSerializer should return NTriplesSerializer for NTRIPLES format") void createSerializer_shouldReturnNTriplesSerializer_forNTriplesFormat() { try (MockedConstruction mockedConstruction = mockConstruction(NTriplesSerializer.class)) { - RdfSerializer serializer = factory.createSerializer(RdfFormat.NTRIPLES, mockModel, mockConfig); + RDFSerializer serializer = factory.createSerializer(RDFFormat.NTRIPLES, mockModel, mockConfig); assertNotNull(serializer); assertTrue(serializer instanceof NTriplesSerializer); @@ -60,7 +66,7 @@ void createSerializer_shouldReturnNTriplesSerializer_forNTriplesFormat() { @DisplayName("createSerializer should return NQuadsSerializer for NQUADS format") void createSerializer_shouldReturnNQuadsSerializer_forNQuadsFormat() { try (MockedConstruction mockedConstruction = mockConstruction(NQuadsSerializer.class)) { - RdfSerializer serializer = factory.createSerializer(RdfFormat.NQUADS, mockModel, mockConfig); + RDFSerializer serializer = factory.createSerializer(RDFFormat.NQUADS, mockModel, mockConfig); assertNotNull(serializer); assertTrue(serializer instanceof NQuadsSerializer); @@ -72,7 +78,7 @@ void createSerializer_shouldReturnNQuadsSerializer_forNQuadsFormat() { @DisplayName("createSerializer should return TriGSerializer for TRIG format") void createSerializer_shouldReturnTriGSerializer_forTriGFormat() { try (MockedConstruction mockedConstruction = mockConstruction(TriGSerializer.class)) { - RdfSerializer serializer = factory.createSerializer(RdfFormat.TRIG, mockModel, mockConfig); + RDFSerializer serializer = factory.createSerializer(RDFFormat.TRIG, mockModel, mockConfig); assertNotNull(serializer); assertTrue(serializer instanceof TriGSerializer); @@ -84,7 +90,7 @@ void createSerializer_shouldReturnTriGSerializer_forTriGFormat() { @DisplayName("createSerializer should return XmlSerializer for RDFXML format") void createSerializer_shouldReturnXmlSerializer_forRdfXmlFormat() { try (MockedConstruction mockedConstruction = mockConstruction(XmlSerializer.class)) { - RdfSerializer serializer = factory.createSerializer(RdfFormat.RDFXML, mockModel, mockConfig); + RDFSerializer serializer = factory.createSerializer(RDFFormat.RDFXML, mockModel, mockConfig); assertNotNull(serializer); assertTrue(serializer instanceof XmlSerializer); @@ -97,14 +103,14 @@ void createSerializer_shouldReturnXmlSerializer_forRdfXmlFormat() { void createSerializer_shouldThrowNPE_forNullFormat() { assertThrows(NullPointerException.class, () -> factory.createSerializer(null, mockModel, mockConfig), - "Should throw NullPointerException for null RdfFormat"); + "Should throw NullPointerException for null RDFFormat"); } @Test @DisplayName("createSerializer should throw NullPointerException for a null model") void createSerializer_shouldThrowNPE_forNullModel() { assertThrows(NullPointerException.class, - () -> factory.createSerializer(RdfFormat.TURTLE, null, mockConfig), + () -> factory.createSerializer(RDFFormat.TURTLE, null, mockConfig), "Should throw NullPointerException for null Model"); } @@ -112,7 +118,7 @@ void createSerializer_shouldThrowNPE_forNullModel() { @DisplayName("createSerializer should throw NullPointerException for a null config") void createSerializer_shouldThrowNPE_forNullConfig() { assertThrows(NullPointerException.class, - () -> factory.createSerializer(RdfFormat.TURTLE, mockModel, null), + () -> factory.createSerializer(RDFFormat.TURTLE, mockModel, null), "Should throw NullPointerException for null SerializationConfig"); } } diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TestStatementFactory.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/TestStatementFactory.java similarity index 98% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/TestStatementFactory.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/TestStatementFactory.java index 3fd8dc034..b16e046a1 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TestStatementFactory.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/TestStatementFactory.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import fr.inria.corese.core.next.api.IRI; import fr.inria.corese.core.next.api.Literal; diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerTest.java new file mode 100644 index 000000000..b8a97059d --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerTest.java @@ -0,0 +1,233 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import com.apicatalog.jsonld.json.JsonLdComparison; +import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.impl.io.option.TitaniumJSONLDProcessorOption; +import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; +import fr.inria.corese.core.next.impl.temp.CoreseModel; +import jakarta.json.Json; +import jakarta.json.JsonReader; +import jakarta.json.JsonReaderFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; + +import static org.junit.jupiter.api.Assertions.*; + +class JSONLDSerializerTest { + + private Model model; + private ValueFactory factory = new CoreseAdaptedValueFactory(); + private IRI iriNode = factory.createIRI("http://example.org/iri1"); + private IRI iriPred = factory.createIRI("http://example.org/pred1"); + private Literal basicLiteral = factory.createLiteral("literal1"); + private Literal typedLiteral = factory.createLiteral("literal2", factory.createIRI("http://example.org/datatype1")); + private Literal langLiteral = factory.createLiteral("literal3", "en"); + private BNode blankNode = factory.createBNode("blank1"); + private IRI graph1 = factory.createIRI("http://example.org/graph1"); + private IRI graph2 = factory.createIRI("http://example.org/graph2"); + + @BeforeEach + public void setUp() { + model = new CoreseModel(); + } + + /** + * Check that the serializer can handle a small model with all types of literals + */ + @Test + public void smallModelTest() { + // IRI IRI IRI + this.model.add(iriNode, iriPred, iriNode); + // IRI IRI Literal + this.model.add(iriNode, iriPred, basicLiteral); + // IRI IRI TypedLiteral + this.model.add(iriNode, iriPred, typedLiteral); + // IRI IRI LangLiteral + this.model.add(iriNode, iriPred, langLiteral); + + RDFSerializer serializer = new JSONLDSerializer(this.model, (new TitaniumJSONLDProcessorOption.Builder()).ordered(true).build()); + + StringWriter writer = new StringWriter(); + + serializer.write(writer); + String result = writer.toString(); + + String expectedResult = """ + [ + { + "@id": "http://example.org/iri1", + "http://example.org/pred1": [ + { + "@id": "http://example.org/iri1" + }, + { + "@value": "literal1" + }, + { + "@value": "literal2", + "@type": "http://example.org/datatype1" + }, + { + "@language": "en", + "@value": "literal3" + } + ] + } + ] + """.replace('\n', ' ').replaceAll("\\s+", ""); + + Reader resultReader = new StringReader(result); + Reader expectedResultReader = new StringReader(expectedResult); + + JsonReaderFactory factory = Json.createReaderFactory(null); + JsonReader resultJsonReader = factory.createReader(resultReader); + JsonReader expectedResultJsonReader = factory.createReader(expectedResultReader); + assertTrue(JsonLdComparison.equals(resultJsonReader.readValue(), expectedResultJsonReader.readValue()), "The result should be the expected JSON object"); + } + + /** + * Test the serialization of a model with blank nodes. + */ + @Test + public void modelWithBlankNodesTest() { + // IRI IRI BlankNode + this.model.add(iriNode, iriPred, blankNode); + // BlankNode IRI IRI + this.model.add(blankNode, iriPred, iriNode); + // BlankNode IRI Literal + this.model.add(blankNode, iriPred, basicLiteral); + // BlankNode IRI BlankNode + this.model.add(blankNode, iriPred, blankNode); + + RDFSerializer serializer = new JSONLDSerializer(this.model); + + StringWriter writer = new StringWriter(); + serializer.write(writer); + String result = writer.toString(); + + String expectedResult = """ +[ + { + "@id":"http://example.org/iri1", + "http://example.org/pred1":[ + {"@id":"blank1"} + ] + }, + { + "@id":"blank1", + "http://example.org/pred1":[ + { + "@id":"http://example.org/iri1" + }, + { + "@id":"blank1" + }, + { + "@value":"literal1" + } + ] + } +] + """.replace('\n', ' ').replaceAll("\\s+", ""); + + Reader resultReader = new StringReader(result); + Reader expectedResultReader = new StringReader(expectedResult); + + JsonReaderFactory factory = Json.createReaderFactory(null); + JsonReader resultJsonReader = factory.createReader(resultReader); + JsonReader expectedResultJsonReader = factory.createReader(expectedResultReader); + assertTrue(JsonLdComparison.equals(resultJsonReader.readValue(), expectedResultJsonReader.readValue()), "The result should be " + expectedResult); + } + + /** + * Test the serialization of a model with named graphs. + */ + @Test + public void modelWithNamedGraphsTest() { + // IRI IRI IRI + this.model.add(iriNode, iriPred, iriNode); + // IRI IRI Literal + this.model.add(iriNode, iriPred, basicLiteral, graph1); + // IRI IRI TypedLiteral + this.model.add(iriNode, iriPred, typedLiteral, graph2); + // IRI IRI LangLiteral + this.model.add(iriNode, iriPred, langLiteral, graph1, graph2); + + RDFSerializer serializer = new JSONLDSerializer(this.model); + + StringWriter writer = new StringWriter(); + serializer.write(writer); + String result = writer.toString(); + + String expectedResult = """ +[ + { + "@id":"http://example.org/iri1", + "http://example.org/pred1":[ + { + "@id":"http://example.org/iri1" + }, + { + "@value":"literal1" + }, + { + "@value":"literal2", + "@type":"http://example.org/datatype1" + }, + { + "@language":"en", + "@value":"literal3" + } + ] + }, + { + "@id":"http://example.org/graph1", + "@graph":[ + { + "@id":"http://example.org/iri1", + "http://example.org/pred1":[ + { + "@value":"literal1" + }, + { + "@language":"en", + "@value":"literal3" + } + ] + } + ] + }, + { + "@id":"http://example.org/graph2", + "@graph":[ + { + "@id":"http://example.org/iri1", + "http://example.org/pred1":[ + { + "@value":"literal2", + "@type":"http://example.org/datatype1" + }, + { + "@language":"en", + "@value":"literal3" + } + ] + } + ] + } +] + """.replace('\n', ' ').replaceAll("\\s+", ""); + Reader resultReader = new StringReader(result); + Reader expectedResultReader = new StringReader(expectedResult); + + JsonReaderFactory jsonReaderFactory = Json.createReaderFactory(null); + JsonReader resultJsonReader = jsonReaderFactory.createReader(resultReader); + JsonReader expectedResultJsonReader = jsonReaderFactory.createReader(expectedResultReader); + assertTrue(JsonLdComparison.equals(resultJsonReader.readValue(), expectedResultJsonReader.readValue()), "The result should be the " + expectedResult); + } +} \ No newline at end of file diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOptionTest.java similarity index 80% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOptionTest.java index 8fdb09247..2b0428c11 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsOptionTest.java @@ -1,25 +1,26 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.nquads; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for the {@link NQuadsConfig} class. + * Unit tests for the {@link NQuadsOption} class. * These tests verify the default configuration settings and the functionality * of the builder pattern for customizing N-Quads serialization options. */ -class NQuadsConfigTest { +class NQuadsOptionTest { @Test @DisplayName("defaultConfig() should return a config with expected N-Quads defaults") void defaultConfig_shouldReturnExpectedDefaults() { - NQuadsConfig config = NQuadsConfig.defaultConfig(); + NQuadsOption config = NQuadsOption.defaultConfig(); assertNotNull(config, "Default config should not be null"); - assertTrue(config.strictMode, "Default strictMode should be true for N-Quads"); + assertTrue(config.isStrictMode(), "Default strictMode should be true for N-Quads"); assertTrue(config.escapeUnicode(), "Default escapeUnicode should be true for N-Quads"); assertEquals(LiteralDatatypePolicyEnum.ALWAYS_TYPED, config.getLiteralDatatypePolicy(), "Default literalDatatypePolicy should be ALWAYS_TYPED"); assertNull(config.getBaseIRI(), "Default baseIRI should be null"); @@ -31,7 +32,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { @Test @DisplayName("Builder should allow overriding includeContext") void builder_shouldAllowOverridingIncludeContext() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .includeContext(false) .build(); @@ -41,7 +42,7 @@ void builder_shouldAllowOverridingIncludeContext() { @Test @DisplayName("Builder should allow overriding literalDatatypePolicy") void builder_shouldAllowOverridingLiteralDatatypePolicy() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .build(); @@ -51,7 +52,7 @@ void builder_shouldAllowOverridingLiteralDatatypePolicy() { @Test @DisplayName("Builder should allow overriding escapeUnicode") void builder_shouldAllowOverridingEscapeUnicode() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .escapeUnicode(false) .build(); @@ -61,18 +62,18 @@ void builder_shouldAllowOverridingEscapeUnicode() { @Test @DisplayName("Builder should allow overriding strictMode") void builder_shouldAllowOverridingStrictMode() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .strictMode(false) .build(); - assertFalse(config.strictMode, "strictMode should be overridden to false"); + assertFalse(config.isStrictMode(), "strictMode should be overridden to false"); } @Test @DisplayName("Builder should allow setting baseIRI") void builder_shouldAllowSettingBaseIRI() { String testBaseIRI = "http://example.org/base/"; - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .baseIRI(testBaseIRI) .build(); @@ -83,7 +84,7 @@ void builder_shouldAllowSettingBaseIRI() { @DisplayName("Builder should allow setting lineEnding") void builder_shouldAllowSettingLineEnding() { String customLineEnding = "\r\n"; - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .lineEnding(customLineEnding) .build(); @@ -93,7 +94,7 @@ void builder_shouldAllowSettingLineEnding() { @Test @DisplayName("Builder should allow overriding validateURIs") void builder_shouldAllowOverridingValidateURIs() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .validateURIs(true) .build(); @@ -103,7 +104,7 @@ void builder_shouldAllowOverridingValidateURIs() { @Test @DisplayName("Builder should allow overriding stableBlankNodeIds") void builder_shouldAllowOverridingStableBlankNodeIds() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .stableBlankNodeIds(true) .build(); @@ -113,7 +114,7 @@ void builder_shouldAllowOverridingStableBlankNodeIds() { @Test @DisplayName("Builder should handle null values for optional fields gracefully (e.g., baseIRI)") void builder_shouldHandleNullForOptionalFields() { - NQuadsConfig config = NQuadsConfig.builder() + NQuadsOption config = NQuadsOption.builder() .baseIRI(null) .build(); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializerTest.java similarity index 97% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializerTest.java index 2feaa385b..ea3f653a9 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsSerializerTest.java @@ -1,8 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.nquads; import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.impl.common.serialization.config.NQuadsConfig; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; import fr.inria.corese.core.next.impl.exception.SerializationException; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -21,7 +22,7 @@ class NQuadsSerializerTest { private Model model; - private NQuadsConfig config; + private NQuadsOption config; private NQuadsSerializer nQuadsSerializer; private TestStatementFactory factory; @@ -40,7 +41,7 @@ class NQuadsSerializerTest { @BeforeEach void setUp() { model = mock(Model.class); - config = NQuadsConfig.defaultConfig(); + config = NQuadsOption.defaultConfig(); nQuadsSerializer = new NQuadsSerializer(model, config); factory = new TestStatementFactory(); @@ -262,7 +263,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Writer writer = new StringWriter(); - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsConfig.defaultConfig()); + NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -285,7 +286,7 @@ void shouldHandleLiteralsWithCustomDatatypes() throws SerializationException { Model currentTestModel = mock(Model.class); when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsConfig.defaultConfig()); + NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); StringWriter writer = new StringWriter(); serializer.write(writer); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOptionTest.java similarity index 79% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOptionTest.java index 0f7ec0927..d4b4f7d42 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesOptionTest.java @@ -1,25 +1,26 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for the {@link NTriplesConfig} class. + * Unit tests for the {@link NTriplesOption} class. * These tests verify the default configuration settings and the functionality * of the builder pattern for customizing N-Triples serialization options. */ -class NTriplesConfigTest { +class NTriplesOptionTest { @Test @DisplayName("defaultConfig() should return a config with expected N-Triples defaults") void defaultConfig_shouldReturnExpectedDefaults() { - NTriplesConfig config = NTriplesConfig.defaultConfig(); + NTriplesOption config = NTriplesOption.defaultConfig(); assertNotNull(config, "Default config should not be null"); - assertTrue(config.strictMode, "Default strictMode should be true for N-Triples"); + assertTrue(config.isStrictMode(), "Default strictMode should be true for N-Triples"); assertTrue(config.escapeUnicode(), "Default escapeUnicode should be true for N-Triples"); assertEquals(LiteralDatatypePolicyEnum.ALWAYS_TYPED, config.getLiteralDatatypePolicy(), "Default literalDatatypePolicy should be ALWAYS_TYPED"); assertNull(config.getBaseIRI(), "Default baseIRI should be null"); @@ -31,7 +32,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { @Test @DisplayName("Builder should allow overriding includeContext") void builder_shouldAllowOverridingIncludeContext() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .includeContext(true) .build(); @@ -41,7 +42,7 @@ void builder_shouldAllowOverridingIncludeContext() { @Test @DisplayName("Builder should allow overriding literalDatatypePolicy") void builder_shouldAllowOverridingLiteralDatatypePolicy() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .build(); @@ -51,7 +52,7 @@ void builder_shouldAllowOverridingLiteralDatatypePolicy() { @Test @DisplayName("Builder should allow overriding escapeUnicode") void builder_shouldAllowOverridingEscapeUnicode() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .escapeUnicode(false) .build(); @@ -61,18 +62,18 @@ void builder_shouldAllowOverridingEscapeUnicode() { @Test @DisplayName("Builder should allow overriding strictMode") void builder_shouldAllowOverridingStrictMode() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .strictMode(false) .build(); - assertFalse(config.strictMode, "strictMode should be overridden to false"); + assertFalse(config.isStrictMode(), "strictMode should be overridden to false"); } @Test @DisplayName("Builder should allow setting baseIRI") void builder_shouldAllowSettingBaseIRI() { String testBaseIRI = "http://example.org/base/"; - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .baseIRI(testBaseIRI) .build(); @@ -83,7 +84,7 @@ void builder_shouldAllowSettingBaseIRI() { @DisplayName("Builder should allow setting lineEnding") void builder_shouldAllowSettingLineEnding() { String customLineEnding = "\r\n"; - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .lineEnding(customLineEnding) .build(); @@ -93,7 +94,7 @@ void builder_shouldAllowSettingLineEnding() { @Test @DisplayName("Builder should allow overriding validateURIs") void builder_shouldAllowOverridingValidateURIs() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .validateURIs(true) .build(); @@ -103,7 +104,7 @@ void builder_shouldAllowOverridingValidateURIs() { @Test @DisplayName("Builder should allow overriding stableBlankNodeIds") void builder_shouldAllowOverridingStableBlankNodeIds() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .stableBlankNodeIds(true) .build(); @@ -113,7 +114,7 @@ void builder_shouldAllowOverridingStableBlankNodeIds() { @Test @DisplayName("Builder should handle null values for optional fields gracefully (e.g., baseIRI)") void builder_shouldHandleNullForOptionalFields() { - NTriplesConfig config = NTriplesConfig.builder() + NTriplesOption config = NTriplesOption.builder() .baseIRI(null) .build(); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializerTest.java similarity index 88% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializerTest.java index aa51f1536..07b4088f1 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesSerializerTest.java @@ -1,13 +1,15 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.impl.common.serialization.config.NTriplesConfig; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; import fr.inria.corese.core.next.impl.exception.SerializationException; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mockito; import java.io.IOException; import java.io.StringWriter; @@ -21,7 +23,7 @@ class NTriplesSerializerTest { private Model model; - private NTriplesConfig config; + private NTriplesOption config; private NTriplesSerializer nTriplesSerializer; private TestStatementFactory factory; @@ -40,7 +42,7 @@ class NTriplesSerializerTest { @BeforeEach void setUp() { model = mock(Model.class); - config = NTriplesConfig.defaultConfig(); + config = NTriplesOption.defaultConfig(); nTriplesSerializer = new NTriplesSerializer(model, config); factory = new TestStatementFactory(); @@ -75,7 +77,7 @@ void writeShouldSerializeSimpleStatement() throws SerializationException { mockExName, mockLiteralJohn ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); nTriplesSerializer.write(writer); @@ -85,7 +87,7 @@ void writeShouldSerializeSimpleStatement() throws SerializationException { mockExName.stringValue(), escapeNTriplesString(lexJohn)) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -98,7 +100,7 @@ void writeShouldSerializeStatementWithContext() throws SerializationException { mockLiteralJohn, mockContext ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); nTriplesSerializer.write(writer); @@ -108,7 +110,7 @@ void writeShouldSerializeStatementWithContext() throws SerializationException { mockExName.stringValue(), escapeNTriplesString(lexJohn)) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -119,7 +121,7 @@ void writeShouldHandleBlankNodes() throws SerializationException { mockExKnows, mockBNode2 ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); nTriplesSerializer.write(writer); @@ -129,7 +131,7 @@ void writeShouldHandleBlankNodes() throws SerializationException { mockExKnows.stringValue(), mockBNode2.stringValue()) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -140,9 +142,9 @@ void writeShouldThrowOnIOException() throws IOException { mockExName, mockLiteralJohn ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - Writer faultyWriter = mock(Writer.class); + Writer faultyWriter = Mockito.mock(Writer.class); doThrow(new IOException("Simulated IO error during write")).when(faultyWriter).write(anyString()); doThrow(new IOException("Simulated IO error (char array)")).when(faultyWriter).write(any(char[].class), anyInt(), anyInt()); @@ -188,11 +190,11 @@ void writeShouldThrowOnNullPredicateValue() { @Test @DisplayName("Write should throw SerializationException for null object value in strict mode") void writeShouldThrowOnNullObjectValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(mockExPerson); - when(stmt.getPredicate()).thenReturn(mockExName); - when(stmt.getObject()).thenReturn(null); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Statement stmt = Mockito.mock(Statement.class); + Mockito.when(stmt.getSubject()).thenReturn(mockExPerson); + Mockito.when(stmt.getPredicate()).thenReturn(mockExName); + Mockito.when(stmt.getObject()).thenReturn(null); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); @@ -243,7 +245,7 @@ void writeShouldHandleVariousLiterals(String literalValue) throws SerializationE mockExName, literalMock ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); nTriplesSerializer.write(writer); @@ -255,21 +257,20 @@ void writeShouldHandleVariousLiterals(String literalValue) throws SerializationE mockExName.stringValue(), expectedEscapedLiteral) + " .\n"; - assertEquals(expectedOutput, writer.toString()); + Assertions.assertEquals(expectedOutput, writer.toString()); } - @Test @DisplayName("Should handle literals with language tags") void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Statement stmt = factory.createStatement(mockExPerson, factory.createIRI("http://example.org/greeting"), mockLiteralHelloEn); - Model currentTestModel = mock(Model.class); - when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); + Model currentTestModel = Mockito.mock(Model.class); + Mockito.when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesConfig.defaultConfig()); + NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -278,7 +279,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { escapeNTriplesString(hello), mockLiteralHelloEn.getLanguage().get()) + " .\n"; - assertEquals(expectedOutput, writer.toString()); + Assertions.assertEquals(expectedOutput, writer.toString()); } @@ -293,7 +294,7 @@ void shouldHandleLiteralsWithCustomDatatypes() throws SerializationException { Model currentTestModel = mock(Model.class); when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesConfig.defaultConfig()); + NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); StringWriter writer = new StringWriter(); serializer.write(writer); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlConfigTest.java similarity index 85% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlConfigTest.java index 7e55fd903..562bd866d 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlConfigTest.java @@ -1,6 +1,8 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.rdfxml; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for the {@link XmlConfig} class. + * Unit tests for the {@link XmlOption} class. * These tests verify the default configuration settings and the functionality * of the builder pattern for customizing RDF/XML serialization options. */ @@ -19,7 +21,7 @@ class XmlConfigTest { @Test @DisplayName("defaultConfig() should return a config with expected RDF/XML defaults") void defaultConfig_shouldReturnExpectedDefaults() { - XmlConfig config = XmlConfig.defaultConfig(); + XmlOption config = XmlOption.defaultConfig(); assertNotNull(config, "Default config should not be null"); @@ -42,7 +44,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { assertFalse(config.sortPredicates(), "Default sortPredicates should be false for XML"); assertTrue(config.useMultilineLiterals(), "Default useMultilineLiterals should be true for XML"); - assertTrue(config.strictMode, "Default strictMode should be true"); + assertTrue(config.isStrictMode(), "Default strictMode should be true"); assertFalse(config.escapeUnicode(), "Default escapeUnicode should be false for XML"); assertEquals(LiteralDatatypePolicyEnum.ALWAYS_TYPED, config.getLiteralDatatypePolicy(), "Default literalDatatypePolicy should be ALWAYS_TYPED for XML"); assertNull(config.getBaseIRI(), "Default baseIRI should be null"); @@ -52,7 +54,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { @Test @DisplayName("Builder should allow overriding usePrefixes") void builder_shouldAllowOverridingUsePrefixes() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .usePrefixes(false) .build(); assertFalse(config.usePrefixes(), "usePrefixes should be overridden to false"); @@ -61,7 +63,7 @@ void builder_shouldAllowOverridingUsePrefixes() { @Test @DisplayName("Builder should allow overriding autoDeclarePrefixes") void builder_shouldAllowOverridingAutoDeclarePrefixes() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .autoDeclarePrefixes(false) .build(); assertFalse(config.autoDeclarePrefixes(), "autoDeclarePrefixes should be overridden to false"); @@ -70,7 +72,7 @@ void builder_shouldAllowOverridingAutoDeclarePrefixes() { @Test @DisplayName("Builder should allow overriding prefixOrdering") void builder_shouldAllowOverridingPrefixOrdering() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .prefixOrdering(PrefixOrderingEnum.USAGE_ORDER) .build(); assertEquals(PrefixOrderingEnum.USAGE_ORDER, config.getPrefixOrdering(), "prefixOrdering should be overridden to USAGE_ORDER"); @@ -81,7 +83,7 @@ void builder_shouldAllowOverridingPrefixOrdering() { void builder_shouldAllowAddingCustomPrefixes() { String customPrefix = "my"; String customNamespace = "http://my.example.org/"; - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .addCustomPrefix(customPrefix, customNamespace) .build(); @@ -94,7 +96,7 @@ void builder_shouldAllowAddingCustomPrefixes() { @Test @DisplayName("Builder should allow overriding prettyPrint") void builder_shouldAllowOverridingPrettyPrint() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .prettyPrint(false) .build(); assertFalse(config.prettyPrint(), "prettyPrint should be overridden to false"); @@ -104,7 +106,7 @@ void builder_shouldAllowOverridingPrettyPrint() { @DisplayName("Builder should allow overriding indent") void builder_shouldAllowOverridingIndent() { String customIndent = "\t"; - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .indent(customIndent) .build(); assertEquals(customIndent, config.getIndent(), "indent should be overridden to custom value"); @@ -114,7 +116,7 @@ void builder_shouldAllowOverridingIndent() { @DisplayName("Builder should allow overriding maxLineLength") void builder_shouldAllowOverridingMaxLineLength() { int customLength = 120; - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .maxLineLength(customLength) .build(); assertEquals(customLength, config.getMaxLineLength(), "maxLineLength should be overridden to custom value"); @@ -123,7 +125,7 @@ void builder_shouldAllowOverridingMaxLineLength() { @Test @DisplayName("Builder should allow overriding sortSubjects") void builder_shouldAllowOverridingSortSubjects() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .sortSubjects(true) .build(); assertTrue(config.sortSubjects(), "sortSubjects should be overridden to true"); @@ -132,7 +134,7 @@ void builder_shouldAllowOverridingSortSubjects() { @Test @DisplayName("Builder should allow overriding sortPredicates") void builder_shouldAllowOverridingSortPredicates() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .sortPredicates(true) .build(); assertTrue(config.sortPredicates(), "sortPredicates should be overridden to true"); @@ -141,7 +143,7 @@ void builder_shouldAllowOverridingSortPredicates() { @Test @DisplayName("Builder should allow overriding useMultilineLiterals") void builder_shouldAllowOverridingUseMultilineLiterals() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .useMultilineLiterals(false) .build(); assertFalse(config.useMultilineLiterals(), "useMultilineLiterals should be overridden to false"); @@ -150,16 +152,16 @@ void builder_shouldAllowOverridingUseMultilineLiterals() { @Test @DisplayName("Builder should allow overriding strictMode") void builder_shouldAllowOverridingStrictMode() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .strictMode(false) .build(); - assertFalse(config.strictMode, "strictMode should be overridden to false"); + assertFalse(config.isStrictMode(), "strictMode should be overridden to false"); } @Test @DisplayName("Builder should allow overriding escapeUnicode") void builder_shouldAllowOverridingEscapeUnicode() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .escapeUnicode(true) .build(); assertTrue(config.escapeUnicode(), "escapeUnicode should be overridden to true"); @@ -168,7 +170,7 @@ void builder_shouldAllowOverridingEscapeUnicode() { @Test @DisplayName("Builder should allow overriding literalDatatypePolicy") void builder_shouldAllowOverridingLiteralDatatypePolicy() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .build(); assertEquals(LiteralDatatypePolicyEnum.MINIMAL, config.getLiteralDatatypePolicy(), "literalDatatypePolicy should be overridden to MINIMAL"); @@ -178,7 +180,7 @@ void builder_shouldAllowOverridingLiteralDatatypePolicy() { @DisplayName("Builder should allow setting baseIRI") void builder_shouldAllowSettingBaseIRI() { String testBaseIRI = "http://example.org/base/"; - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .baseIRI(testBaseIRI) .build(); assertEquals(testBaseIRI, config.getBaseIRI(), "baseIRI should be set correctly"); @@ -188,7 +190,7 @@ void builder_shouldAllowSettingBaseIRI() { @DisplayName("Builder should allow overriding lineEnding") void builder_shouldAllowOverridingLineEnding() { String customLineEnding = "\r\n"; - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .lineEnding(customLineEnding) .build(); assertEquals(customLineEnding, config.getLineEnding(), "lineEnding should be overridden to custom value"); @@ -197,7 +199,7 @@ void builder_shouldAllowOverridingLineEnding() { @Test @DisplayName("Builder should allow overriding validateURIs") void builder_shouldAllowOverridingValidateURIs() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .validateURIs(true) .build(); assertTrue(config.validateURIs(), "validateURIs should be overridden to true"); @@ -206,7 +208,7 @@ void builder_shouldAllowOverridingValidateURIs() { @Test @DisplayName("Builder should allow overriding stableBlankNodeIds") void builder_shouldAllowOverridingStableBlankNodeIds() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .stableBlankNodeIds(false) .build(); assertFalse(config.stableBlankNodeIds(), "stableBlankNodeIds should be overridden to false"); @@ -215,7 +217,7 @@ void builder_shouldAllowOverridingStableBlankNodeIds() { @Test @DisplayName("Builder should allow overriding includeContext") void builder_shouldAllowOverridingIncludeContext() { - XmlConfig config = new XmlConfig.Builder() + XmlOption config = new XmlOption.Builder() .includeContext(true) .build(); assertTrue(config.includeContext(), "includeContext should be overridden to true"); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializerTest.java similarity index 94% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializerTest.java index 54d27e46c..34bae8f51 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/rdfxml/XmlSerializerTest.java @@ -1,11 +1,11 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.rdfxml; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.impl.common.serialization.config.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.PrefixOrderingEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.XmlConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -27,7 +27,7 @@ class XmlSerializerTest { @Mock private Model mockModel; - XmlConfig mockConfig; + XmlOption mockConfig; private TestStatementFactory factory; private StringWriter writer; @@ -38,7 +38,7 @@ void setUp() { writer = new StringWriter(); factory = new TestStatementFactory(); - mockConfig = XmlConfig.defaultConfig(); + mockConfig = XmlOption.defaultConfig(); } @@ -53,7 +53,7 @@ void shouldSerializeSimpleIriTriple() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .autoDeclarePrefixes(true) .usePrefixes(true) .addCustomPrefix("foaf", "http://xmlns.com/foaf/0.1/") @@ -88,7 +88,7 @@ void shouldHandleBlankNodeSubject() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .stableBlankNodeIds(true) .addCustomPrefix("foaf", "http://xmlns.com/foaf/0.1/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -121,7 +121,7 @@ void shouldHandleBlankNodeObject() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .stableBlankNodeIds(true) .addCustomPrefix("dc", "http://purl.org/dc/elements/1.1/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -154,7 +154,7 @@ void shouldSerializeLiteralWithStringDatatypeMinimalPolicy() throws Serializatio when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .addCustomPrefix("foaf", "http://xmlns.com/foaf/0.1/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -185,7 +185,7 @@ void shouldSerializeLiteralWithCustomDatatypeMinimalPolicy() throws Serializatio when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .addCustomPrefix("ex", "http://example.org/vocabulary/") .addCustomPrefix("xsd", "http://www.w3.org/2001/XMLSchema#") @@ -217,7 +217,7 @@ void shouldSerializeLiteralWithLanguage() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .addCustomPrefix("dc", "http://purl.org/dc/elements/1.1/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) .build(); @@ -254,7 +254,7 @@ void shouldRespectPrefixOrderingDefault() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt1, stmt2)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .addCustomPrefix("exorg", "http://ex.org/") .addCustomPrefix("excom", "http://ex.com/") .prefixOrdering(PrefixOrderingEnum.USAGE_ORDER) @@ -296,7 +296,7 @@ void shouldSortSubjectsAlphabetically() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt1, stmt2)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .sortSubjects(true) .addCustomPrefix("ex", "http://ex.org/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -332,7 +332,7 @@ void shouldEscapeXmlAttributeValues() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) .build(); @@ -362,7 +362,7 @@ void shouldEscapeXmlContentValues() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.ALWAYS_TYPED) .addCustomPrefix("ex", "http://example.org/") .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -396,7 +396,7 @@ void shouldNotAutoDeclarePrefixesIfDisabled() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .autoDeclarePrefixes(false) .usePrefixes(true) .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -428,7 +428,7 @@ void shouldNotUsePrefixesIfDisabled() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .usePrefixes(false) .autoDeclarePrefixes(true) .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) @@ -466,7 +466,7 @@ void shouldNotGenerateStableBlankNodeIds() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.of(stmt1, stmt2)); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .stableBlankNodeIds(false) .sortSubjects(true) .addCustomPrefix("ex", "http://example.org/") @@ -497,7 +497,7 @@ void shouldNotGenerateStableBlankNodeIds() throws SerializationException { void shouldHandleEmptyModel() throws SerializationException { when(mockModel.stream()).thenReturn(Stream.empty()); - XmlConfig testConfig = new XmlConfig.Builder() + XmlOption testConfig = new XmlOption.Builder() .prefixOrdering(PrefixOrderingEnum.ALPHABETICAL) .build(); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOptionTest.java similarity index 85% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOptionTest.java index ff16f055f..f847596cf 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGOptionTest.java @@ -1,6 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.trig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.BlankNodeStyleEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,16 +13,16 @@ import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for the {@link TriGConfig} class. + * Unit tests for the {@link TriGOption} class. * These tests verify the default configuration settings and the functionality * of the builder pattern for customizing TriG serialization options. */ -class TriGConfigTest { +class TriGOptionTest { @Test @DisplayName("defaultConfig() should return a config with expected TriG defaults") void defaultConfig_shouldReturnExpectedDefaults() { - TriGConfig config = TriGConfig.defaultConfig(); + TriGOption config = TriGOption.defaultConfig(); assertNotNull(config, "Default config should not be null"); @@ -48,7 +51,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { assertFalse(config.sortSubjects(), "Default sortSubjects should be false"); assertFalse(config.sortPredicates(), "Default sortPredicates should be false"); - assertTrue(config.strictMode, "Default strictMode should be true"); + assertTrue(config.isStrictMode(), "Default strictMode should be true"); assertFalse(config.escapeUnicode(), "Default escapeUnicode should be false"); assertEquals(LiteralDatatypePolicyEnum.MINIMAL, config.getLiteralDatatypePolicy(), "Default literalDatatypePolicy should be MINIMAL"); assertNull(config.getBaseIRI(), "Default baseIRI should be null"); @@ -57,7 +60,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { @Test @DisplayName("Builder should allow overriding includeContext") void builder_shouldAllowOverridingIncludeContext() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .includeContext(false) .build(); assertFalse(config.includeContext(), "includeContext should be overridden to false"); @@ -66,7 +69,7 @@ void builder_shouldAllowOverridingIncludeContext() { @Test @DisplayName("Builder should allow overriding blankNodeStyle") void builder_shouldAllowOverridingBlankNodeStyle() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .blankNodeStyle(BlankNodeStyleEnum.ANONYMOUS) .build(); assertEquals(BlankNodeStyleEnum.ANONYMOUS, config.getBlankNodeStyle(), "blankNodeStyle should be overridden to ANONYMOUS"); @@ -75,7 +78,7 @@ void builder_shouldAllowOverridingBlankNodeStyle() { @Test @DisplayName("Builder should allow overriding useCollections") void builder_shouldAllowOverridingUseCollections() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .useCollections(true) .build(); assertTrue(config.useCollections(), "useCollections should be overridden to true"); @@ -86,7 +89,7 @@ void builder_shouldAllowOverridingUseCollections() { void builder_shouldAllowAddingCustomPrefixes() { String customPrefix = "my"; String customNamespace = "http://my.example.org/"; - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .addCustomPrefix(customPrefix, customNamespace) .build(); @@ -99,7 +102,7 @@ void builder_shouldAllowAddingCustomPrefixes() { @Test @DisplayName("Builder should allow overriding usePrefixes") void builder_shouldAllowOverridingUsePrefixes() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .usePrefixes(false) .build(); assertFalse(config.usePrefixes(), "usePrefixes should be overridden to false"); @@ -108,7 +111,7 @@ void builder_shouldAllowOverridingUsePrefixes() { @Test @DisplayName("Builder should allow overriding autoDeclarePrefixes") void builder_shouldAllowOverridingAutoDeclarePrefixes() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .autoDeclarePrefixes(false) .build(); assertFalse(config.autoDeclarePrefixes(), "autoDeclarePrefixes should be overridden to false"); @@ -117,7 +120,7 @@ void builder_shouldAllowOverridingAutoDeclarePrefixes() { @Test @DisplayName("Builder should allow overriding prefixOrdering") void builder_shouldAllowOverridingPrefixOrdering() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .prefixOrdering(PrefixOrderingEnum.USAGE_ORDER) .build(); assertEquals(PrefixOrderingEnum.USAGE_ORDER, config.getPrefixOrdering(), "prefixOrdering should be overridden to USAGE_ORDER"); @@ -126,7 +129,7 @@ void builder_shouldAllowOverridingPrefixOrdering() { @Test @DisplayName("Builder should allow overriding useCompactTriples") void builder_shouldAllowOverridingUseCompactTriples() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .useCompactTriples(false) .build(); assertFalse(config.useCompactTriples(), "useCompactTriples should be overridden to false"); @@ -135,7 +138,7 @@ void builder_shouldAllowOverridingUseCompactTriples() { @Test @DisplayName("Builder should allow overriding useRdfTypeShortcut") void builder_shouldAllowOverridingUseRdfTypeShortcut() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .useRdfTypeShortcut(false) .build(); assertFalse(config.useRdfTypeShortcut(), "useRdfTypeShortcut should be overridden to false"); @@ -144,7 +147,7 @@ void builder_shouldAllowOverridingUseRdfTypeShortcut() { @Test @DisplayName("Builder should allow overriding useMultilineLiterals") void builder_shouldAllowOverridingUseMultilineLiterals() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .useMultilineLiterals(false) .build(); assertFalse(config.useMultilineLiterals(), "useMultilineLiterals should be overridden to false"); @@ -153,7 +156,7 @@ void builder_shouldAllowOverridingUseMultilineLiterals() { @Test @DisplayName("Builder should allow overriding prettyPrint") void builder_shouldAllowOverridingPrettyPrint() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .prettyPrint(false) .build(); assertFalse(config.prettyPrint(), "prettyPrint should be overridden to false"); @@ -163,7 +166,7 @@ void builder_shouldAllowOverridingPrettyPrint() { @DisplayName("Builder should allow overriding indent") void builder_shouldAllowOverridingIndent() { String customIndent = "\t"; - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .indent(customIndent) .build(); assertEquals(customIndent, config.getIndent(), "indent should be overridden to custom value"); @@ -173,7 +176,7 @@ void builder_shouldAllowOverridingIndent() { @DisplayName("Builder should allow overriding maxLineLength") void builder_shouldAllowOverridingMaxLineLength() { int customLength = 120; - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .maxLineLength(customLength) .build(); assertEquals(customLength, config.getMaxLineLength(), "maxLineLength should be overridden to custom value"); @@ -182,7 +185,7 @@ void builder_shouldAllowOverridingMaxLineLength() { @Test @DisplayName("Builder should allow overriding groupBySubject") void builder_shouldAllowOverridingGroupBySubject() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .groupBySubject(false) .build(); assertFalse(config.groupBySubject(), "groupBySubject should be overridden to false"); @@ -191,7 +194,7 @@ void builder_shouldAllowOverridingGroupBySubject() { @Test @DisplayName("Builder should allow overriding sortSubjects") void builder_shouldAllowOverridingSortSubjects() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .sortSubjects(true) .build(); assertTrue(config.sortSubjects(), "sortSubjects should be overridden to true"); @@ -200,7 +203,7 @@ void builder_shouldAllowOverridingSortSubjects() { @Test @DisplayName("Builder should allow overriding sortPredicates") void builder_shouldAllowOverridingSortPredicates() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .sortPredicates(true) .build(); assertTrue(config.sortPredicates(), "sortPredicates should be overridden to true"); @@ -209,17 +212,17 @@ void builder_shouldAllowOverridingSortPredicates() { @Test @DisplayName("Builder should allow overriding strictMode") void builder_shouldAllowOverridingStrictMode() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .strictMode(false) .build(); - assertFalse(config.strictMode, "strictMode should be overridden to false"); + assertFalse(config.isStrictMode(), "strictMode should be overridden to false"); } @Test @DisplayName("Builder should allow overriding literalDatatypePolicy") void builder_shouldAllowOverridingLiteralDatatypePolicy() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.ALWAYS_TYPED) .build(); assertEquals(LiteralDatatypePolicyEnum.ALWAYS_TYPED, config.getLiteralDatatypePolicy(), "literalDatatypePolicy should be overridden to ALWAYS_TYPED"); @@ -229,7 +232,7 @@ void builder_shouldAllowOverridingLiteralDatatypePolicy() { @DisplayName("Builder should allow setting baseIRI") void builder_shouldAllowSettingBaseIRI() { String testBaseIRI = "http://example.org/base/"; - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .baseIRI(testBaseIRI) .build(); assertEquals(testBaseIRI, config.getBaseIRI(), "baseIRI should be set correctly"); @@ -239,7 +242,7 @@ void builder_shouldAllowSettingBaseIRI() { @DisplayName("Builder should allow overriding lineEnding") void builder_shouldAllowOverridingLineEnding() { String customLineEnding = "\r\n"; - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .lineEnding(customLineEnding) .build(); assertEquals(customLineEnding, config.getLineEnding(), "lineEnding should be overridden to custom value"); @@ -248,7 +251,7 @@ void builder_shouldAllowOverridingLineEnding() { @Test @DisplayName("Builder should allow overriding validateURIs") void builder_shouldAllowOverridingValidateURIs() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .validateURIs(true) .build(); assertTrue(config.validateURIs(), "validateURIs should be overridden to true"); @@ -257,7 +260,7 @@ void builder_shouldAllowOverridingValidateURIs() { @Test @DisplayName("Builder should allow overriding stableBlankNodeIds") void builder_shouldAllowOverridingStableBlankNodeIds() { - TriGConfig config = TriGConfig.builder() + TriGOption config = TriGOption.builder() .stableBlankNodeIds(true) .build(); assertTrue(config.stableBlankNodeIds(), "stableBlankNodeIds should be overridden to true"); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializerTest.java similarity index 96% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializerTest.java index cda7322cc..dd28ae083 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TriGSerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/trig/TriGSerializerTest.java @@ -1,12 +1,12 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.trig; import fr.inria.corese.core.next.api.IRI; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Statement; import fr.inria.corese.core.next.impl.common.literal.RDF; -import fr.inria.corese.core.next.impl.common.serialization.config.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.TriGConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,13 +27,13 @@ class TriGSerializerTest { private Model mockModel; - private TriGConfig defaultConfig; + private TriGOption defaultConfig; private TestStatementFactory factory; @BeforeEach void setUp() { mockModel = mock(Model.class); - defaultConfig = TriGConfig.defaultConfig(); + defaultConfig = TriGOption.defaultConfig(); factory = new TestStatementFactory(); } @@ -155,7 +155,7 @@ void testLiteralWithLanguageTag() throws SerializationException, IOException { StringWriter writer = new StringWriter(); - TriGConfig customConfig = new TriGConfig.Builder() + TriGOption customConfig = new TriGOption.Builder() .strictMode(false) .build(); TriGSerializer triGSerializer = new TriGSerializer(mockModel, customConfig); @@ -205,7 +205,7 @@ void testLiteralWithExplicitXsdStringType() throws SerializationException, IOExc StringWriter writer = new StringWriter(); - TriGConfig customConfig = new TriGConfig.Builder() + TriGOption customConfig = new TriGOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.ALWAYS_TYPED) .build(); TriGSerializer triGSerializer = new TriGSerializer(mockModel, customConfig); @@ -255,7 +255,7 @@ void testBaseIRI() throws SerializationException, IOException { StringWriter writer = new StringWriter(); - TriGConfig configWithBase = new TriGConfig.Builder() + TriGOption configWithBase = new TriGOption.Builder() .baseIRI("http://example.org/base/") .build(); TriGSerializer triGSerializer = new TriGSerializer(mockModel, configWithBase); @@ -338,7 +338,7 @@ void testStrictModeInvalidLiteral() throws SerializationException { StringWriter writer = new StringWriter(); - TriGConfig strictConfig = new TriGConfig.Builder().strictMode(true).build(); + TriGOption strictConfig = new TriGOption.Builder().strictMode(true).build(); TriGSerializer triGSerializer = new TriGSerializer(mockModel, strictConfig); @@ -374,7 +374,7 @@ void testStrictModeInvalidIRICharacters() throws SerializationException { StringWriter writer = new StringWriter(); - TriGConfig strictConfig = new TriGConfig.Builder().strictMode(true).validateURIs(true).build(); + TriGOption strictConfig = new TriGOption.Builder().strictMode(true).validateURIs(true).build(); TriGSerializer triGSerializer = new TriGSerializer(mockModel, strictConfig); @@ -411,7 +411,7 @@ void testMultilineLiteralSerialization() throws SerializationException, IOExcept .thenReturn(Stream.of(mockStatement)); StringWriter writer = new StringWriter(); - TriGConfig customConfig = new TriGConfig.Builder() + TriGOption customConfig = new TriGOption.Builder() .useMultilineLiterals(true) .prettyPrint(true) .build(); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOptionTest.java similarity index 84% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOptionTest.java index 482d9718c..f1443fe8b 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleOptionTest.java @@ -1,6 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization.config; +package fr.inria.corese.core.next.impl.io.serialization.turtle; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.option.BlankNodeStyleEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,16 +13,16 @@ import static org.junit.jupiter.api.Assertions.*; /** - * Unit tests for the {@link TurtleConfig} class. + * Unit tests for the {@link TurtleOption} class. * These tests verify the default configuration settings and the functionality * of the builder pattern for customizing Turtle serialization options. */ -class TurtleConfigTest { +class TurtleOptionTest { @Test @DisplayName("defaultConfig() should return a config with expected Turtle defaults") void defaultConfig_shouldReturnExpectedDefaults() { - TurtleConfig config = TurtleConfig.defaultConfig(); + TurtleOption config = TurtleOption.defaultConfig(); assertNotNull(config, "Default config should not be null"); @@ -46,7 +49,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { assertEquals(80, config.getMaxLineLength(), "Default maxLineLength should be 80"); assertTrue(config.groupBySubject(), "Default groupBySubject should be true"); - assertTrue(config.strictMode, "Default strictMode should be true"); + assertTrue(config.isStrictMode(), "Default strictMode should be true"); assertFalse(config.escapeUnicode(), "Default escapeUnicode should be false"); assertEquals(LiteralDatatypePolicyEnum.MINIMAL, config.getLiteralDatatypePolicy(), "Default literalDatatypePolicy should be MINIMAL"); assertNull(config.getBaseIRI(), "Default baseIRI should be null"); @@ -58,7 +61,7 @@ void defaultConfig_shouldReturnExpectedDefaults() { @Test @DisplayName("Builder should allow overriding useCollections") void builder_shouldAllowOverridingUseCollections() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .useCollections(false) .build(); assertFalse(config.useCollections(), "useCollections should be overridden to false"); @@ -67,7 +70,7 @@ void builder_shouldAllowOverridingUseCollections() { @Test @DisplayName("Builder should allow overriding blankNodeStyle") void builder_shouldAllowOverridingBlankNodeStyle() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .blankNodeStyle(BlankNodeStyleEnum.NAMED) .build(); assertEquals(BlankNodeStyleEnum.NAMED, config.getBlankNodeStyle(), "blankNodeStyle should be overridden to NAMED"); @@ -78,7 +81,7 @@ void builder_shouldAllowOverridingBlankNodeStyle() { void builder_shouldAllowAddingCustomPrefixes() { String customPrefix = "my"; String customNamespace = "http://my.example.org/"; - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .addCustomPrefix(customPrefix, customNamespace) .build(); @@ -91,7 +94,7 @@ void builder_shouldAllowAddingCustomPrefixes() { @Test @DisplayName("Builder should allow overriding usePrefixes") void builder_shouldAllowOverridingUsePrefixes() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .usePrefixes(false) .build(); assertFalse(config.usePrefixes(), "usePrefixes should be overridden to false"); @@ -100,7 +103,7 @@ void builder_shouldAllowOverridingUsePrefixes() { @Test @DisplayName("Builder should allow overriding autoDeclarePrefixes") void builder_shouldAllowOverridingAutoDeclarePrefixes() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .autoDeclarePrefixes(false) .build(); assertFalse(config.autoDeclarePrefixes(), "autoDeclarePrefixes should be overridden to false"); @@ -109,7 +112,7 @@ void builder_shouldAllowOverridingAutoDeclarePrefixes() { @Test @DisplayName("Builder should allow overriding prefixOrdering") void builder_shouldAllowOverridingPrefixOrdering() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .prefixOrdering(PrefixOrderingEnum.USAGE_ORDER) .build(); assertEquals(PrefixOrderingEnum.USAGE_ORDER, config.getPrefixOrdering(), "prefixOrdering should be overridden to USAGE_ORDER"); @@ -118,7 +121,7 @@ void builder_shouldAllowOverridingPrefixOrdering() { @Test @DisplayName("Builder should allow overriding useCompactTriples") void builder_shouldAllowOverridingUseCompactTriples() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .useCompactTriples(false) .build(); assertFalse(config.useCompactTriples(), "useCompactTriples should be overridden to false"); @@ -127,7 +130,7 @@ void builder_shouldAllowOverridingUseCompactTriples() { @Test @DisplayName("Builder should allow overriding useRdfTypeShortcut") void builder_shouldAllowOverridingUseRdfTypeShortcut() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .useRdfTypeShortcut(false) .build(); assertFalse(config.useRdfTypeShortcut(), "useRdfTypeShortcut should be overridden to false"); @@ -136,7 +139,7 @@ void builder_shouldAllowOverridingUseRdfTypeShortcut() { @Test @DisplayName("Builder should allow overriding useMultilineLiterals") void builder_shouldAllowOverridingUseMultilineLiterals() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .useMultilineLiterals(false) .build(); assertFalse(config.useMultilineLiterals(), "useMultilineLiterals should be overridden to false"); @@ -145,7 +148,7 @@ void builder_shouldAllowOverridingUseMultilineLiterals() { @Test @DisplayName("Builder should allow overriding prettyPrint") void builder_shouldAllowOverridingPrettyPrint() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .prettyPrint(false) .build(); assertFalse(config.prettyPrint(), "prettyPrint should be overridden to false"); @@ -155,7 +158,7 @@ void builder_shouldAllowOverridingPrettyPrint() { @DisplayName("Builder should allow overriding indent") void builder_shouldAllowOverridingIndent() { String customIndent = "\t"; - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .indent(customIndent) .build(); assertEquals(customIndent, config.getIndent(), "indent should be overridden to custom value"); @@ -165,7 +168,7 @@ void builder_shouldAllowOverridingIndent() { @DisplayName("Builder should allow overriding maxLineLength") void builder_shouldAllowOverridingMaxLineLength() { int customLength = 120; - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .maxLineLength(customLength) .build(); assertEquals(customLength, config.getMaxLineLength(), "maxLineLength should be overridden to custom value"); @@ -174,7 +177,7 @@ void builder_shouldAllowOverridingMaxLineLength() { @Test @DisplayName("Builder should allow overriding groupBySubject") void builder_shouldAllowOverridingGroupBySubject() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .groupBySubject(false) .build(); assertFalse(config.groupBySubject(), "groupBySubject should be overridden to false"); @@ -183,7 +186,7 @@ void builder_shouldAllowOverridingGroupBySubject() { @Test @DisplayName("Builder should allow overriding sortSubjects") void builder_shouldAllowOverridingSortSubjects() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .sortSubjects(true) .build(); assertTrue(config.sortSubjects(), "sortSubjects should be overridden to true"); @@ -192,7 +195,7 @@ void builder_shouldAllowOverridingSortSubjects() { @Test @DisplayName("Builder should allow overriding sortPredicates") void builder_shouldAllowOverridingSortPredicates() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .sortPredicates(true) .build(); assertTrue(config.sortPredicates(), "sortPredicates should be overridden to true"); @@ -201,17 +204,17 @@ void builder_shouldAllowOverridingSortPredicates() { @Test @DisplayName("Builder should allow overriding strictMode") void builder_shouldAllowOverridingStrictMode() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .strictMode(false) .build(); - assertFalse(config.strictMode, "strictMode should be overridden to false"); + assertFalse(config.isStrictMode(), "strictMode should be overridden to false"); } @Test @DisplayName("Builder should allow overriding literalDatatypePolicy") void builder_shouldAllowOverridingLiteralDatatypePolicy() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.ALWAYS_TYPED) .build(); assertEquals(LiteralDatatypePolicyEnum.ALWAYS_TYPED, config.getLiteralDatatypePolicy(), "literalDatatypePolicy should be overridden to ALWAYS_TYPED"); @@ -221,7 +224,7 @@ void builder_shouldAllowOverridingLiteralDatatypePolicy() { @DisplayName("Builder should allow setting baseIRI") void builder_shouldAllowSettingBaseIRI() { String testBaseIRI = "http://example.org/base/"; - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .baseIRI(testBaseIRI) .build(); assertEquals(testBaseIRI, config.getBaseIRI(), "baseIRI should be set correctly"); @@ -231,7 +234,7 @@ void builder_shouldAllowSettingBaseIRI() { @DisplayName("Builder should allow overriding lineEnding") void builder_shouldAllowOverridingLineEnding() { String customLineEnding = "\r\n"; - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .lineEnding(customLineEnding) .build(); assertEquals(customLineEnding, config.getLineEnding(), "lineEnding should be overridden to custom value"); @@ -240,7 +243,7 @@ void builder_shouldAllowOverridingLineEnding() { @Test @DisplayName("Builder should allow overriding validateURIs") void builder_shouldAllowOverridingValidateURIs() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .validateURIs(true) .build(); assertTrue(config.validateURIs(), "validateURIs should be overridden to true"); @@ -249,7 +252,7 @@ void builder_shouldAllowOverridingValidateURIs() { @Test @DisplayName("Builder should allow overriding stableBlankNodeIds") void builder_shouldAllowOverridingStableBlankNodeIds() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .stableBlankNodeIds(true) .build(); assertTrue(config.stableBlankNodeIds(), "stableBlankNodeIds should be overridden to true"); @@ -258,7 +261,7 @@ void builder_shouldAllowOverridingStableBlankNodeIds() { @Test @DisplayName("Builder should allow overriding includeContext") void builder_shouldAllowOverridingIncludeContext() { - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .includeContext(true) .build(); assertTrue(config.includeContext(), "includeContext should be overridden to true"); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializerTest.java similarity index 96% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializerTest.java index 053e111ef..f76700962 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/turtle/TurtleSerializerTest.java @@ -1,12 +1,12 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization.turtle; import fr.inria.corese.core.next.api.IRI; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.Statement; import fr.inria.corese.core.next.impl.common.literal.RDF; -import fr.inria.corese.core.next.impl.common.serialization.config.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.common.serialization.config.TurtleConfig; -import fr.inria.corese.core.next.impl.common.serialization.util.SerializationConstants; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -29,13 +29,13 @@ class TurtleSerializerTest { private Model mockModel; - private TurtleConfig defaultConfig; + private TurtleOption defaultConfig; private TestStatementFactory factory; @BeforeEach void setUp() { mockModel = mock(Model.class); - defaultConfig = TurtleConfig.defaultConfig(); + defaultConfig = TurtleOption.defaultConfig(); factory = new TestStatementFactory(); } @@ -152,7 +152,7 @@ void testLiteralWithLanguageTag() throws SerializationException, IOException { StringWriter writer = new StringWriter(); - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.MINIMAL) .useRdfTypeShortcut(true) .useCollections(true) @@ -213,7 +213,7 @@ void testLiteralWithExplicitXsdStringType() throws SerializationException, IOExc StringWriter writer = new StringWriter(); - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .literalDatatypePolicy(LiteralDatatypePolicyEnum.ALWAYS_TYPED) .usePrefixes(true) .autoDeclarePrefixes(true) @@ -314,7 +314,7 @@ void testBaseIRI() throws SerializationException, IOException { StringWriter writer = new StringWriter(); - TurtleConfig configWithBase = new TurtleConfig.Builder() + TurtleOption configWithBase = new TurtleOption.Builder() .baseIRI("http://example.org/base/") .usePrefixes(true) .autoDeclarePrefixes(true) @@ -398,7 +398,7 @@ void testStrictModeInvalidLiteral() throws SerializationException { StringWriter writer = new StringWriter(); - TurtleConfig strictConfig = new TurtleConfig.Builder().strictMode(true).build(); + TurtleOption strictConfig = new TurtleOption.Builder().strictMode(true).build(); TurtleSerializer turtleSerializer = new TurtleSerializer(mockModel, strictConfig); @@ -434,7 +434,7 @@ void testStrictModeInvalidIRICharacters() throws SerializationException { StringWriter writer = new StringWriter(); - TurtleConfig strictConfig = new TurtleConfig.Builder().strictMode(true).validateURIs(true).build(); + TurtleOption strictConfig = new TurtleOption.Builder().strictMode(true).validateURIs(true).build(); TurtleSerializer turtleSerializer = new TurtleSerializer(mockModel, strictConfig); @@ -470,7 +470,7 @@ void testMultilineLiteralSerialization() throws SerializationException, IOExcept .thenReturn(Stream.of(mockStatement)); StringWriter writer = new StringWriter(); - TurtleConfig config = new TurtleConfig.Builder() + TurtleOption config = new TurtleOption.Builder() .useMultilineLiterals(true) .prettyPrint(true) .autoDeclarePrefixes(true) diff --git a/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypeTest.java b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypedTest.java similarity index 98% rename from src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypeTest.java rename to src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypedTest.java index 24dba5a3a..f2fc2d23f 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypeTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/temp/literal/CoreseTypedTest.java @@ -7,14 +7,13 @@ import fr.inria.corese.core.next.api.literal.CoreDatatype; import fr.inria.corese.core.next.impl.temp.CoreseIRI; import fr.inria.corese.core.sparql.api.IDatatype; -import fr.inria.corese.core.sparql.datatype.CoreseLiteral; import fr.inria.corese.core.sparql.datatype.CoreseString; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; -public class CoreseTypeTest { +public class CoreseTypedTest { private String testValue; private IRI testDatatypeIRI; private CoreDatatype testCoreDatatype; diff --git a/src/test/java/fr/inria/corese/core/shex/TestShex.java b/src/test/java/fr/inria/corese/core/shex/TestShex.java deleted file mode 100644 index e69de29bb..000000000