From 154f0cb0736dae2078d2cc992546f764821284dd Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 4 Jun 2025 17:02:52 +0200 Subject: [PATCH 01/31] RDF formats --- .../core/next/api/base/parser/RDFFormat.java | 114 ++++++++ .../core/next/api/base/parser/RDFFormats.java | 255 ++++++++++++++++++ .../core/next/api/base/parser/RDFParser.java | 9 + .../api/base/parser/RDFParserFactory.java | 6 + .../impl/exception/ParsingErrorException.java | 18 ++ 5 files changed, 402 insertions(+) create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java 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 new file mode 100644 index 000000000..4f44df5c5 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java @@ -0,0 +1,114 @@ +package main.java.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 new file mode 100644 index 000000000..3895d6d00 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java @@ -0,0 +1,255 @@ +package main.java.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); + + public static final boolean DEFAULT_SUPPORTS_NAMESPACES = true; + public static final boolean DEFAULT_SUPPORTS_CONTEXTS = true; + public 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/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java new file mode 100644 index 000000000..f619b1430 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java @@ -0,0 +1,9 @@ +package main.java.fr.inria.corese.core.next.api.base.parser; + +public interface RDFParser { + + /** + * Gets the RDF format that this parser can parse. + */ + RDFFormat getRDFFormat(); +} 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 new file mode 100644 index 000000000..52baf8603 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java @@ -0,0 +1,6 @@ +package main.java.fr.inria.corese.core.next.api.base.parser; + +public interface RDFParserFactory { + + +} 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 new file mode 100644 index 000000000..786a062bd --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/exception/ParsingErrorException.java @@ -0,0 +1,18 @@ +package main.java.fr.inria.corese.core.next.impl.exception; + +public class ParsingErrorException extends RuntimeException { + + private static final long serialVersionUID = -2053549958572141648L; + + public ParsingErrorException(String message) { + super(message); + } + + public ParsingErrorException(String message, Throwable cause) { + super(message, cause); + } + + public ParsingErrorException(Throwable cause) { + super(cause); + } +} From 9dcbfd1536d3212611c97a89f8d9edef3b69ed51 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 5 Jun 2025 11:31:16 +0200 Subject: [PATCH 02/31] Barebone RDFParser Factory --- .../core/next/api/base/parser/RDFFormat.java | 2 +- .../core/next/api/base/parser/RDFFormats.java | 8 ++++---- .../core/next/api/base/parser/RDFParser.java | 2 +- .../api/base/parser/RDFParserFactory.java | 12 +++++++++++- .../impl/exception/ParsingErrorException.java | 2 +- .../UnsupportedFileFormatException.java | 19 +++++++++++++++++++ 6 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java 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 index 4f44df5c5..379fba182 100644 --- 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 @@ -1,4 +1,4 @@ -package main.java.fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.base.parser; import java.nio.charset.Charset; import java.util.*; 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 index 3895d6d00..d8d99d8b0 100644 --- 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 @@ -1,4 +1,4 @@ -package main.java.fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.base.parser; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -50,9 +50,9 @@ public enum RDFFormats implements RDFFormat { true, false); - public static final boolean DEFAULT_SUPPORTS_NAMESPACES = true; - public static final boolean DEFAULT_SUPPORTS_CONTEXTS = true; - public static final boolean DEFAULT_SUPPORTS_RDF_STAR = 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. 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/base/parser/RDFParser.java index f619b1430..301ed6211 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/base/parser/RDFParser.java @@ -1,4 +1,4 @@ -package main.java.fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.base.parser; public interface RDFParser { 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 index 52baf8603..950de673e 100644 --- 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 @@ -1,6 +1,16 @@ -package main.java.fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.base.parser; + +import fr.inria.corese.core.next.api.Model; 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); } 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 786a062bd..cc6bf4eee 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,4 +1,4 @@ -package main.java.fr.inria.corese.core.next.impl.exception; +package fr.inria.corese.core.next.impl.exception; public class ParsingErrorException extends RuntimeException { 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 new file mode 100644 index 000000000..b44687d51 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java @@ -0,0 +1,19 @@ +package fr.inria.corese.core.next.impl.exception; + +public class UnsupportedFileFormatException extends Exception { + + private static final long serialVersionUID = 7963163989802143570L; + + public UnsupportedFileFormatException(String message) { + super(message); + } + + public UnsupportedFileFormatException(String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedFileFormatException(Throwable cause) { + super(cause); + } + +} From 81ceb4bc2da1b3dd1f939ebfc904f64a077a754d Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 5 Jun 2025 11:40:16 +0200 Subject: [PATCH 03/31] barebone parser interface --- .../core/next/api/base/parser/RDFParser.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) 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/base/parser/RDFParser.java index 301ed6211..cf8da275c 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/base/parser/RDFParser.java @@ -1,9 +1,42 @@ package fr.inria.corese.core.next.api.base.parser; +import java.io.InputStream; +import java.io.Reader; + public interface RDFParser { /** * Gets the RDF format that this parser can parse. */ RDFFormat getRDFFormat(); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param in The InputStream to read RDF data from. + */ + void parse(InputStream in); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param in The InputStream to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + */ + void parse(InputStream in, String baseURI); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param reader The Reader to read RDF data from. + */ + void parse(Reader reader); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param reader The Reader to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + */ + void parse(Reader reader, String baseURI); } From 1463e4a2f00cffc7e7f2128dfcb265ffca13dda3 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 5 Jun 2025 11:40:16 +0200 Subject: [PATCH 04/31] barebone parser interface --- .../core/next/api/base/parser/RDFParser.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) 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/base/parser/RDFParser.java index 301ed6211..cf8da275c 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/base/parser/RDFParser.java @@ -1,9 +1,42 @@ package fr.inria.corese.core.next.api.base.parser; +import java.io.InputStream; +import java.io.Reader; + public interface RDFParser { /** * Gets the RDF format that this parser can parse. */ RDFFormat getRDFFormat(); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param in The InputStream to read RDF data from. + */ + void parse(InputStream in); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param in The InputStream to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + */ + void parse(InputStream in, String baseURI); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param reader The Reader to read RDF data from. + */ + void parse(Reader reader); + + /** + * Parses RDF data from the specified InputStream or Reader and adds it to the model. + * + * @param reader The Reader to read RDF data from. + * @param baseURI The base URI for resolving relative URIs in the RDF data. + */ + void parse(Reader reader, String baseURI); } From 94010422cf28b838cac3e92cb432416496dd0635 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 11 Jun 2025 17:36:35 +0200 Subject: [PATCH 05/31] First draft with consumer implementation --- build.gradle.kts | 6 +- .../next/api/{base => }/parser/RDFFormat.java | 2 +- .../api/{base => }/parser/RDFFormats.java | 2 +- .../next/api/{base => }/parser/RDFParser.java | 2 +- .../{base => }/parser/RDFParserFactory.java | 5 +- .../parser/jsonld/FromJsonLDConsumer.java | 55 +++++++++++++++ .../next/impl/parser/jsonld/JSONLDParser.java | 70 +++++++++++++++++++ .../parser/jsonld/JSONLDParserFactory.java | 18 +++++ src/main/java/module-info.java | 2 + 9 files changed, 155 insertions(+), 7 deletions(-) rename src/main/java/fr/inria/corese/core/next/api/{base => }/parser/RDFFormat.java (98%) rename src/main/java/fr/inria/corese/core/next/api/{base => }/parser/RDFFormats.java (99%) rename src/main/java/fr/inria/corese/core/next/api/{base => }/parser/RDFParser.java (95%) rename src/main/java/fr/inria/corese/core/next/api/{base => }/parser/RDFParserFactory.java (68%) create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java diff --git a/build.gradle.kts b/build.gradle.kts index f7959310b..3a5856a56 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -112,7 +112,7 @@ dependencies { implementation("fr.com.hp.hpl.jena.rdf.arp:arp:2.2.b") // Exposed: RDF/XML parser implementation("org.apache.commons:commons-text:1.10.0") // Used internally (text manipulation) implementation("commons-lang:commons-lang:2.4") // Used internally (basic utilities) - implementation("org.json:json:20240303") // Used internally (JSON) + implementation("org.json:json:20250517") // Used internally (JSON) implementation("fr.inria.lille.shexjava:shexjava-core:1.0") // Used internally (ShEx validation) implementation("org.glassfish.jersey.core:jersey-client:$jersey_version") // Internal HTTP client implementation("org.glassfish.jersey.inject:jersey-hk2:$jersey_version") // Internal Jersey injection @@ -120,8 +120,10 @@ dependencies { implementation("javax.xml.bind:jaxb-api:2.3.1") // Internal XML binding implementation("fr.inria.corese.org.semarglproject:semargl-rdfa:$semargl_version") // RDFa parsing implementation("fr.inria.corese.org.semarglproject:semargl-core:$semargl_version") // RDF core parser - implementation("com.github.jsonld-java:jsonld-java:0.13.4") // Internal JSON-LD parser + implementation("com.github.jsonld-java:jsonld-java:0.13.4") // Legacy internal JSON-LD parser implementation("com.typesafe:config:1.4.3") // Typesafe config + implementation("com.apicatalog:titanium-json-ld:1.6.0") // JSON-LD 1.1 parser + implementation("com.apicatalog:titanium-rdf-api:1.0.0") // RDF API for the JSON-LD parser // === For tests === testImplementation(platform("org.junit:junit-bom:5.12.2")) // JUnit 5 BOM for dependency management 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/parser/RDFFormat.java similarity index 98% rename from src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java rename to src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java index 379fba182..ad7988ad7 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java +++ b/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.parser; import java.nio.charset.Charset; import java.util.*; 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/parser/RDFFormats.java similarity index 99% rename from src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java rename to src/main/java/fr/inria/corese/core/next/api/parser/RDFFormats.java index d8d99d8b0..f073fa898 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java +++ b/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormats.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.parser; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; 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/parser/RDFParser.java similarity index 95% 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/parser/RDFParser.java index cf8da275c..2977bf158 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/parser/RDFParser.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.parser; import java.io.InputStream; import java.io.Reader; 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/parser/RDFParserFactory.java similarity index 68% rename from src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java rename to src/main/java/fr/inria/corese/core/next/api/parser/RDFParserFactory.java index 950de673e..68f7c16c1 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/api/parser/RDFParserFactory.java @@ -1,6 +1,7 @@ -package fr.inria.corese.core.next.api.base.parser; +package fr.inria.corese.core.next.api.parser; import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; public interface RDFParserFactory { @@ -11,6 +12,6 @@ public interface RDFParserFactory { * @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); + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java new file mode 100644 index 000000000..e9ac7f3a4 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java @@ -0,0 +1,55 @@ +package fr.inria.corese.core.next.impl.parser.jsonld; + +import com.apicatalog.rdf.api.RdfConsumerException; +import com.apicatalog.rdf.api.RdfQuadConsumer; +import fr.inria.corese.core.next.api.*; + +public class FromJsonLDConsumer implements RdfQuadConsumer { + + private Model model; + private final ValueFactory valueFactory; + + FromJsonLDConsumer(Model model, ValueFactory valueFactory) { + this.model = model; + this.valueFactory = valueFactory; + } + + @Override + public RdfQuadConsumer quad(String subject, String predicate, String object, String datatype, String language, String direction, String graph) throws RdfConsumerException { + if(subject != null || predicate != null || object != null) { + // Subject + Resource subjectRes = null; + if(RdfQuadConsumer.isBlank(subject)) { + subjectRes = valueFactory.createBNode(subject); + } else { + subjectRes = valueFactory.createIRI(subject); + } + + // Property + IRI propertyRes = valueFactory.createIRI(predicate); + + // Object + Value objectRes = null; + if(RdfQuadConsumer.isValidObject(datatype, language, direction)) { + if(RdfQuadConsumer.isLiteral( datatype, language, direction)) { + if(language != null) { + objectRes = valueFactory.createLiteral(object, language); + } else { + if (datatype != null) { + IRI datatypeIRI = this.valueFactory.createIRI(datatype); + objectRes = valueFactory.createLiteral(object, datatypeIRI); + } else { + objectRes = valueFactory.createLiteral(object); + } + } + } else if(RdfQuadConsumer.isBlank(object)) { + objectRes = valueFactory.createBNode(object); + } else { + objectRes = valueFactory.createIRI(object); + } + } + this.model.add(subjectRes, propertyRes, objectRes); + } + return this; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java new file mode 100644 index 000000000..321935e9a --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java @@ -0,0 +1,70 @@ +package fr.inria.corese.core.next.impl.parser.jsonld; + +import com.apicatalog.jsonld.JsonLd; +import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.document.JsonDocument; +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.parser.RDFFormat; +import fr.inria.corese.core.next.api.parser.RDFFormats; +import fr.inria.corese.core.next.api.parser.RDFParser; +import fr.inria.corese.core.next.impl.exception.ParsingErrorException; + +import java.io.InputStream; +import java.io.Reader; + +public class JSONLDParser implements RDFParser { + + private Model model; + private final ValueFactory valueFactory; + + public JSONLDParser(Model model, ValueFactory factory) { + this.model = model; + this.valueFactory = factory; + } + + @Override + public RDFFormat getRDFFormat() { + return RDFFormats.JSON_LD; + } + + @Override + public void parse(InputStream in) throws ParsingErrorException { + try { + JsonDocument document = JsonDocument.of(in); + JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + @Override + public void parse(InputStream in, String baseURI) throws ParsingErrorException { + try { + JsonDocument document = JsonDocument.of(in); + JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + @Override + public void parse(Reader reader) throws ParsingErrorException { + try { + JsonDocument document = JsonDocument.of(reader); + JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + @Override + public void parse(Reader reader, String baseURI) { + try { + JsonDocument document = JsonDocument.of(reader); + JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java new file mode 100644 index 000000000..94235d0af --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java @@ -0,0 +1,18 @@ +package fr.inria.corese.core.next.impl.parser.jsonld; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.ValueFactory; +import fr.inria.corese.core.next.api.parser.RDFFormat; +import fr.inria.corese.core.next.api.parser.RDFFormats; +import fr.inria.corese.core.next.api.parser.RDFParser; +import fr.inria.corese.core.next.api.parser.RDFParserFactory; + +public class JSONLDParserFactory implements RDFParserFactory { + @Override + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { + if(format == RDFFormats.JSON_LD) { + return new JSONLDParser(model, factory); + } + return null; + } +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index da52e9920..08a7b5d29 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -13,6 +13,8 @@ requires org.json; // requires org.apache.commons.lang3; requires org.slf4j; + requires titanium.json.ld; requires fr.inria.corese.corese_core; + requires titanium.rdf.api; exports fr.inria.corese.core.load; exports fr.inria.corese.core.load.result; From c0cb9c088fe184f93c671b9405acc74b024c7f6f Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 12 Jun 2025 17:13:12 +0200 Subject: [PATCH 06/31] Json parser redone ffrom scratch using Jsonld-java --- build.gradle.kts | 10 +-- .../parser/jsonld/FromJsonLDConsumer.java | 55 ------------- .../next/impl/parser/jsonld/JSONLDParser.java | 80 ++++++++++++------- .../parser/jsonld/JSONLDParserFactory.java | 11 +++ src/main/java/module-info.java | 4 +- .../impl/parser/jsonld/JSONLDParserTest.java | 54 +++++++++++++ 6 files changed, 124 insertions(+), 90 deletions(-) delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 130a53d70..0735f6033 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -117,11 +117,8 @@ dependencies { implementation("fr.inria.lille.shexjava:shexjava-core:1.0") // ShEx validation engine implementation("fr.inria.corese.org.semarglproject:semargl-rdfa:$semargl_version") // RDFa parser (Semargl) implementation("fr.inria.corese.org.semarglproject:semargl-core:$semargl_version") // Semargl core RDF parser - implementation("com.github.jsonld-java:jsonld-java:0.13.4") // JSON-LD processing - - // === JSON-LD === - implementation("com.apicatalog:titanium-json-ld:1.6.0") // JSON-LD 1.1 parser - implementation("com.apicatalog:titanium-rdf-api:1.0.0") // RDF API for the JSON-LD parser + implementation("com.github.jsonld-java:jsonld-java:0.13.6") // Legacy JSON-LD processing + // === HTTP and XML === implementation("org.glassfish.jersey.core:jersey-client:$jersey_version") // HTTP client (Jersey) @@ -154,6 +151,9 @@ extraJavaModuleInfo { automaticModule("commons-lang:commons-lang", "commons.lang") // Module for Commons Lang automaticModule("fr.inria.lille.shexjava:shexjava-core", "shexjava.core") // Module for ShexJava core automaticModule("org.eclipse.rdf4j:rdf4j-model", "rdf4j.model") // Module for RDF4J model + automaticModule("com.apicatalog:titanium-json-ld", "titanium.json.ld") // Module for Titanium JSON-LD + automaticModule("com.apicatalog:titanium-rdf-api", "titanium.rdf.api") // Module for Titanium RDF API + } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java deleted file mode 100644 index e9ac7f3a4..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/FromJsonLDConsumer.java +++ /dev/null @@ -1,55 +0,0 @@ -package fr.inria.corese.core.next.impl.parser.jsonld; - -import com.apicatalog.rdf.api.RdfConsumerException; -import com.apicatalog.rdf.api.RdfQuadConsumer; -import fr.inria.corese.core.next.api.*; - -public class FromJsonLDConsumer implements RdfQuadConsumer { - - private Model model; - private final ValueFactory valueFactory; - - FromJsonLDConsumer(Model model, ValueFactory valueFactory) { - this.model = model; - this.valueFactory = valueFactory; - } - - @Override - public RdfQuadConsumer quad(String subject, String predicate, String object, String datatype, String language, String direction, String graph) throws RdfConsumerException { - if(subject != null || predicate != null || object != null) { - // Subject - Resource subjectRes = null; - if(RdfQuadConsumer.isBlank(subject)) { - subjectRes = valueFactory.createBNode(subject); - } else { - subjectRes = valueFactory.createIRI(subject); - } - - // Property - IRI propertyRes = valueFactory.createIRI(predicate); - - // Object - Value objectRes = null; - if(RdfQuadConsumer.isValidObject(datatype, language, direction)) { - if(RdfQuadConsumer.isLiteral( datatype, language, direction)) { - if(language != null) { - objectRes = valueFactory.createLiteral(object, language); - } else { - if (datatype != null) { - IRI datatypeIRI = this.valueFactory.createIRI(datatype); - objectRes = valueFactory.createLiteral(object, datatypeIRI); - } else { - objectRes = valueFactory.createLiteral(object); - } - } - } else if(RdfQuadConsumer.isBlank(object)) { - objectRes = valueFactory.createBNode(object); - } else { - objectRes = valueFactory.createIRI(object); - } - } - this.model.add(subjectRes, propertyRes, objectRes); - } - return this; - } -} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java index 321935e9a..c8a7efb2d 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java @@ -1,26 +1,34 @@ package fr.inria.corese.core.next.impl.parser.jsonld; -import com.apicatalog.jsonld.JsonLd; -import com.apicatalog.jsonld.JsonLdError; -import com.apicatalog.jsonld.document.JsonDocument; -import fr.inria.corese.core.next.api.Model; -import fr.inria.corese.core.next.api.ValueFactory; +import com.github.jsonldjava.core.JsonLdError; +import com.github.jsonldjava.core.JsonLdOptions; +import com.github.jsonldjava.core.JsonLdProcessor; +import com.github.jsonldjava.core.RDFDataset; +import com.github.jsonldjava.utils.JsonUtils; +import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.api.parser.RDFFormat; import fr.inria.corese.core.next.api.parser.RDFFormats; import fr.inria.corese.core.next.api.parser.RDFParser; import fr.inria.corese.core.next.impl.exception.ParsingErrorException; +import java.io.IOException; import java.io.InputStream; import java.io.Reader; public class JSONLDParser implements RDFParser { - private Model model; + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JSONLDParser.class); + + private static final String jsonldjavadefaultGraphName = "@default"; + + private final Model model; private final ValueFactory valueFactory; + private JsonLdOptions commonOptions = new JsonLdOptions(); public JSONLDParser(Model model, ValueFactory factory) { this.model = model; this.valueFactory = factory; + commonOptions.setCompactArrays(true); } @Override @@ -31,40 +39,56 @@ public RDFFormat getRDFFormat() { @Override public void parse(InputStream in) throws ParsingErrorException { try { - JsonDocument document = JsonDocument.of(in); - JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); - } catch (JsonLdError e) { - throw new ParsingErrorException(e); + Object input = JsonUtils.fromInputStream(in); + RDFDataset output = (RDFDataset)JsonLdProcessor.toRDF(input, this.commonOptions); + logger.debug("JSON-LD output: {}", output); + for(String gName: output.graphNames()) { + logger.debug("Graph name: {}", gName); + for(RDFDataset.Quad q : output.getQuads(gName)) { + logger.debug("Quad: {}", q); + Resource subject = null; + if (q.getSubject().isIRI()) { + subject = valueFactory.createIRI(q.getSubject().getValue()); + } else { + subject = valueFactory.createBNode(q.getSubject().getValue()); + } + + IRI predicate = valueFactory.createIRI(q.getPredicate().getValue()); + + Value object = null; + if (q.getObject().isIRI()) { + object = valueFactory.createIRI(q.getObject().getValue()); + } else if (q.getObject().isBlankNode()) { + object = valueFactory.createBNode(q.getObject().getValue()); + } else { + object = valueFactory.createLiteral(q.getObject().getValue()); + } + + if(gName.equals("@default")) { + model.add(subject, predicate, object); + } else { + IRI graph = valueFactory.createIRI(gName); + model.add(subject, predicate, object, graph); + } + } + } + } catch (IOException | JsonLdError e) { + throw new ParsingErrorException(e); } } @Override public void parse(InputStream in, String baseURI) throws ParsingErrorException { - try { - JsonDocument document = JsonDocument.of(in); - JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); - } catch (JsonLdError e) { - throw new ParsingErrorException(e); - } + } @Override public void parse(Reader reader) throws ParsingErrorException { - try { - JsonDocument document = JsonDocument.of(reader); - JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); - } catch (JsonLdError e) { - throw new ParsingErrorException(e); - } + } @Override public void parse(Reader reader, String baseURI) { - try { - JsonDocument document = JsonDocument.of(reader); - JsonLd.toRdf(document).provide(new FromJsonLDConsumer(this.model, this.valueFactory)); - } catch (JsonLdError e) { - throw new ParsingErrorException(e); - } + } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java index 94235d0af..d7eeae5b8 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java @@ -8,6 +8,17 @@ import fr.inria.corese.core.next.api.parser.RDFParserFactory; public class JSONLDParserFactory implements RDFParserFactory { + + private static final JSONLDParserFactory INSTANCE = new JSONLDParserFactory(); + + public static JSONLDParserFactory getInstance() { + return INSTANCE; + } + + private JSONLDParserFactory() { + + } + @Override public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { if(format == RDFFormats.JSON_LD) { diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 08a7b5d29..999115852 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -13,8 +13,8 @@ requires org.json; // requires org.apache.commons.lang3; requires org.slf4j; - requires titanium.json.ld; requires fr.inria.corese.corese_core; - requires titanium.rdf.api; + requires jsonld.java; + exports fr.inria.corese.core.load; exports fr.inria.corese.core.load.result; diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java new file mode 100644 index 000000000..d42b4361f --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java @@ -0,0 +1,54 @@ +package fr.inria.corese.core.next.impl.parser.jsonld; + +import fr.inria.corese.core.next.api.parser.RDFFormats; +import fr.inria.corese.core.next.api.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; + +import java.io.ByteArrayInputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class JSONLDParserTest { + @Test + void testGetRDFFormat() { + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, new CoreseModel(), new CoreseAdaptedValueFactory()); + assertEquals(RDFFormats.JSON_LD, parser.getRDFFormat()); + } + + @Test + void testParseInputStream() { + String sampleJsonLD = "{\n" + + " \"@context\": {\n" + + " \"name\": \"http://xmlns.com/foaf/0.1/name\",\n" + + " \"knows\": \"http://xmlns.com/foaf/0.1/knows\"\n" + + " },\n" + + " \"@id\": \"http://me.markus-lanthaler.com/\",\n" + + " \"name\": \"Markus Lanthaler\",\n" + + " \"knows\": [\n" + + " {\n" + + " \"name\": \"Dave Longley\"\n" + + " }\n" + + " ]\n" + + "}"; + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); + + assertNotEquals(0, model.size()); + } + + @Test + void testParseInputStreamString() { + } + + @Test + void testParseReader() { + } + + @Test + void testParseReaderString() { + } +} From 72bf0b747586532516696ddb986b99ff4764f607 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Fri, 13 Jun 2025 16:07:46 +0200 Subject: [PATCH 07/31] Unit tests --- build.gradle.kts | 2 - .../next/impl/parser/jsonld/JSONLDParser.java | 80 ++++-- .../impl/parser/jsonld/JSONLDParserTest.java | 268 ++++++++++++++++-- 3 files changed, 299 insertions(+), 51 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0735f6033..033c60b50 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -151,8 +151,6 @@ extraJavaModuleInfo { automaticModule("commons-lang:commons-lang", "commons.lang") // Module for Commons Lang automaticModule("fr.inria.lille.shexjava:shexjava-core", "shexjava.core") // Module for ShexJava core automaticModule("org.eclipse.rdf4j:rdf4j-model", "rdf4j.model") // Module for RDF4J model - automaticModule("com.apicatalog:titanium-json-ld", "titanium.json.ld") // Module for Titanium JSON-LD - automaticModule("com.apicatalog:titanium-rdf-api", "titanium.rdf.api") // Module for Titanium RDF API } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java index c8a7efb2d..f8ed47bcd 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java @@ -28,7 +28,8 @@ public class JSONLDParser implements RDFParser { public JSONLDParser(Model model, ValueFactory factory) { this.model = model; this.valueFactory = factory; - commonOptions.setCompactArrays(true); + commonOptions.setCompactArrays(false); + commonOptions.setBase(null); } @Override @@ -36,59 +37,78 @@ public RDFFormat getRDFFormat() { return RDFFormats.JSON_LD; } - @Override - public void parse(InputStream in) throws ParsingErrorException { + private void parseFromJsonInput(Object input, String baseURI) { try { - Object input = JsonUtils.fromInputStream(in); + if(baseURI != null) { + commonOptions.setBase(baseURI); + } RDFDataset output = (RDFDataset)JsonLdProcessor.toRDF(input, this.commonOptions); logger.debug("JSON-LD output: {}", output); for(String gName: output.graphNames()) { logger.debug("Graph name: {}", gName); for(RDFDataset.Quad q : output.getQuads(gName)) { - logger.debug("Quad: {}", q); - Resource subject = null; - if (q.getSubject().isIRI()) { - subject = valueFactory.createIRI(q.getSubject().getValue()); - } else { - subject = valueFactory.createBNode(q.getSubject().getValue()); - } + logger.debug("Quad: {}", q); + Resource subject = null; + if (q.getSubject().isIRI()) { + subject = valueFactory.createIRI(q.getSubject().getValue()); + } else { + subject = valueFactory.createBNode(q.getSubject().getValue()); + } IRI predicate = valueFactory.createIRI(q.getPredicate().getValue()); - Value object = null; - if (q.getObject().isIRI()) { - object = valueFactory.createIRI(q.getObject().getValue()); - } else if (q.getObject().isBlankNode()) { - object = valueFactory.createBNode(q.getObject().getValue()); - } else { - object = valueFactory.createLiteral(q.getObject().getValue()); - } - - if(gName.equals("@default")) { - model.add(subject, predicate, object); - } else { - IRI graph = valueFactory.createIRI(gName); - model.add(subject, predicate, object, graph); - } + Value object = null; + if (q.getObject().isIRI()) { + object = valueFactory.createIRI(q.getObject().getValue()); + } else if (q.getObject().isBlankNode()) { + object = valueFactory.createBNode(q.getObject().getValue()); + } else { + object = valueFactory.createLiteral(q.getObject().getValue()); + } + + if(gName.equals(jsonldjavadefaultGraphName)) { + model.add(subject, predicate, object); + } else { + IRI graph = valueFactory.createIRI(gName); + model.add(subject, predicate, object, graph); + } } } - } catch (IOException | JsonLdError e) { + if(baseURI != null) { + commonOptions.setBase(null); + } + } catch (JsonLdError e) { throw new ParsingErrorException(e); } } @Override - public void parse(InputStream in, String baseURI) throws ParsingErrorException { + public void parse(InputStream in) throws ParsingErrorException { + parse(in, null); + } + @Override + public void parse(InputStream in, String baseURI) throws ParsingErrorException { + try { + Object input = JsonUtils.fromInputStream(in); + parseFromJsonInput(input, baseURI); + } catch (IOException | JsonLdError e) { + throw new ParsingErrorException(e); + } } @Override public void parse(Reader reader) throws ParsingErrorException { - + parse(reader, null); } @Override public void parse(Reader reader, String baseURI) { - + try { + Object input = JsonUtils.fromReader(reader); + parseFromJsonInput(input, baseURI); + } catch (IOException | JsonLdError e) { + throw new ParsingErrorException(e); + } } } diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java index d42b4361f..d65e744d6 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java @@ -1,5 +1,9 @@ package fr.inria.corese.core.next.impl.parser.jsonld; +import fr.inria.corese.core.next.api.BNode; +import fr.inria.corese.core.next.api.IRI; +import fr.inria.corese.core.next.api.Literal; +import fr.inria.corese.core.next.api.Statement; import fr.inria.corese.core.next.api.parser.RDFFormats; import fr.inria.corese.core.next.api.parser.RDFParser; import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; @@ -7,9 +11,10 @@ import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; +import java.io.StringReader; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class JSONLDParserTest { @Test @@ -18,37 +23,262 @@ void testGetRDFFormat() { assertEquals(RDFFormats.JSON_LD, parser.getRDFFormat()); } + /** + * Test method for {@link JSONLDParser#parse(java.io.InputStream)}. No relative IRIs in this test. + */ @Test - void testParseInputStream() { - String sampleJsonLD = "{\n" + - " \"@context\": {\n" + - " \"name\": \"http://xmlns.com/foaf/0.1/name\",\n" + - " \"knows\": \"http://xmlns.com/foaf/0.1/knows\"\n" + - " },\n" + - " \"@id\": \"http://me.markus-lanthaler.com/\",\n" + - " \"name\": \"Markus Lanthaler\",\n" + - " \"knows\": [\n" + - " {\n" + - " \"name\": \"Dave Longley\"\n" + - " }\n" + - " ]\n" + - "}"; + 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" + } + ] + } + """; CoreseModel model = new CoreseModel(); RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); - assertNotEquals(0, model.size()); + assertEquals(3, model.size()); + IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); + Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); + Statement daveNameStatement = new CoreseAdaptedValueFactory().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 - void testParseInputStreamString() { + 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" + } + ] + } + """; + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes()), "http://me.markus-lanthaler.com/"); + + assertEquals(3, model.size()); + IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); + Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); + Statement daveNameStatement = new CoreseAdaptedValueFactory().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 - void testParseReader() { + 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" + } + ] + } + """; + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new StringReader(sampleJsonLD)); + + assertEquals(3, model.size()); + IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); + Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); + Statement daveNameStatement = new CoreseAdaptedValueFactory().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 - void testParseReaderString() { + 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" + } + ] + } + """; + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new StringReader(sampleJsonLD), "http://me.markus-lanthaler.com/"); + + assertEquals(3, model.size()); + IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); + IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); + Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); + Statement daveNameStatement = new CoreseAdaptedValueFactory().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"} + } + ] + } + + """; + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new StringReader(sampleJsonLD)); + + assertEquals(2, model.size()); + BNode b0 = new CoreseAdaptedValueFactory().createBNode("b0"); + BNode b1 = new CoreseAdaptedValueFactory().createBNode("b1"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().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", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, + "Person": "http://xmlns.com/foaf/0.1/Person", + "name": "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": "2012-04-09T00:00:00", + "@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" + } + ] + } + """; + + CoreseModel model = new CoreseModel(); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + parser.parse(new StringReader(sampleJsonLD)); + + assertEquals(7, model.size()); + IRI graphIRI = new CoreseAdaptedValueFactory().createIRI("http://example.org/foaf-graph"); + IRI generatedAt = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/ns/prov#generatedAt"); + IRI datetimeDatatype = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/2001/XMLSchema#dateTime"); + Literal generatedAtValue = new CoreseAdaptedValueFactory().createLiteral("2012-04-09T00:00:00", datetimeDatatype) ; + IRI manuIRI = new CoreseAdaptedValueFactory().createIRI("http://manu.sporny.org/about#manu"); + Literal manuName = new CoreseAdaptedValueFactory().createLiteral("Manu Sporny"); + IRI greggIRI = new CoreseAdaptedValueFactory().createIRI("https://greggkellogg.net/foaf#me"); + Literal greggName = new CoreseAdaptedValueFactory().createLiteral("Gregg Kellogg"); + IRI typeIRI = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + IRI personType = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/Person"); + IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + + // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + assertTrue(model.contains(graphIRI, generatedAt, generatedAtValue)); + // { + // a foaf:Person; + assertTrue(model.contains(manuIRI, typeIRI, personType, graphIRI)); + // foaf:name "Manu Sporny"; + assertTrue(model.contains(manuIRI, namePredicate, manuName, graphIRI)); + // foaf:knows . + assertTrue(model.contains(manuIRI, knowsPredicate, greggIRI, graphIRI)); + // + // a foaf:Person; + assertTrue(model.contains(greggIRI, typeIRI, personType, graphIRI)); + // foaf:name "Gregg Kellogg"; + assertTrue(model.contains(greggIRI, namePredicate, greggName, graphIRI)); + // foaf:knows . + assertTrue(model.contains(greggIRI, knowsPredicate, manuIRI, graphIRI)); + //} } } From a33d70bbf0506110aaa67745fe49f8986d9dcb09 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 16 Jun 2025 11:27:24 +0200 Subject: [PATCH 08/31] fix literal typing during parsing --- .../next/impl/parser/jsonld/JSONLDParser.java | 15 +++++++++++---- .../impl/parser/jsonld/JSONLDParserTest.java | 16 ++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java index f8ed47bcd..e2fb6439a 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java @@ -43,11 +43,8 @@ private void parseFromJsonInput(Object input, String baseURI) { commonOptions.setBase(baseURI); } RDFDataset output = (RDFDataset)JsonLdProcessor.toRDF(input, this.commonOptions); - logger.debug("JSON-LD output: {}", output); for(String gName: output.graphNames()) { - logger.debug("Graph name: {}", gName); for(RDFDataset.Quad q : output.getQuads(gName)) { - logger.debug("Quad: {}", q); Resource subject = null; if (q.getSubject().isIRI()) { subject = valueFactory.createIRI(q.getSubject().getValue()); @@ -62,8 +59,18 @@ private void parseFromJsonInput(Object input, String baseURI) { object = valueFactory.createIRI(q.getObject().getValue()); } else if (q.getObject().isBlankNode()) { object = valueFactory.createBNode(q.getObject().getValue()); + } else if(q.getObject().isLiteral()){ + String objectDatatype = q.getObject().getDatatype(); + String objectLanguage = q.getObject().getLanguage(); + if(objectLanguage != null) { + object = valueFactory.createLiteral(q.getObject().getValue(), objectLanguage); + } else if(objectDatatype != null) { + object = valueFactory.createLiteral(q.getObject().getValue(), valueFactory.createIRI(objectDatatype)); + } else { + object = valueFactory.createLiteral(q.getObject().getValue()); + } } else { - object = valueFactory.createLiteral(q.getObject().getValue()); + throw new ParsingErrorException("Unknown object type: " + q.getObject()); } if(gName.equals(jsonldjavadefaultGraphName)) { diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java index d65e744d6..42894cc47 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class JSONLDParserTest { + @Test void testGetRDFFormat() { RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, new CoreseModel(), new CoreseAdaptedValueFactory()); @@ -220,15 +221,17 @@ public void testParseJSONLDWithGraphs() { { "@context": { "generatedAt": { - "@id": "http://www.w3.org/ns/prov#generatedAtTime", - "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + "@id": "http://www.w3.org/ns/prov#generatedAtTime" }, "Person": "http://xmlns.com/foaf/0.1/Person", "name": "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": "2012-04-09T00:00:00", + "generatedAt": { + "@value": "2012-04-09T00:00:00", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime" + }, "@graph": [ { "@id": "http://manu.sporny.org/about#manu", @@ -251,7 +254,7 @@ public void testParseJSONLDWithGraphs() { assertEquals(7, model.size()); IRI graphIRI = new CoreseAdaptedValueFactory().createIRI("http://example.org/foaf-graph"); - IRI generatedAt = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/ns/prov#generatedAt"); + IRI generatedAt = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/ns/prov#generatedAtTime"); IRI datetimeDatatype = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/2001/XMLSchema#dateTime"); Literal generatedAtValue = new CoreseAdaptedValueFactory().createLiteral("2012-04-09T00:00:00", datetimeDatatype) ; IRI manuIRI = new CoreseAdaptedValueFactory().createIRI("http://manu.sporny.org/about#manu"); @@ -263,8 +266,7 @@ public void testParseJSONLDWithGraphs() { IRI personType = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/Person"); IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); - // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . - assertTrue(model.contains(graphIRI, generatedAt, generatedAtValue)); + // { // a foaf:Person; assertTrue(model.contains(manuIRI, typeIRI, personType, graphIRI)); @@ -280,5 +282,7 @@ public void testParseJSONLDWithGraphs() { // foaf:knows . assertTrue(model.contains(greggIRI, knowsPredicate, manuIRI, graphIRI)); //} + // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + assertTrue(model.contains(graphIRI, generatedAt, generatedAtValue)); } } From 4012ee7dad39e8fdfd866d7518b9794af61cc126 Mon Sep 17 00:00:00 2001 From: pierrerene Date: Fri, 20 Jun 2025 13:43:56 +0200 Subject: [PATCH 09/31] TurtleParser and turtle g4 --- .../core/next/impl/parser/turtle/Turtle.g4 | 324 ++++++++++++++++++ .../next/impl/parser/turtle/TurtleParser.java | 46 +++ .../parser/turtle/TurtleParserFactory.java | 18 + 3 files changed, 388 insertions(+) create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 new file mode 100644 index 000000000..a51350b3e --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 @@ -0,0 +1,324 @@ +/* + [The "BSD licence"] + Copyright (c) 2014, Alejandro Medrano (@ Universidad Politecnica de Madrid, http://www.upm.es/) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +*/ +/* Derived from http://www.w3.org/TR/turtle/#sec-grammar-grammar */ + +// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false +// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging + +grammar Turtle; + +turtleDoc + : statement* EOF + ; + +statement + : directive + | triples '.' + ; + +directive + : prefixID + | base + | sparqlPrefix + | sparqlBase + ; + +triples + : subject predicateObjectList + | blankNodePropertyList predicateObjectList? + ; + +predicateObjectList + : verb objectList (';' (verb objectList)?)* + ; + +objectList + : object_ (',' object_)* + ; + +verb + : predicate + | 'a' + ; + +subject + : iri + | BlankNode + | collection + ; + +predicate + : iri + ; + +object_ + : iri + | BlankNode + | collection + | blankNodePropertyList + | literal + ; + +literal + : rdfLiteral + | numericLiteral + | BooleanLiteral + ; + +blankNodePropertyList + : '[' predicateObjectList ']' + ; + +collection + : '(' object_* ')' + ; + +prefixID + : '@prefix' PNAME_NS IRIREF '.' + ; + +base + : '@base' IRIREF '.' + ; + +sparqlBase + : Base_w IRIREF + ; + +sparqlPrefix + : Prefix_w PNAME_NS IRIREF + ; + +numericLiteral + : INTEGER + | DECIMAL + | DOUBLE + ; + +rdfLiteral + : string (LANGTAG | '^^' iri)? + ; + +BooleanLiteral + : 'true' + | 'false' + ; + +string + : STRING_LITERAL_QUOTE + | STRING_LITERAL_SINGLE_QUOTE + | STRING_LITERAL_LONG_SINGLE_QUOTE + | STRING_LITERAL_LONG_QUOTE + ; + +iri + : IRIREF + | PrefixedName + ; + +BlankNode + : BLANK_NODE_LABEL + | ANON + ; + +WS + : ([\t\r\n\u000C] | ' ')+ -> skip + ; + +// LEXER + +Base_w options { caseInsensitive=true; } + : 'BASE' + ; + +Prefix_w options { caseInsensitive=true; } + : 'PREFIX' + ; + +// PN_CHARS_BASE ((PN_CHARS | '.')* PN_CHARS)? +// Prefix without the final ':' +PN_PREFIX + : PN_CHARS_BASE ((PN_CHARS | '.')* PN_CHARS)? + ; + +IRIREF + : '<' ((~( '\u0000' | '\u0020' | '<' | '>' | '"' | '{' | '}' | '|' | '^' | '`' |'\\' )) | UCHAR)* '>' + ; + +// Prefix alone +PNAME_NS + : PN_PREFIX? ':' + ; + +PrefixedName + : PNAME_LN + | PNAME_NS + ; + +// Prefix + local name +PNAME_LN + : PNAME_NS PN_LOCAL + ; + +BLANK_NODE_LABEL + : '_:' (PN_CHARS_U | '0' .. '9') ((PN_CHARS | '.')* PN_CHARS)? + ; + +LANGTAG + : '@' ('a'.. 'z' | 'A' .. 'Z')+ ('-' ('a'.. 'z' | 'A' .. 'Z' | '0' .. '9')* )* + ; + +INTEGER + : ('+' | '-' )? ('0' .. '9')+ + ; + +DECIMAL + : ('+' | '-' )? ('0' .. '9')* '.' ('0' .. '9')+ + ; + +DOUBLE + : ('+' | '-' )? (('0' .. '9')+ '.' ('0' .. '9')* EXPONENT + | '.' ('0' .. '9')+ EXPONENT + | ('0' .. '9')+ EXPONENT) + ; + +EXPONENT + : ('e' | 'E') ('+' | '-' )? ('0' .. '9')+ + ; + +// "'''" (("'" | "''")? ([^'\] | ECHAR | UCHAR))* "'''" +STRING_LITERAL_LONG_SINGLE_QUOTE + : '\'\'\'' ( ('\'' '\''? )? ( [^'\\] | ECHAR | UCHAR | '"' ) )* '\'\'\'' + ; + +// '"""' (('"' | '""')? ([^"\] | ECHAR | UCHAR))* '"""' +STRING_LITERAL_LONG_QUOTE + : '"""' ( ('"' '"'? )? ( (~["\\]) | ECHAR | UCHAR )+ )* '"""' + ; + +STRING_LITERAL_QUOTE + : '"' (~ [\u0027\u005C\u000A\u000D] | ECHAR | UCHAR | '"')* '"' + ; + +STRING_LITERAL_SINGLE_QUOTE + : '\'' (~ [\u0027\u005C\u000A\u000D] | ECHAR | UCHAR | '\'')* '\'' + ; + +// Hexadecimal unicode character +UCHAR + : '\\u' HEX HEX HEX HEX + | '\\U' HEX HEX HEX HEX HEX HEX HEX HEX + ; + +// Escaped character +ECHAR + : '\\' [tbnrf"'\\] + ; + +ANON_WS + : ' ' + | '\t' + | '\r' + | '\n' + ; + +ANON + : '[' ANON_WS* ']' + ; + +PN_CHARS_BASE + : 'A' .. 'Z' + | 'a' .. 'z' + | '\u00C0' .. '\u00D6' + | '\u00D8' .. '\u00F6' + | '\u00F8' .. '\u02FF' + | '\u0370' .. '\u037D' + | '\u037F' .. '\u1FFF' + | '\u200C' .. '\u200D' + | '\u2070' .. '\u218F' + | '\u2C00' .. '\u2FEF' + | '\u3001' .. '\uD7FF' + | '\uF900' .. '\uFDCF' + | '\uFDF0' .. '\uFFFD' +// | '\u10000' .. '\uEFFFF' + ; + +PN_CHARS_U + : PN_CHARS_BASE + | '_' + ; + +PN_CHARS + : PN_CHARS_U + | '-' + | [0-9] + | [\u00B7] + | [\u0300-\u036F] + | [\u203F-\u2040] + ; + +PN_LOCAL + : (PN_CHARS_U | ':' | [0-9] | PLX) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX))? + ; + +PLX + : PERCENT + | PN_LOCAL_ESC + ; + +PERCENT + : '%' HEX HEX + ; + +HEX + : [0-9] + | [A-F] + | [a-f] + ; + +PN_LOCAL_ESC + : '\\' ( + '_' + | '~' + | '.' + | '-' + | '!' + | '$' + | '&' + | '\'' + | '(' + | ')' + | '*' + | '+' + | ',' + | ';' + | '=' + | '/' + | '?' + | '#' + | '@' + | '%' + ) + ; + +LC + : '#' ~[\r\n]* -> channel(HIDDEN) + ; + diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java new file mode 100644 index 000000000..bae3779fa --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java @@ -0,0 +1,46 @@ +package fr.inria.corese.core.next.impl.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 java.io.InputStream; +import java.io.Reader; + +public class TurtleParser implements RDFParser { + + private final Model model; + private final RDFFormat format = RDFFormats.TURTLE; + + public TurtleParser(Model model) { + this.model = model; + } + + + @Override + public RDFFormat getRDFFormat() { + return format; + } + + @Override + public void parse(InputStream in) { + + } + + @Override + public void parse(InputStream in, String baseURI) { + + } + + @Override + public void parse(Reader reader) { + + } + + @Override + public void parse(Reader reader, String baseURI) { + + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java new file mode 100644 index 000000000..69be4314f --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java @@ -0,0 +1,18 @@ +package fr.inria.corese.core.next.impl.parser.turtle; + +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.base.parser.RDFParser; +import fr.inria.corese.core.next.api.base.parser.RDFParserFactory; + +public class TurtleParserFactory implements RDFParserFactory { + + @Override + public RDFParser createRDFParser(RDFFormat format, Model model) { + if (!format.equals(RDFFormats.TURTLE)) { + throw new IllegalArgumentException("Unsupported format : " + format); + } + return new TurtleParser(model); + } +} From f286b90fc146e6bb2e4b6f15701389128d664737 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 23 Jun 2025 15:06:00 +0200 Subject: [PATCH 10/31] basic JSONLD implementation with titanium --- build.gradle.kts | 3 + .../base/io}/FileFormat.java | 2 +- .../base/io}/RdfFormat.java | 2 +- .../api/base/io/parser/AbstractParser.java | 39 +++ .../next/api/{ => io}/parser/RDFParser.java | 6 +- .../api/{ => io}/parser/RDFParserFactory.java | 5 +- .../serialization}/FormatSerializer.java | 7 +- .../core/next/api/parser/RDFFormat.java | 114 -------- .../core/next/api/parser/RDFFormats.java | 255 ------------------ .../core/next/impl/config/CoreConfig.java | 3 +- .../impl/io/parser/jsonld/JSONLDParser.java | 109 ++++++++ .../parser/jsonld/JSONLDParserFactory.java | 13 +- .../serialization/FormatConfig.java | 2 +- .../serialization/NQuadsFormat.java | 3 +- .../serialization/NTriplesFormat.java | 3 +- .../io}/serialization/NTriplesFormatTest.java | 152 ++++++----- .../serialization/Serializer.java | 19 +- .../next/impl/parser/jsonld/JSONLDParser.java | 121 --------- .../base/io}/FileFormatTest.java | 54 ++-- .../base/io}/RdfFormatTest.java | 94 +++---- .../parser/jsonld/JSONLDParserTest.java | 22 +- .../serialization/FormatConfigTest.java | 14 +- .../serialization/NQuadsFormatTest.java | 22 +- .../serialization/SerializerTest.java | 23 +- 24 files changed, 374 insertions(+), 713 deletions(-) rename src/main/java/fr/inria/corese/core/next/{impl/common/serialization => api/base/io}/FileFormat.java (97%) rename src/main/java/fr/inria/corese/core/next/{impl/common/serialization => api/base/io}/RdfFormat.java (98%) create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java rename src/main/java/fr/inria/corese/core/next/api/{ => io}/parser/RDFParser.java (89%) rename src/main/java/fr/inria/corese/core/next/api/{ => io}/parser/RDFParserFactory.java (73%) rename src/main/java/fr/inria/corese/core/next/api/{ => io/serialization}/FormatSerializer.java (87%) delete mode 100644 src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java delete mode 100644 src/main/java/fr/inria/corese/core/next/api/parser/RDFFormats.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParser.java rename src/main/java/fr/inria/corese/core/next/impl/{ => io}/parser/jsonld/JSONLDParserFactory.java (56%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/FormatConfig.java (96%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/NQuadsFormat.java (98%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/NTriplesFormat.java (98%) rename src/{test/java/fr/inria/corese/core/next/impl/common => main/java/fr/inria/corese/core/next/impl/io}/serialization/NTriplesFormatTest.java (65%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/Serializer.java (68%) delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java rename src/test/java/fr/inria/corese/core/next/{impl/common/serialization => api/base/io}/FileFormatTest.java (70%) rename src/test/java/fr/inria/corese/core/next/{impl/common/serialization => api/base/io}/RdfFormatTest.java (58%) rename src/test/java/fr/inria/corese/core/next/impl/{ => io}/parser/jsonld/JSONLDParserTest.java (94%) rename src/test/java/fr/inria/corese/core/next/impl/{common => io}/serialization/FormatConfigTest.java (67%) rename src/test/java/fr/inria/corese/core/next/impl/{common => io}/serialization/NQuadsFormatTest.java (92%) rename src/test/java/fr/inria/corese/core/next/impl/{common => io}/serialization/SerializerTest.java (66%) diff --git a/build.gradle.kts b/build.gradle.kts index 3a948204c..83a2bafa1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -117,6 +117,9 @@ dependencies { implementation("fr.inria.corese.org.semarglproject:semargl-rdfa:$semargl_version") // RDFa parser (Semargl) implementation("fr.inria.corese.org.semarglproject:semargl-core:$semargl_version") // Semargl core RDF parser implementation("com.github.jsonld-java:jsonld-java:0.13.6") // Legacy JSON-LD processing + implementation("com.apicatalog:titanium-json-ld:1.6.0") + implementation("com.apicatalog:titanium-rdf-api:1.0.0") + implementation("jakarta.json:jakarta.json-api:2.1.3") // === HTTP and XML === 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 98% 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 fbea74d93..e2cbb02fc 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; diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java new file mode 100644 index 000000000..67560a162 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java @@ -0,0 +1,39 @@ +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.parser.RDFParser; +import fr.inria.corese.core.next.impl.exception.ParsingErrorException; + +import java.io.InputStream; +import java.io.Reader; + +public abstract class AbstractParser implements RDFParser { + + private final Model model; + private final ValueFactory valueFactory; + + protected AbstractParser(Model model, ValueFactory factory) { + this.model = model; + this.valueFactory = factory; + + } + + @Override + public void parse(InputStream in) throws ParsingErrorException { + parse(in, null); + } + + @Override + public void parse(Reader reader) throws ParsingErrorException { + parse(reader, null); + } + + protected Model getModel() { + return model; + } + + protected ValueFactory getValueFactory() { + return valueFactory; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/api/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java similarity index 89% rename from src/main/java/fr/inria/corese/core/next/api/parser/RDFParser.java rename to src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index 2977bf158..9b1ab30a5 100644 --- a/src/main/java/fr/inria/corese/core/next/api/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -1,4 +1,6 @@ -package fr.inria.corese.core.next.api.parser; +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.base.io.RdfFormat; import java.io.InputStream; import java.io.Reader; @@ -8,7 +10,7 @@ public interface RDFParser { /** * Gets the RDF format that this parser can parse. */ - RDFFormat getRDFFormat(); + RdfFormat getRDFFormat(); /** * 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/parser/RDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java similarity index 73% rename from src/main/java/fr/inria/corese/core/next/api/parser/RDFParserFactory.java rename to src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java index 68f7c16c1..dc0b34eb8 100644 --- a/src/main/java/fr/inria/corese/core/next/api/parser/RDFParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java @@ -1,7 +1,8 @@ -package fr.inria.corese.core.next.api.parser; +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; public interface RDFParserFactory { @@ -12,6 +13,6 @@ public interface RDFParserFactory { * @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); + RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory); } diff --git a/src/main/java/fr/inria/corese/core/next/api/FormatSerializer.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/FormatSerializer.java similarity index 87% rename from src/main/java/fr/inria/corese/core/next/api/FormatSerializer.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/FormatSerializer.java index 4741a9712..6e95f96e2 100644 --- a/src/main/java/fr/inria/corese/core/next/api/FormatSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/FormatSerializer.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.api; - -import java.io.Writer; +package fr.inria.corese.core.next.api.io.serialization; +import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.impl.exception.SerializationException; +import java.io.Writer; + public interface FormatSerializer { /** diff --git a/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java b/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java deleted file mode 100644 index ad7988ad7..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormat.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.inria.corese.core.next.api.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/parser/RDFFormats.java b/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormats.java deleted file mode 100644 index f073fa898..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/parser/RDFFormats.java +++ /dev/null @@ -1,255 +0,0 @@ -package fr.inria.corese.core.next.api.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/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/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..020ab553e --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParser.java @@ -0,0 +1,109 @@ +package fr.inria.corese.core.next.impl.io.parser.jsonld; + +import com.apicatalog.jsonld.JsonLd; +import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.document.Document; +import com.apicatalog.jsonld.document.JsonDocument; +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.AbstractParser; +import fr.inria.corese.core.next.api.base.io.RdfFormat; +import fr.inria.corese.core.next.impl.exception.ParsingErrorException; + +import java.io.InputStream; +import java.io.Reader; + +public class JSONLDParser extends AbstractParser { + + 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); + } + + @Override + public RdfFormat getRDFFormat() { + return RdfFormat.JSONLD; + } + + @Override + public void parse(InputStream in, String baseURI) throws ParsingErrorException { + try { + parseJSONLDDocument(JsonDocument.of(in), baseURI); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } + + @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 { + JsonLd.toRdf(document) + .base(baseURI) + .provide(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; + if (RdfQuadConsumer.isValidObject(object, datatype, language)) { + // Object is a BN + if (RdfQuadConsumer.isBlank(object)) { + objValue = getValueFactory().createBNode(object); + // Object is a Literal + } else if (RdfQuadConsumer.isLiteral(object, datatype, language)) { + if (RdfQuadConsumer.isLangString(datatype, language, direction)) { + objValue = getValueFactory().createLiteral(object, language); + } else if( datatype != null ){ + objValue = getValueFactory().createLiteral(object, getValueFactory().createIRI(datatype)); + } else { + objValue = getValueFactory().createLiteral(object); + } + // Object is a IRI + } else { + objValue = getValueFactory().createIRI(object); + } + } + + // Graph + Resource graphResource = null; + if (RdfQuadConsumer.isBlank(graph)) { + graphResource = getValueFactory().createBNode(graph); + } else if(! graph.equals(JSONLD_JAVA_DEFAULT_GRAPH)) { + graphResource = getValueFactory().createIRI(graph); + } + + if(graphResource == null) { + getModel().add(subjResource, predicateIRI, objValue); + } else { + getModel().add(subjResource, predicateIRI, objValue, graphResource); + } + + return this; + } + }); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java similarity index 56% rename from src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java rename to src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java index d7eeae5b8..8bb7965bb 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java @@ -1,11 +1,10 @@ -package fr.inria.corese.core.next.impl.parser.jsonld; +package fr.inria.corese.core.next.impl.io.parser.jsonld; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.ValueFactory; -import fr.inria.corese.core.next.api.parser.RDFFormat; -import fr.inria.corese.core.next.api.parser.RDFFormats; -import fr.inria.corese.core.next.api.parser.RDFParser; -import fr.inria.corese.core.next.api.parser.RDFParserFactory; +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; public class JSONLDParserFactory implements RDFParserFactory { @@ -20,8 +19,8 @@ private JSONLDParserFactory() { } @Override - public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { - if(format == RDFFormats.JSON_LD) { + public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory) { + if(format == RdfFormat.JSONLD) { return new JSONLDParser(model, factory); } return null; diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java similarity index 96% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfig.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java index 0e85acff7..dc842840d 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import java.util.Objects; diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormat.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java similarity index 98% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormat.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java index daa921cf0..64b5bd34f 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormat.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java @@ -1,6 +1,7 @@ -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.*; +import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.common.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormat.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java similarity index 98% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormat.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java index fc20c0e92..fcfba5a32 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormat.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java @@ -1,6 +1,7 @@ -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.*; +import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.common.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormatTest.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java similarity index 65% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormatTest.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java index e00d89d41..3bcbd44cb 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesFormatTest.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java @@ -1,14 +1,16 @@ -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.*; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; - 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.ArgumentMatchers; +import org.mockito.Mockito; import java.io.IOException; import java.io.StringWriter; @@ -16,15 +18,11 @@ import java.util.Iterator; import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - class NTriplesFormatTest { private Model model; - private FormatConfig config; - private NTriplesFormat nTriplesFormat; + private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; + private fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat nTriplesFormat; private Resource mockExPerson; private IRI mockExName; @@ -41,9 +39,9 @@ class NTriplesFormatTest { @BeforeEach void setUp() { - model = mock(Model.class); - config = new FormatConfig.Builder().build(); - nTriplesFormat = new NTriplesFormat(model, config); + model = Mockito.mock(Model.class); + config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); + nTriplesFormat = new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, config); mockExPerson = createIRI("http://example.org/Person"); @@ -63,14 +61,14 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new NTriplesFormat(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new NTriplesFormat(null, config), "Model cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(null), "Model cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(null, config), "Model cannot be null"); } @Test @DisplayName("Constructor should throw NullPointerException for null config") void constructorShouldThrowForNullConfig() { - assertThrows(NullPointerException.class, () -> new NTriplesFormat(model, null), "Configuration cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, null), "Configuration cannot be null"); } @Test @@ -81,7 +79,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(); nTriplesFormat.write(writer); @@ -92,7 +90,7 @@ void writeShouldSerializeSimpleStatement() throws SerializationException { mockExName.stringValue(), escapeNTriplesString(lexJohn)) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -105,7 +103,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(); nTriplesFormat.write(writer); @@ -115,7 +113,7 @@ void writeShouldSerializeStatementWithContext() throws SerializationException { mockExName.stringValue(), escapeNTriplesString(lexJohn)) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -126,7 +124,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(); nTriplesFormat.write(writer); @@ -136,21 +134,21 @@ void writeShouldHandleBlankNodes() throws SerializationException { mockExKnows.stringValue(), mockBNode2.stringValue()) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @DisplayName("Write should handle blank nodes with custom prefix") void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - NTriplesFormat customSerializer = new NTriplesFormat(model, customConfig); + fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); + fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, customConfig); Statement stmt = createStatement( mockBNode1, mockExKnows, mockBNode2 ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); customSerializer.write(writer); @@ -160,7 +158,7 @@ void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException mockExKnows.stringValue(), mockBNode2.stringValue()) + " .\n"; - assertEquals(expected, writer.toString()); + Assertions.assertEquals(expected, writer.toString()); } @Test @@ -171,52 +169,52 @@ 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")).when(faultyWriter).write(anyString()); + Mockito.doThrow(new IOException("Simulated IO error")).when(faultyWriter).write(ArgumentMatchers.anyString()); - assertThrows(SerializationException.class, () -> nTriplesFormat.write(faultyWriter)); + Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(faultyWriter)); } @Test @DisplayName("Write should throw SerializationException on null subject value from Statement") void writeShouldThrowOnNullSubjectValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(null); - when(stmt.getPredicate()).thenReturn(mockExName); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Statement stmt = Mockito.mock(Statement.class); + Mockito.when(stmt.getSubject()).thenReturn(null); + Mockito.when(stmt.getPredicate()).thenReturn(mockExName); + Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); - assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); + Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); } @Test @DisplayName("Write should throw SerializationException on null predicate value from Statement") void writeShouldThrowOnNullPredicateValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(mockExPerson); - when(stmt.getPredicate()).thenReturn(null); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); + Statement stmt = Mockito.mock(Statement.class); + Mockito.when(stmt.getSubject()).thenReturn(mockExPerson); + Mockito.when(stmt.getPredicate()).thenReturn(null); + Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); - assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); + Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); } @Test @DisplayName("Write should throw SerializationException on null object value from Statement") 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(); - assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); + Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); } @ParameterizedTest @@ -239,7 +237,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(); nTriplesFormat.write(writer); @@ -250,7 +248,7 @@ void writeShouldHandleVariousLiterals(String literalValue) throws SerializationE mockExName.stringValue(), expectedEscapedLiteral) + " .\n"; - assertEquals(expectedOutput, writer.toString()); + Assertions.assertEquals(expectedOutput, writer.toString()); } @Test @@ -267,7 +265,7 @@ void writeShouldHandleMultipleStatements() throws SerializationException { mockExPerson, createIRI("http://example.org/ctx") ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt1, stmt2)); + Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt1, stmt2)); StringWriter writer = new StringWriter(); nTriplesFormat.write(writer); @@ -281,7 +279,7 @@ void writeShouldHandleMultipleStatements() throws SerializationException { mockExKnows.stringValue(), mockExPerson.stringValue()) + " .\n"; - assertEquals(expectedOutput, writer.toString()); + Assertions.assertEquals(expectedOutput, writer.toString()); } @Test @@ -289,11 +287,11 @@ void writeShouldHandleMultipleStatements() throws SerializationException { void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Statement stmt = createStatement(mockExPerson, 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(); - NTriplesFormat serializer = new NTriplesFormat(currentTestModel); + fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat serializer = new NTriplesFormat(currentTestModel); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -302,7 +300,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { escapeNTriplesString(hello), mockLiteralHelloEn.getLanguage().get()) + " .\n"; - assertEquals(expectedOutput, writer.toString()); + Assertions.assertEquals(expectedOutput, writer.toString()); } @@ -384,19 +382,19 @@ public Statement next() { * @return A mocked Literal instance. */ private Literal createLiteral(String lexicalForm, IRI dataTypeIRI, String langTag) { - Literal literal = mock(Literal.class); - when(literal.isLiteral()).thenReturn(true); - when(literal.isResource()).thenReturn(false); - when(literal.stringValue()).thenReturn(lexicalForm); + Literal literal = Mockito.mock(Literal.class); + Mockito.when(literal.isLiteral()).thenReturn(true); + Mockito.when(literal.isResource()).thenReturn(false); + Mockito.when(literal.stringValue()).thenReturn(lexicalForm); if (langTag != null && !langTag.isEmpty()) { - when(literal.getLanguage()).thenReturn(Optional.of(langTag)); + Mockito.when(literal.getLanguage()).thenReturn(Optional.of(langTag)); - when(literal.getDatatype()).thenReturn(RDF.langString.getIRI()); + Mockito.when(literal.getDatatype()).thenReturn(RDF.langString.getIRI()); } else { - when(literal.getLanguage()).thenReturn(Optional.empty()); - when(literal.getDatatype()).thenReturn(dataTypeIRI); + Mockito.when(literal.getLanguage()).thenReturn(Optional.empty()); + Mockito.when(literal.getDatatype()).thenReturn(dataTypeIRI); } return literal; } @@ -406,29 +404,29 @@ private Statement createStatement(Resource subject, IRI predicate, Value object) } private Statement createStatement(Resource subject, IRI predicate, Value object, Resource context) { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(subject); - when(stmt.getPredicate()).thenReturn(predicate); - when(stmt.getObject()).thenReturn(object); - when(stmt.getContext()).thenReturn(context); + Statement stmt = Mockito.mock(Statement.class); + Mockito.when(stmt.getSubject()).thenReturn(subject); + Mockito.when(stmt.getPredicate()).thenReturn(predicate); + Mockito.when(stmt.getObject()).thenReturn(object); + Mockito.when(stmt.getContext()).thenReturn(context); return stmt; } private Resource createBlankNode(String id) { - Resource blankNode = mock(Resource.class); - when(blankNode.isResource()).thenReturn(true); - when(blankNode.isBNode()).thenReturn(true); - when(blankNode.isIRI()).thenReturn(false); - when(blankNode.stringValue()).thenReturn(id); + Resource blankNode = Mockito.mock(Resource.class); + Mockito.when(blankNode.isResource()).thenReturn(true); + Mockito.when(blankNode.isBNode()).thenReturn(true); + Mockito.when(blankNode.isIRI()).thenReturn(false); + Mockito.when(blankNode.stringValue()).thenReturn(id); return blankNode; } private IRI createIRI(String uri) { - IRI iri = mock(IRI.class); - when(iri.isResource()).thenReturn(true); - when(iri.isIRI()).thenReturn(true); - when(iri.isBNode()).thenReturn(false); - when(iri.stringValue()).thenReturn(uri); + IRI iri = Mockito.mock(IRI.class); + Mockito.when(iri.isResource()).thenReturn(true); + Mockito.when(iri.isIRI()).thenReturn(true); + Mockito.when(iri.isBNode()).thenReturn(false); + Mockito.when(iri.stringValue()).thenReturn(uri); return iri; } } \ No newline at end of file diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/Serializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java similarity index 68% rename from src/main/java/fr/inria/corese/core/next/impl/common/serialization/Serializer.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java index 37427b832..3e315b61a 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/serialization/Serializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java @@ -1,7 +1,8 @@ -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.FormatSerializer; +import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; 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; @@ -22,27 +23,27 @@ public Serializer(Model model, FormatConfig config) { } /** - * Serializes the RDF model to the given writer in the specified {@link RdfFormat}. + * Serializes the RDF model to the given writer in the specified {@link fr.inria.corese.core.next.api.base.io.RdfFormat}. * * @param writer the Writer to write the serialized data to. - * @param format the {@link RdfFormat} describing the desired serialization format. + * @param format the {@link fr.inria.corese.core.next.api.base.io.RdfFormat} describing the desired serialization format. * @throws SerializationException if an error occurs during serialization or if the format is not currently supported by an implementation. */ - public void serialize(Writer writer, RdfFormat format) throws SerializationException { + public void serialize(Writer writer, fr.inria.corese.core.next.api.base.io.RdfFormat format) throws SerializationException { Objects.requireNonNull(writer, "Writer cannot be null"); Objects.requireNonNull(format, "RdfFormat cannot be null"); FormatSerializer formatSerializer; - if (format.equals(RdfFormat.NTRIPLES)) { + if (format.equals(fr.inria.corese.core.next.api.base.io.RdfFormat.NTRIPLES)) { formatSerializer = new NTriplesFormat(model, config); - } else if (format.equals( RdfFormat.NQUADS)) { + } else if (format.equals( fr.inria.corese.core.next.api.base.io.RdfFormat.NQUADS)) { formatSerializer = new NQuadsFormat(model, config); - } else if (format.equals( RdfFormat.TURTLE)) { + } else if (format.equals( fr.inria.corese.core.next.api.base.io.RdfFormat.TURTLE)) { throw new UnsupportedOperationException("Serialization to " + format.getName() + " format is not yet implemented."); - } else if (format.equals( RdfFormat.JSONLD)) { + } else if (format.equals( fr.inria.corese.core.next.api.base.io.RdfFormat.JSONLD)) { throw new UnsupportedOperationException("Serialization to " + format.getName() + " format is not yet implemented."); } else if (format.equals( RdfFormat.RDFXML)) { throw new UnsupportedOperationException("Serialization to " + format.getName() + " format is not yet implemented."); diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java deleted file mode 100644 index e2fb6439a..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParser.java +++ /dev/null @@ -1,121 +0,0 @@ -package fr.inria.corese.core.next.impl.parser.jsonld; - -import com.github.jsonldjava.core.JsonLdError; -import com.github.jsonldjava.core.JsonLdOptions; -import com.github.jsonldjava.core.JsonLdProcessor; -import com.github.jsonldjava.core.RDFDataset; -import com.github.jsonldjava.utils.JsonUtils; -import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.api.parser.RDFFormat; -import fr.inria.corese.core.next.api.parser.RDFFormats; -import fr.inria.corese.core.next.api.parser.RDFParser; -import fr.inria.corese.core.next.impl.exception.ParsingErrorException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; - -public class JSONLDParser implements RDFParser { - - private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JSONLDParser.class); - - private static final String jsonldjavadefaultGraphName = "@default"; - - private final Model model; - private final ValueFactory valueFactory; - private JsonLdOptions commonOptions = new JsonLdOptions(); - - public JSONLDParser(Model model, ValueFactory factory) { - this.model = model; - this.valueFactory = factory; - commonOptions.setCompactArrays(false); - commonOptions.setBase(null); - } - - @Override - public RDFFormat getRDFFormat() { - return RDFFormats.JSON_LD; - } - - private void parseFromJsonInput(Object input, String baseURI) { - try { - if(baseURI != null) { - commonOptions.setBase(baseURI); - } - RDFDataset output = (RDFDataset)JsonLdProcessor.toRDF(input, this.commonOptions); - for(String gName: output.graphNames()) { - for(RDFDataset.Quad q : output.getQuads(gName)) { - Resource subject = null; - if (q.getSubject().isIRI()) { - subject = valueFactory.createIRI(q.getSubject().getValue()); - } else { - subject = valueFactory.createBNode(q.getSubject().getValue()); - } - - IRI predicate = valueFactory.createIRI(q.getPredicate().getValue()); - - Value object = null; - if (q.getObject().isIRI()) { - object = valueFactory.createIRI(q.getObject().getValue()); - } else if (q.getObject().isBlankNode()) { - object = valueFactory.createBNode(q.getObject().getValue()); - } else if(q.getObject().isLiteral()){ - String objectDatatype = q.getObject().getDatatype(); - String objectLanguage = q.getObject().getLanguage(); - if(objectLanguage != null) { - object = valueFactory.createLiteral(q.getObject().getValue(), objectLanguage); - } else if(objectDatatype != null) { - object = valueFactory.createLiteral(q.getObject().getValue(), valueFactory.createIRI(objectDatatype)); - } else { - object = valueFactory.createLiteral(q.getObject().getValue()); - } - } else { - throw new ParsingErrorException("Unknown object type: " + q.getObject()); - } - - if(gName.equals(jsonldjavadefaultGraphName)) { - model.add(subject, predicate, object); - } else { - IRI graph = valueFactory.createIRI(gName); - model.add(subject, predicate, object, graph); - } - } - } - if(baseURI != null) { - commonOptions.setBase(null); - } - } catch (JsonLdError e) { - throw new ParsingErrorException(e); - } - } - - @Override - public void parse(InputStream in) throws ParsingErrorException { - parse(in, null); - } - - @Override - public void parse(InputStream in, String baseURI) throws ParsingErrorException { - try { - Object input = JsonUtils.fromInputStream(in); - parseFromJsonInput(input, baseURI); - } catch (IOException | JsonLdError e) { - throw new ParsingErrorException(e); - } - } - - @Override - public void parse(Reader reader) throws ParsingErrorException { - parse(reader, null); - } - - @Override - public void parse(Reader reader, String baseURI) { - try { - Object input = JsonUtils.fromReader(reader); - parseFromJsonInput(input, baseURI); - } catch (IOException | JsonLdError e) { - throw new ParsingErrorException(e); - } - } -} 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 58% 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 8f0df66d0..975b51b0c 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; @@ -20,7 +20,7 @@ void constructorAndGetters() { boolean supportsNamespaces = true; boolean supportsNamedGraphs = false; - RdfFormat format = new RdfFormat(name, extensions, mimeTypes, supportsNamespaces, supportsNamedGraphs); + fr.inria.corese.core.next.api.base.io.RdfFormat format = new fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat format = fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.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 + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t1"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t1"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, true); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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); + fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); + fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat turtle = fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat ntriples = fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat nquads = fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat jsonld = fr.inria.corese.core.next.api.base.io.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; + fr.inria.corese.core.next.api.base.io.RdfFormat rdfxml = fr.inria.corese.core.next.api.base.io.RdfFormat.RDFXML; assertNotNull(rdfxml, "RDFXML constant should not be null"); assertEquals("RDF/XML", rdfxml.getName()); @@ -223,16 +223,16 @@ void rdfXmlConstant() { @Test @DisplayName("byName() should find existing format by name (case-insensitive)") void byNameFound() { - Optional format = RdfFormat.byName("TuRtLe"); + Optional format = fr.inria.corese.core.next.api.base.io.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(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byName("NonExistentFormat"); assertFalse(format.isPresent(), "Non-existent format should not be found"); } @@ -240,20 +240,20 @@ void byNameNotFound() { @Test @DisplayName("byExtension() should find existing format by extension (case-insensitive)") void byExtensionFound() { - Optional format = RdfFormat.byExtension("TTL"); + Optional format = fr.inria.corese.core.next.api.base.io.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(fr.inria.corese.core.next.api.base.io.RdfFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); - Optional rdfXmlFormat = RdfFormat.byExtension("XML"); + Optional rdfXmlFormat = fr.inria.corese.core.next.api.base.io.RdfFormat.byExtension("XML"); assertTrue(rdfXmlFormat.isPresent()); - assertEquals(RdfFormat.RDFXML, rdfXmlFormat.get()); + assertEquals(fr.inria.corese.core.next.api.base.io.RdfFormat.RDFXML, rdfXmlFormat.get()); } @Test @DisplayName("byExtension() should return empty Optional for non-existent extension") void byExtensionNotFound() { - Optional format = RdfFormat.byExtension("xyz"); + Optional format = fr.inria.corese.core.next.api.base.io.RdfFormat.byExtension("xyz"); assertFalse(format.isPresent(), "Non-existent extension should not find a format"); } @@ -261,21 +261,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 = fr.inria.corese.core.next.api.base.io.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(fr.inria.corese.core.next.api.base.io.RdfFormat.TURTLE, format.get(), "Found format should be the TURTLE constant"); - Optional nTriplesFormat = RdfFormat.byMimeType("text/plain"); + Optional nTriplesFormat = fr.inria.corese.core.next.api.base.io.RdfFormat.byMimeType("text/plain"); assertTrue(nTriplesFormat.isPresent()); - assertEquals(RdfFormat.NTRIPLES, nTriplesFormat.get()); + assertEquals(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byMimeType("application/x-unknown"); assertFalse(format.isPresent(), "Non-existent MIME type should not find a format"); } @@ -283,16 +283,16 @@ void byMimeTypeNotFound() { @Test @DisplayName("all() should return a list containing all predefined formats") void allFormats() { - List allFormats = RdfFormat.all(); + List allFormats = fr.inria.corese.core.next.api.base.io.RdfFormat.all(); assertNotNull(allFormats, "List of all formats should not be null"); assertEquals(5, allFormats.size(), "List should contain 5 predefined formats"); // TURTLE, NTRIPLES, NQUADS, JSONLD, RDFXML - 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(fr.inria.corese.core.next.api.base.io.RdfFormat.TURTLE)); + assertTrue(allFormats.contains(fr.inria.corese.core.next.api.base.io.RdfFormat.NTRIPLES)); + assertTrue(allFormats.contains(fr.inria.corese.core.next.api.base.io.RdfFormat.NQUADS)); + assertTrue(allFormats.contains(fr.inria.corese.core.next.api.base.io.RdfFormat.JSONLD)); + assertTrue(allFormats.contains(fr.inria.corese.core.next.api.base.io.RdfFormat.RDFXML)); assertThrows(UnsupportedOperationException.class, () -> allFormats.add(RdfFormat.TURTLE), "The list returned by all() should be unmodifiable"); diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java similarity index 94% rename from src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java index 42894cc47..dee403461 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/parser/jsonld/JSONLDParserTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java @@ -1,11 +1,11 @@ -package fr.inria.corese.core.next.impl.parser.jsonld; +package fr.inria.corese.core.next.impl.io.parser.jsonld; import fr.inria.corese.core.next.api.BNode; import fr.inria.corese.core.next.api.IRI; import fr.inria.corese.core.next.api.Literal; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.api.parser.RDFFormats; -import fr.inria.corese.core.next.api.parser.RDFParser; +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.temp.CoreseAdaptedValueFactory; import fr.inria.corese.core.next.impl.temp.CoreseModel; import org.junit.jupiter.api.Test; @@ -20,8 +20,8 @@ public class JSONLDParserTest { @Test void testGetRDFFormat() { - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, new CoreseModel(), new CoreseAdaptedValueFactory()); - assertEquals(RDFFormats.JSON_LD, parser.getRDFFormat()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, new CoreseModel(), new CoreseAdaptedValueFactory()); + assertEquals(RdfFormat.JSONLD, parser.getRDFFormat()); } /** @@ -46,7 +46,7 @@ public void testParseInputStream() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); assertEquals(3, model.size()); @@ -84,7 +84,7 @@ public void testParseInputStreamString() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes()), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -122,7 +122,7 @@ public void testParseReader() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(3, model.size()); @@ -160,7 +160,7 @@ public void testParseReaderString() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -203,7 +203,7 @@ public void testParseJsonLDWithBlankNodes() { """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(2, model.size()); @@ -249,7 +249,7 @@ public void testParseJSONLDWithGraphs() { """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RDFFormats.JSON_LD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(7, model.size()); diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfigTest.java similarity index 67% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfigTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfigTest.java index c1ee05f95..799e0d70d 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/FormatConfigTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfigTest.java @@ -1,11 +1,9 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; class FormatConfigTest { @@ -13,7 +11,7 @@ class FormatConfigTest { @DisplayName("Builder should create FormatConfig with default blank node prefix") void builderShouldCreateWithDefaultBlankNodePrefix() { - FormatConfig config = new FormatConfig.Builder().build(); + fr.inria.corese.core.next.impl.io.serialization.FormatConfig config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); assertNotNull(config, "FormatConfig should not be null"); @@ -26,7 +24,7 @@ void builderShouldCreateWithCustomBlankNodePrefix() { String customPrefix = "genid-"; - FormatConfig config = new FormatConfig.Builder() + fr.inria.corese.core.next.impl.io.serialization.FormatConfig config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder() .blankNodePrefix(customPrefix) .build(); @@ -39,7 +37,7 @@ void builderShouldCreateWithCustomBlankNodePrefix() { @DisplayName("blankNodePrefix method in Builder should throw NullPointerException for null prefix") void blankNodePrefixShouldThrowForNull() { - FormatConfig.Builder builder = new FormatConfig.Builder(); + fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder builder = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder(); assertThrows(NullPointerException.class, () -> builder.blankNodePrefix(null), @@ -50,7 +48,7 @@ void blankNodePrefixShouldThrowForNull() { @DisplayName("FormatConfig constructor should be private and only accessible via builder") void constructorIsPrivateAndAccessibleViaBuilder() { - FormatConfig config = new FormatConfig.Builder().build(); + fr.inria.corese.core.next.impl.io.serialization.FormatConfig config = new FormatConfig.Builder().build(); assertNotNull(config); } } diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.java similarity index 92% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormatTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.java index 5d1a3636d..94510d036 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.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.*; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; @@ -22,8 +22,8 @@ class NQuadsFormatTest { private Model model; - private FormatConfig config; - private NQuadsFormat nQuadsFormat; + private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; + private fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat nQuadsFormat; private Resource mockExPerson; private IRI mockExName; @@ -44,8 +44,8 @@ class NQuadsFormatTest { @BeforeEach void setUp() { model = mock(Model.class); - config = new FormatConfig.Builder().build(); - nQuadsFormat = new NQuadsFormat(model, config); + config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); + nQuadsFormat = new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, config); mockExPerson = createIRI("http://example.org/Person"); mockExName = createIRI("http://example.org/name"); @@ -64,14 +64,14 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new NQuadsFormat(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new NQuadsFormat(null, config), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(null), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(null, config), "Model cannot be null"); } @Test @DisplayName("Constructor should throw NullPointerException for null config") void constructorShouldThrowForNullConfig() { - assertThrows(NullPointerException.class, () -> new NQuadsFormat(model, null), "Configuration cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, null), "Configuration cannot be null"); } @Test @@ -168,8 +168,8 @@ void writeShouldHandleBlankNodesInContext() throws SerializationException { @Test @DisplayName("Write should handle blank nodes with custom prefix") void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - NQuadsFormat customSerializer = new NQuadsFormat(model, customConfig); + fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); + fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, customConfig); Statement stmt = createStatement( mockBNode1, @@ -318,7 +318,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); - NQuadsFormat serializer = new NQuadsFormat(currentTestModel); + fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat serializer = new NQuadsFormat(currentTestModel); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", diff --git a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/SerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java similarity index 66% rename from src/test/java/fr/inria/corese/core/next/impl/common/serialization/SerializerTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java index 0e8700810..838deb1eb 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/common/serialization/SerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.common.serialization; +package fr.inria.corese.core.next.impl.io.serialization; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -7,6 +7,11 @@ import java.io.Writer; +import fr.inria.corese.core.next.api.base.io.RdfFormat; +import fr.inria.corese.core.next.impl.io.serialization.FormatConfig; +import fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat; +import fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat; +import fr.inria.corese.core.next.impl.io.serialization.Serializer; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -19,7 +24,7 @@ class SerializerTest { - private Serializer serializer; + private fr.inria.corese.core.next.impl.io.serialization.Serializer serializer; @Mock private Model mockModel; @@ -31,7 +36,7 @@ class SerializerTest { @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - serializer = new Serializer(mockModel, mockConfig); + serializer = new fr.inria.corese.core.next.impl.io.serialization.Serializer(mockModel, mockConfig); } // --- Constructor tests --- @@ -39,8 +44,8 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new Serializer(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new Serializer(null, mockConfig), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.Serializer(null), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.Serializer(null, mockConfig), "Model cannot be null"); } @Test @@ -54,7 +59,7 @@ void constructorShouldThrowForNullConfig() { @Test @DisplayName("serialize should throw NullPointerException for null writer") void serializeShouldThrowForNullWriter() { - assertThrows(NullPointerException.class, () -> serializer.serialize(null, RdfFormat.NTRIPLES), + assertThrows(NullPointerException.class, () -> serializer.serialize(null, fr.inria.corese.core.next.api.base.io.RdfFormat.NTRIPLES), "Writer cannot be null"); } @@ -70,8 +75,8 @@ void serializeShouldThrowForNullFormat() { @Test @DisplayName("serialize should delegate to NTriplesFormat for NTRIPLES format") void serializeShouldDelegateToNTriplesFormat() throws SerializationException { - try (MockedConstruction mockedNtConstructor = mockConstruction(NTriplesFormat.class)) { - serializer.serialize(mockWriter, RdfFormat.NTRIPLES); + try (MockedConstruction mockedNtConstructor = mockConstruction(fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat.class)) { + serializer.serialize(mockWriter, fr.inria.corese.core.next.api.base.io.RdfFormat.NTRIPLES); assertEquals(1, mockedNtConstructor.constructed().size(), "NTriplesFormat constructor should be called once"); @@ -85,7 +90,7 @@ void serializeShouldDelegateToNTriplesFormat() throws SerializationException { @Test @DisplayName("serialize should delegate to NQuadsFormat for NQUADS format") void serializeShouldDelegateToNQuadsFormat() throws SerializationException { - try (MockedConstruction mockedNqConstructor = mockConstruction(NQuadsFormat.class)) { + try (MockedConstruction mockedNqConstructor = mockConstruction(fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat.class)) { serializer.serialize(mockWriter, RdfFormat.NQUADS); assertEquals(1, mockedNqConstructor.constructed().size(), "NQuadsFormat constructor should be called once"); From 9c06cfcf83f2d5cfc37bed5577c22955d854e7eb Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Tue, 24 Jun 2025 11:49:55 +0200 Subject: [PATCH 11/31] better package organization --- .gitignore | 2 ++ .../api/base/io/parser/AbstractParser.java | 11 ++++++++ .../io/parser/AbstractRDFParserFactory.java | 18 ++++++++++++ .../corese/core/next/api/io/IOConfig.java | 4 +++ .../core/next/api/io/parser/RDFParser.java | 4 +++ .../next/api/io/parser/RDFParserFactory.java | 12 ++++++++ .../next/impl/io/parser/ParserFactory.java | 24 ++++++++++++++++ .../impl/io/parser/jsonld/JSONLDParser.java | 8 ++++++ .../io/parser/jsonld/JSONLDParserConfig.java | 21 ++++++++++++++ .../io/parser/jsonld/JSONLDParserFactory.java | 28 ------------------- .../impl/io/serialization/FormatConfig.java | 5 +++- .../impl/io/serialization/Serializer.java | 2 ++ .../{ => nquads}/NQuadsFormat.java | 3 +- .../{ => ntriples}/NTriplesFormat.java | 3 +- .../io/parser/jsonld/JSONLDParserTest.java | 17 ++++++----- .../impl/io/serialization/SerializerTest.java | 10 +++---- .../{ => nquads}/NQuadsFormatTest.java | 15 +++++----- .../ntriples}/NTriplesFormatTest.java | 15 +++++----- 18 files changed, 144 insertions(+), 58 deletions(-) create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParserFactory.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/io/IOConfig.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java rename src/main/java/fr/inria/corese/core/next/impl/io/serialization/{ => nquads}/NQuadsFormat.java (98%) rename src/main/java/fr/inria/corese/core/next/impl/io/serialization/{ => ntriples}/NTriplesFormat.java (98%) rename src/test/java/fr/inria/corese/core/next/impl/io/serialization/{ => nquads}/NQuadsFormatTest.java (95%) rename src/{main/java/fr/inria/corese/core/next/impl/io/serialization => test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples}/NTriplesFormatTest.java (94%) diff --git a/.gitignore b/.gitignore index a500424cd..2885ea863 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,7 @@ target/ /dist/ /nbdist/ /.nb-gradle/ +.continue/ # Logs and coverage reports *.log @@ -82,6 +83,7 @@ gradle/gradle-daemon-jvm.properties # Other build directories and generated files /bin/ +/out/ # Fichiers de logs logs/ diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java index 67560a162..a2c9a06db 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java @@ -2,6 +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.io.IOConfig; import fr.inria.corese.core.next.api.io.parser.RDFParser; import fr.inria.corese.core.next.impl.exception.ParsingErrorException; @@ -12,6 +13,16 @@ public abstract class AbstractParser implements RDFParser { private final Model model; private final ValueFactory valueFactory; + private IOConfig config; + + public IOConfig getConfig() { + return config; + } + + @Override + public void setConfig(IOConfig config) { + this.config = config; + } protected AbstractParser(Model model, ValueFactory factory) { this.model = model; 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..d8dcbf76f --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParserFactory.java @@ -0,0 +1,18 @@ +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; + +public abstract class AbstractRDFParserFactory implements RDFParserFactory { + + protected AbstractRDFParserFactory() { + } + + @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/io/IOConfig.java b/src/main/java/fr/inria/corese/core/next/api/io/IOConfig.java new file mode 100644 index 000000000..0c6adbb54 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/IOConfig.java @@ -0,0 +1,4 @@ +package fr.inria.corese.core.next.api.io; + +public interface IOConfig { +} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index 9b1ab30a5..7b7758815 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -1,6 +1,7 @@ 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.IOConfig; import java.io.InputStream; import java.io.Reader; @@ -12,6 +13,9 @@ public interface RDFParser { */ RdfFormat getRDFFormat(); + public void setConfig(IOConfig config); + public IOConfig 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/RDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java index dc0b34eb8..cb86b263d 100644 --- 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 @@ -3,9 +3,11 @@ 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.IOConfig; public interface RDFParserFactory { + /** * Creates a new RDF parser for the specified format and model. * @@ -15,4 +17,14 @@ public interface RDFParserFactory { */ 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, IOConfig config); + } 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..3f99ad1fb --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java @@ -0,0 +1,24 @@ +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.IOConfig; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.impl.io.parser.jsonld.JSONLDParser; + +public class ParserFactory extends AbstractRDFParserFactory { + + public ParserFactory() { + super(); + } + + @Override + public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory, IOConfig config) { + if(format == RdfFormat.JSONLD) { + return new JSONLDParser(model, factory, config); + } + 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 index 020ab553e..0f01cac0b 100644 --- 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 @@ -9,6 +9,7 @@ import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.api.base.io.parser.AbstractParser; import fr.inria.corese.core.next.api.base.io.RdfFormat; +import fr.inria.corese.core.next.api.io.IOConfig; import fr.inria.corese.core.next.impl.exception.ParsingErrorException; import java.io.InputStream; @@ -24,6 +25,13 @@ public JSONLDParser(Model model, ValueFactory factory) { super(model, factory); } + public JSONLDParser(Model model, ValueFactory factory, IOConfig config) { + super(model, factory); + if(config instanceof JSONLDParserConfig) { + setConfig(config); + } + } + @Override public RdfFormat getRDFFormat() { return RdfFormat.JSONLD; diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java new file mode 100644 index 000000000..9909f2412 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java @@ -0,0 +1,21 @@ +package fr.inria.corese.core.next.impl.io.parser.jsonld; + +import fr.inria.corese.core.next.api.IRI; +import fr.inria.corese.core.next.api.io.IOConfig; + +public class JSONLDParserConfig implements IOConfig { + + private IRI baseIRI = null; + + public JSONLDParserConfig() { + super(); + } + + public void setBaseIRI(IRI baseIRI) { + this.baseIRI = baseIRI; + } + + public IRI getBaseIRI() { + return baseIRI; + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java deleted file mode 100644 index 8bb7965bb..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.inria.corese.core.next.impl.io.parser.jsonld; - -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; - -public class JSONLDParserFactory implements RDFParserFactory { - - private static final JSONLDParserFactory INSTANCE = new JSONLDParserFactory(); - - public static JSONLDParserFactory getInstance() { - return INSTANCE; - } - - private JSONLDParserFactory() { - - } - - @Override - public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory) { - if(format == RdfFormat.JSONLD) { - return new JSONLDParser(model, factory); - } - return null; - } -} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java index dc842840d..888b5c3c2 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java @@ -1,12 +1,15 @@ package fr.inria.corese.core.next.impl.io.serialization; +import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; + import java.util.Objects; /** * Configuration options for the {@link NTriplesFormat} serializer. * Use {@link FormatConfig # Builder} to create instances. */ -public class FormatConfig { +public class FormatConfig implements IOConfig { private final String blankNodePrefix; diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java index 3e315b61a..36a8bbcdc 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/Serializer.java @@ -4,6 +4,8 @@ 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 fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; import java.io.Writer; import java.util.Objects; diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormat.java similarity index 98% rename from src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormat.java index 64b5bd34f..b5c433343 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormat.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormat.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.impl.io.serialization; +package fr.inria.corese.core.next.impl.io.serialization.nquads; import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.common.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.serialization.FormatConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormat.java similarity index 98% rename from src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormat.java index fcfba5a32..5bf989118 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormat.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormat.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.impl.io.serialization; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.common.util.SerializationConstants; import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.serialization.FormatConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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 index dee403461..609aee582 100644 --- 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 @@ -6,6 +6,7 @@ import fr.inria.corese.core.next.api.Statement; 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; @@ -18,9 +19,11 @@ public class JSONLDParserTest { + private final ParserFactory factory = new ParserFactory(); + @Test void testGetRDFFormat() { - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, new CoreseModel(), new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, new CoreseModel(), new CoreseAdaptedValueFactory()); assertEquals(RdfFormat.JSONLD, parser.getRDFFormat()); } @@ -46,7 +49,7 @@ public void testParseInputStream() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); assertEquals(3, model.size()); @@ -84,7 +87,7 @@ public void testParseInputStreamString() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes()), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -122,7 +125,7 @@ public void testParseReader() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(3, model.size()); @@ -160,7 +163,7 @@ public void testParseReaderString() { } """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -203,7 +206,7 @@ public void testParseJsonLDWithBlankNodes() { """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(2, model.size()); @@ -249,7 +252,7 @@ public void testParseJSONLDWithGraphs() { """; CoreseModel model = new CoreseModel(); - RDFParser parser = JSONLDParserFactory.getInstance().createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); parser.parse(new StringReader(sampleJsonLD)); assertEquals(7, model.size()); diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java index 838deb1eb..adeb0c874 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/SerializerTest.java @@ -8,10 +8,8 @@ import java.io.Writer; import fr.inria.corese.core.next.api.base.io.RdfFormat; -import fr.inria.corese.core.next.impl.io.serialization.FormatConfig; -import fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat; -import fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat; -import fr.inria.corese.core.next.impl.io.serialization.Serializer; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -75,7 +73,7 @@ void serializeShouldThrowForNullFormat() { @Test @DisplayName("serialize should delegate to NTriplesFormat for NTRIPLES format") void serializeShouldDelegateToNTriplesFormat() throws SerializationException { - try (MockedConstruction mockedNtConstructor = mockConstruction(fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat.class)) { + try (MockedConstruction mockedNtConstructor = mockConstruction(fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat.class)) { serializer.serialize(mockWriter, fr.inria.corese.core.next.api.base.io.RdfFormat.NTRIPLES); assertEquals(1, mockedNtConstructor.constructed().size(), @@ -90,7 +88,7 @@ void serializeShouldDelegateToNTriplesFormat() throws SerializationException { @Test @DisplayName("serialize should delegate to NQuadsFormat for NQUADS format") void serializeShouldDelegateToNQuadsFormat() throws SerializationException { - try (MockedConstruction mockedNqConstructor = mockConstruction(fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat.class)) { + try (MockedConstruction mockedNqConstructor = mockConstruction(NQuadsFormat.class)) { serializer.serialize(mockWriter, RdfFormat.NQUADS); assertEquals(1, mockedNqConstructor.constructed().size(), "NQuadsFormat constructor should be called once"); diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java similarity index 95% rename from src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java index 94510d036..72e33fd98 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/NQuadsFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java @@ -3,6 +3,7 @@ import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -23,7 +24,7 @@ class NQuadsFormatTest { private Model model; private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat nQuadsFormat; + private fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat nQuadsFormat; private Resource mockExPerson; private IRI mockExName; @@ -45,7 +46,7 @@ class NQuadsFormatTest { void setUp() { model = mock(Model.class); config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nQuadsFormat = new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, config); + nQuadsFormat = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, config); mockExPerson = createIRI("http://example.org/Person"); mockExName = createIRI("http://example.org/name"); @@ -64,14 +65,14 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(null, config), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null), "Model cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null, config), "Model cannot be null"); } @Test @DisplayName("Constructor should throw NullPointerException for null config") void constructorShouldThrowForNullConfig() { - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, null), "Configuration cannot be null"); + assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, null), "Configuration cannot be null"); } @Test @@ -169,7 +170,7 @@ void writeShouldHandleBlankNodesInContext() throws SerializationException { @DisplayName("Write should handle blank nodes with custom prefix") void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat(model, customConfig); + fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, customConfig); Statement stmt = createStatement( mockBNode1, @@ -318,7 +319,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); - fr.inria.corese.core.next.impl.io.serialization.NQuadsFormat serializer = new NQuadsFormat(currentTestModel); + fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat serializer = new NQuadsFormat(currentTestModel); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java similarity index 94% rename from src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java index 3bcbd44cb..f420c93c7 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/NTriplesFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java @@ -3,6 +3,7 @@ import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.impl.common.vocabulary.RDF; import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -22,7 +23,7 @@ class NTriplesFormatTest { private Model model; private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat nTriplesFormat; + private fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat nTriplesFormat; private Resource mockExPerson; private IRI mockExName; @@ -41,7 +42,7 @@ class NTriplesFormatTest { void setUp() { model = Mockito.mock(Model.class); config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nTriplesFormat = new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, config); + nTriplesFormat = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, config); mockExPerson = createIRI("http://example.org/Person"); @@ -61,14 +62,14 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(null), "Model cannot be null"); - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(null, config), "Model cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null), "Model cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null, config), "Model cannot be null"); } @Test @DisplayName("Constructor should throw NullPointerException for null config") void constructorShouldThrowForNullConfig() { - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, null), "Configuration cannot be null"); + Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, null), "Configuration cannot be null"); } @Test @@ -141,7 +142,7 @@ void writeShouldHandleBlankNodes() throws SerializationException { @DisplayName("Write should handle blank nodes with custom prefix") void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat(model, customConfig); + fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, customConfig); Statement stmt = createStatement( mockBNode1, @@ -291,7 +292,7 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Mockito.when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); - fr.inria.corese.core.next.impl.io.serialization.NTriplesFormat serializer = new NTriplesFormat(currentTestModel); + fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat serializer = new NTriplesFormat(currentTestModel); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", From ad060727bdfb985b57691fd3bb279830c4a03117 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 25 Jun 2025 14:25:41 +0200 Subject: [PATCH 12/31] Basic jsonld serializer --- .../jsonld/JSONLDSerializer.java | 36 +++ .../jsonld/JSONLDSerializerConfig.java | 8 + .../jsonld/JSONLDSerializerFactory.java | 33 ++ ...itaniumRDFDatasetSerializationAdapter.java | 306 ++++++++++++++++++ 4 files changed, 383 insertions(+) create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/TitaniumRDFDatasetSerializationAdapter.java 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..6d99affe5 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java @@ -0,0 +1,36 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.serialization.RdfToJsonld; +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; +import fr.inria.corese.core.next.impl.exception.SerializationException; + +import java.io.IOException; +import java.io.Writer; + +public class JSONLDSerializer implements FormatSerializer { + + private Model model; + private JSONLDSerializerConfig config; + + public JSONLDSerializer(Model model, JSONLDSerializerConfig config) { + this.model = model; + this.config = config; + } + + public JSONLDSerializer(Model model) { + this(model, null); + } + + @Override + public void write(Writer writer) throws SerializationException { + TitaniumRDFDatasetSerializationAdapter adapter = new TitaniumRDFDatasetSerializationAdapter(model); + try { + jakarta.json.JsonArray jsonArray = RdfToJsonld.with(adapter).build(); + 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/JSONLDSerializerConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java new file mode 100644 index 000000000..0f4395afa --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java @@ -0,0 +1,8 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import fr.inria.corese.core.next.api.io.IOConfig; + +public class JSONLDSerializerConfig implements IOConfig { + public JSONLDSerializerConfig() { + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java new file mode 100644 index 000000000..a3057f64d --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java @@ -0,0 +1,33 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.base.io.RdfFormat; +import fr.inria.corese.core.next.api.io.IOConfig; + +/** + * Placeholder class while waiting for the general serializer factory to be implemented + */ +public class JSONLDSerializerFactory { + + public JSONLDSerializerFactory() { + } + + public JSONLDSerializer createSerializer(RdfFormat format, Model model) { + return createSerializer(format, model, null); + } + + public JSONLDSerializer createSerializer(RdfFormat format, Model model, IOConfig config) { + if(format == RdfFormat.JSONLD) { + if(config == null) { + return new JSONLDSerializer(model); + } else if(config instanceof JSONLDSerializerConfig) { + return new JSONLDSerializer(model, (JSONLDSerializerConfig) config); + } else { + throw new IllegalArgumentException("Unsupported config for JSONLD serialization: " + config); + } + } else { + throw new IllegalArgumentException("Unsupported format: " + format); + } + + } +} 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..4e26ef068 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/TitaniumRDFDatasetSerializationAdapter.java @@ -0,0 +1,306 @@ +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 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.*; + +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 null; + } + + @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() { + return new HashSet<>(this.model.contexts().stream().map(this::toRdfResource).toList()); + } + + @Override + public Optional getGraph(RdfResource graphName) { + return Optional.of(new RdfGraph() { + @Override + public boolean contains(RdfTriple triple) { + return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject())); + } + + @Override + public List toList() { + List result = new ArrayList<>(); + model.getStatements(null, null, null, toResource(graphName)).forEach(statement -> result.add(toRdfNQuad(statement))); + return result; + } + }); + } + + @Override + public int size() { + return this.model.size(); + } + + 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()); + } + }; + } + + private RdfResource toRdfResource(Resource resource) { + return () -> { + if (resource != null) { + return resource.stringValue(); + } else { + return null; + } + }; + } + + private RdfValue toRdfValue(Value value) { + if (value.isResource()) { + return toRdfResource((Resource) value); + } else if (value.isLiteral()) { + return toRdfLiteral((Literal) value); + } else { + throw new IllegalArgumentException("Unknown value type"); + } + } + + private RdfLiteral toRdfLiteral(Literal literal) { + return new RdfLiteral() { + @Override + public String getValue() { + return literal.getLabel(); + } + + @Override + public String getDatatype() { + if (literal.getDatatype() != null) { + return literal.getDatatype().stringValue(); + } else { + return ""; + } + } + + @Override + public Optional getLanguage() { + return literal.getLanguage(); + } + }; + } + + 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 IllegalArgumentException("Unknown value type"); + } + } + + private Resource toResource(RdfResource resource) { + if (resource.isIRI()) { + return toIRI(resource); + } else if (resource.isBlankNode()) { + return toBNode(resource); + } else { + throw new IllegalArgumentException("Unknown resource type"); + } + } + + private IRI toIRI(RdfResource resource) { + if(resource.isIRI()) { + return stringToIRI(resource.getValue()); + } + return null; + } + + 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; + } + + 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) { + logger.error("Literal couldn't be converted to XMLGregorianCalendar", e); + } + return null; + } + + @Override + public CoreDatatype getCoreDatatype() { + return () -> stringToIRI(literal.getDatatype()); + } + }; + } + + private IRI stringToIRI(String iri) { + if (iri == null || !IRIUtils.isStandardIRI(iri)) { + return null; + } + 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; + } + }; + } +} From 6a97a7316e681d44ce141fc7911ca1775c96fed6 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 25 Jun 2025 16:59:46 +0200 Subject: [PATCH 13/31] better config --- .../jsonld/JSONLDSerializer.java | 17 ++++++-- .../jsonld/JSONLDSerializerConfig.java | 42 +++++++++++++++++++ .../jsonld/JSONLDSerializerFactory.java | 4 +- ...itaniumRDFDatasetSerializationAdapter.java | 36 +++++++++++++++- 4 files changed, 91 insertions(+), 8 deletions(-) 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 index 6d99affe5..c59394e1e 100644 --- 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 @@ -8,26 +8,35 @@ import java.io.IOException; import java.io.Writer; +import java.util.Objects; +/** + * Serializer for JSON-LD format. + */ public class JSONLDSerializer implements FormatSerializer { private Model model; private JSONLDSerializerConfig config; public JSONLDSerializer(Model model, JSONLDSerializerConfig config) { - this.model = model; - this.config = config; + this.model = Objects.requireNonNull(model); + this.config = Objects.requireNonNull(config); } public JSONLDSerializer(Model model) { - this(model, null); + this(model, new JSONLDSerializerConfig()); } @Override public void write(Writer writer) throws SerializationException { TitaniumRDFDatasetSerializationAdapter adapter = new TitaniumRDFDatasetSerializationAdapter(model); try { - jakarta.json.JsonArray jsonArray = RdfToJsonld.with(adapter).build(); + RdfToJsonld builder = RdfToJsonld.with(adapter) + .ordered(this.config.isOrdered()) + .processingMode(this.config.getVersion()) + .useNativeTypes(this.config.usesNativeTypes()) + .useRdfType(this.config.usesRdfType()); + jakarta.json.JsonArray jsonArray = builder.build(); 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/JSONLDSerializerConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java index 0f4395afa..1e3427013 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java @@ -1,8 +1,50 @@ package fr.inria.corese.core.next.impl.io.serialization.jsonld; +import com.apicatalog.jsonld.JsonLdVersion; import fr.inria.corese.core.next.api.io.IOConfig; public class JSONLDSerializerConfig implements IOConfig { + + private boolean ordered = false; + private JsonLdVersion version = JsonLdVersion.V1_1; + private boolean useNativeTypes = false; + private boolean useRdfType = false; public JSONLDSerializerConfig() { } + + public boolean isOrdered() { + return ordered; + } + + public void setOrdered(boolean ordered) { + this.ordered = ordered; + } + + public void setVersionTo10() { + version = JsonLdVersion.V1_0; + } + + public void setVersionTo11() { + version = JsonLdVersion.V1_1; + } + + public JsonLdVersion getVersion() { + return version; + } + + public boolean usesNativeTypes() { + return useNativeTypes; + } + + public void setUseNativeTypes(boolean useNativeTypes) { + this.useNativeTypes = useNativeTypes; + } + + public boolean usesRdfType() { + return useRdfType; + } + + public void setUseRdfType(boolean useRdfType) { + this.useRdfType = useRdfType; + } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java index a3057f64d..9331e563e 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java @@ -12,8 +12,8 @@ public class JSONLDSerializerFactory { public JSONLDSerializerFactory() { } - public JSONLDSerializer createSerializer(RdfFormat format, Model model) { - return createSerializer(format, model, null); + public JSONLDSerializer createSerializer(Model model) { + return createSerializer(RdfFormat.JSONLD, model, null); } public JSONLDSerializer createSerializer(RdfFormat format, Model model, IOConfig config) { 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 index 4e26ef068..a87732e1f 100644 --- 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 @@ -18,6 +18,9 @@ import java.time.temporal.TemporalAmount; import java.util.*; +/** + * Adapter class from Model to RdfDataset for usage in the JSON-LD serialization process using the titanium library. + */ public class TitaniumRDFDatasetSerializationAdapter implements RdfDataset { private static final Logger logger = LoggerFactory.getLogger(TitaniumRDFDatasetSerializationAdapter.class); @@ -29,7 +32,17 @@ public TitaniumRDFDatasetSerializationAdapter(Model model) { @Override public RdfGraph getDefaultGraph() { - return null; + 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 @@ -58,7 +71,7 @@ public Optional getGraph(RdfResource graphName) { return Optional.of(new RdfGraph() { @Override public boolean contains(RdfTriple triple) { - return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject())); + return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject()), toResource(graphName)); } @Override @@ -99,6 +112,25 @@ public RdfValue getObject() { }; } + 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()); + } + }; + } + private RdfResource toRdfResource(Resource resource) { return () -> { if (resource != null) { From 00eb7481ba644f2ca3992a2d0049343dabfc4991 Mon Sep 17 00:00:00 2001 From: pierrerene Date: Wed, 25 Jun 2025 17:01:43 +0200 Subject: [PATCH 14/31] TurtleParser and turtle g4 --- build.gradle.kts | 58 +++++- .../impl/parser/turtle => antlr}/Turtle.g4 | 0 .../impl/parser/turtle/ANTLRTurtleParser.java | 74 +++++++ .../parser/turtle/TurtleListenerImpl.java | 180 ++++++++++++++++++ .../parser/turtle/TurtleParserFactory.java | 2 +- src/main/java/module-info.java | 1 + .../parser/turtle/ANTLRTurtleParserSpec.java | 30 +++ .../parser/turtle/TurtleListenerImplSpec.java | 99 ++++++++++ 8 files changed, 438 insertions(+), 6 deletions(-) rename src/main/{java/fr/inria/corese/core/next/impl/parser/turtle => antlr}/Turtle.g4 (100%) create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java diff --git a/build.gradle.kts b/build.gradle.kts index f7959310b..dc746d83b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,6 +16,7 @@ plugins { id("com.gradleup.shadow") version "8.3.5" // Bundles dependencies into a single JAR id("org.sonarqube") version "6.0.1.5171" // SonarQube integration id("com.intershop.gradle.javacc") version "5.0.0" // JavaCC plugin for parsing JavaCC files + id("antlr") } // SonarQube configuration @@ -69,11 +70,11 @@ object Meta { // Project description const val desc = "Corese is a Semantic Web Factory (triple store and SPARQL endpoint) implementing RDF, RDFS, SPARQL 1.1 Query and Update, Shacl. STTL. LDScript." const val githubRepo = "corese-stack/corese-core" - + // License information const val license = "CeCILL-C License" const val licenseUrl = "https://opensource.org/licenses/CeCILL-C" - + // Sonatype OSSRH publishing settings const val release = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" const val snapshot = "https://oss.sonatype.org/content/repositories/snapshots/" @@ -104,10 +105,16 @@ repositories { dependencies { val jersey_version = "3.0.4" val semargl_version = "0.7.1" + val antlr_version = "4.13.2" // === Public API (Corese-Core users must see these classes) === api("org.slf4j:slf4j-api:2.0.9") // Exposed: Logging API + // === Antlr + + antlr("org.antlr:antlr4:$antlr_version") + //antlr("org.antlr:antlr4-runtime:$antlr_version") + // === Internal implementations === implementation("fr.com.hp.hpl.jena.rdf.arp:arp:2.2.b") // Exposed: RDF/XML parser implementation("org.apache.commons:commons-text:1.10.0") // Used internally (text manipulation) @@ -122,7 +129,8 @@ dependencies { implementation("fr.inria.corese.org.semarglproject:semargl-core:$semargl_version") // RDF core parser implementation("com.github.jsonld-java:jsonld-java:0.13.4") // Internal JSON-LD parser implementation("com.typesafe:config:1.4.3") // Typesafe config - + implementation("org.antlr:antlr4:$antlr_version") // Antlr for grammar creation + implementation("org.antlr:antlr4-runtime:$antlr_version") // === For tests === testImplementation(platform("org.junit:junit-bom:5.12.2")) // JUnit 5 BOM for dependency management testImplementation("org.junit.jupiter:junit-jupiter") // JUnit 5 for unit testing @@ -133,6 +141,7 @@ dependencies { // === For viewing logs during development (DO NOT include in production) === runtimeOnly("org.slf4j:slf4j-simple:2.0.9") // Simple SLF4J implementation for logging + } // Configure extra Java module information for dependencies without module-info @@ -161,7 +170,7 @@ publishing { // Configure the publication to include JAR, sources, and Javadoc from(components["java"]) - // Configures version mapping to control how dependency versions are resolved + // Configures version mapping to control how dependency versions are resolved // for different usage contexts (API and runtime). versionMapping { // Defines version mapping for Java API usage. @@ -288,7 +297,7 @@ tasks.withType { tasks { shadowJar { this.archiveClassifier = "jar-with-dependencies" - } + } } // Configure Javadoc tasks to disable doclint warnings. @@ -335,3 +344,42 @@ tasks.withType().configureEach { tasks.withType().configureEach { dependsOn(tasks.withType()) } + + + +val generatedSourcesPath = "src/main/generated" +sourceSets["main"].java.srcDir(file(generatedSourcesPath)) + +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) +} + +/* +val copyAntlrGenerated = tasks.register("copyAntlrGenerated") { + dependsOn("generateGrammarSource") + from("$buildDir/generated-src/antlr/main") + into("$generatedSourcesPath/antlr/parser") + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + outputs.dir("$generatedSourcesPath/antlr/parser") +} + */ + + +tasks.named("compileJava") { + dependsOn("generateGrammarSource" /*, "copyAntlrGenerated" */) +} + +tasks.named("sourcesJar") { + dependsOn("generateGrammarSource"/*, "copyAntlrGenerated" */) + from(generatedSourcesPath) + includeEmptyDirs = false +} + + +tasks.clean { + doLast { + file(generatedSourcesPath).deleteRecursively() + } +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 b/src/main/antlr/Turtle.g4 similarity index 100% rename from src/main/java/fr/inria/corese/core/next/impl/parser/turtle/Turtle.g4 rename to src/main/antlr/Turtle.g4 diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java new file mode 100644 index 000000000..875d6c738 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java @@ -0,0 +1,74 @@ +package fr.inria.corese.core.next.impl.parser.turtle; + +import fr.inria.corese.core.next.api.base.parser.RDFParser; +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.impl.parser.antlr.TurtleLexer; +import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.ParseTreeWalker; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +public class ANTLRTurtleParser implements RDFParser { + + private final Model model; + private final RDFFormat format = RDFFormats.TURTLE; + + public ANTLRTurtleParser(Model model) { + this.model = model; + } + + @Override + public RDFFormat getRDFFormat() { + return format; + } + + @Override + public void parse(InputStream in) { + parse(new InputStreamReader(in), null); + } + + @Override + public void parse(InputStream in, String baseURI) { + parse(new InputStreamReader(in), baseURI); + } + + @Override + public void parse(Reader reader) { + parse(reader, null); + } + + /** + * We are using ANTLR4 lexer and parser + * @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 { + CharStream charStream = CharStreams.fromReader(reader); + TurtleLexer lexer = new TurtleLexer(charStream); + CommonTokenStream tokens = new CommonTokenStream(lexer); + TurtleParser parser = new TurtleParser(tokens); + ParseTreeWalker walker = new ParseTreeWalker(); + ParseTree tree = parser.turtleDoc(); + TurtleListenerImpl listener = new TurtleListenerImpl(model, baseURI); + + walker.walk((ParseTreeListener) listener, tree); + + } catch (IOException e) { + throw new RuntimeException("Failed to parse Turtle RDF", e); + } + } +} \ No newline at end of file diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java new file mode 100644 index 000000000..8488f8968 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java @@ -0,0 +1,180 @@ +package fr.inria.corese.core.next.impl.parser.turtle; + +import fr.inria.corese.core.next.api.*; +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; + +public class TurtleListenerImpl extends TurtleBaseListener { + + private final Model model; + private String baseURI; + private final Map prefixMap = new HashMap<>(); + private final ValueFactory factory = new CoreseAdaptedValueFactory(); + + private Resource currentSubject; + private IRI currentPredicate; + + public TurtleListenerImpl(Model model, String baseURI) { + this.model = model; + this.baseURI = baseURI != null ? baseURI : ""; + } + + public void exitPrefixID(TurtleParser.PrefixIDContext ctx) { + String prefix = ctx.PNAME_NS().getText(); + String iri = ctx.IRIREF().getText(); + prefix = prefix.substring(0, prefix.length() - 1); + iri = iri.substring(1, iri.length() - 1); + prefixMap.put(prefix, iri); + + Namespace ns = new ModelNamespace(prefix, iri); + model.setNamespace(prefix, iri); + } + + public void exitSparqlBase(TurtleParser.SparqlBaseContext ctx) { + String iri = ctx.IRIREF().getText(); + baseURI = iri.substring(1, iri.length() - 1); + } + + public void enterTriples(TurtleParser.TriplesContext ctx) { + currentSubject = extractSubject(ctx.subject()); + } + + public void enterVerb(TurtleParser.VerbContext ctx) { + currentPredicate = extractVerb(ctx); + } + + public void exitObject_(TurtleParser.Object_Context ctx) { + Value object = extractObject(ctx); + model.add(currentSubject, currentPredicate, object); + } + + + @Override public void enterEveryRule(ParserRuleContext ctx) {} + + @Override public void exitEveryRule(ParserRuleContext ctx) { } + + @Override public void visitTerminal(TerminalNode node) { } + + @Override public void visitErrorNode(ErrorNode node) { } + + + private String resolveIRI(String raw) { + if (raw.startsWith("<") && raw.endsWith(">")) { + return raw.substring(1, raw.length() - 1); + } else if (raw.equals("a")) { + return RDF.type.getIRI().stringValue(); + } else if (raw.contains(":")) { + // Prefixed name (e.g., ex:predicate) + String[] parts = raw.split(":", 2); + String ns = prefixMap.get(parts[0]); + if (ns != null) { + return ns + parts[1]; + } else { + throw new IllegalArgumentException("Prefix not declared: " + parts[0]); + } + } else { + return baseURI + raw; + } + } + + private String stripQuotes(String text) { + if (text == null || text.length() < 2) return text; + if ((text.startsWith("\"") && text.endsWith("\"")) || + (text.startsWith("'''") && text.endsWith("'''")) || + (text.startsWith("\"\"\"") && text.endsWith("\"\"\""))) { + return text.substring(1, text.length() - 1); + } + return text; + } + + private Literal extractLiteral(TurtleParser.LiteralContext ctx) { + String label; + IRI datatype; + String lang; + + if (ctx.rdfLiteral() != null) { + if (ctx.rdfLiteral().iri() != null) { + datatype = factory.createIRI(resolveIRI(ctx.rdfLiteral().iri().getText())); + label = ctx.rdfLiteral().string().getText(); + return factory.createLiteral(stripQuotes(label), datatype); + } + if (ctx.rdfLiteral().LANGTAG() != null) { + lang = ctx.rdfLiteral().LANGTAG().getText().substring(1); + label = ctx.rdfLiteral().string().getText(); + return factory.createLiteral(stripQuotes(label), lang); + } + label = ctx.rdfLiteral().string().getText(); + return factory.createLiteral(stripQuotes(label)); + } + + if (ctx.BooleanLiteral() != null) { + label = ctx.BooleanLiteral().getText(); + datatype = XSD.BOOLEAN.getIRI(); + return factory.createLiteral(label, datatype); + } + if (ctx.numericLiteral() != null) { + if (ctx.numericLiteral().DECIMAL() != null) { + label = ctx.numericLiteral().DECIMAL().getText(); + datatype = XSD.DECIMAL.getIRI(); + return factory.createLiteral(label, datatype); + } + if (ctx.numericLiteral().DOUBLE() != null) { + label = ctx.numericLiteral().DOUBLE().getText(); + datatype = XSD.DOUBLE.getIRI(); + return factory.createLiteral(label, datatype); + } + if (ctx.numericLiteral().INTEGER() != null) { + label = ctx.numericLiteral().INTEGER().getText(); + datatype = XSD.INTEGER.getIRI(); + return factory.createLiteral(label, datatype); + } + } + throw new IllegalArgumentException("Unsupported literal type: " + ctx.getText()); + } + + private Value extractObject(TurtleParser.Object_Context ctx) { + if (ctx.iri() != null) { + return new CoreseIRI(resolveIRI(ctx.iri().getText())); + } + if (ctx.BlankNode() != null) { + return new CoreseBNode(ctx.BlankNode().getText()); + } + if (ctx.literal() != null) { + return extractLiteral(ctx.literal()); + } + throw new RuntimeException("Unsupported object: " + ctx.getText()); + } + + private Resource extractSubject(TurtleParser.SubjectContext ctx) { + if (ctx.iri() != null) { + return factory.createIRI(resolveIRI(ctx.iri().getText())); + } + if (ctx.BlankNode() != null) { + return factory.createBNode(ctx.BlankNode().getText()); + } + throw new RuntimeException("Unsupported subject: " + ctx.getText()); + } + + private IRI extractPredicate(TurtleParser.PredicateContext ctx) { + return factory.createIRI(resolveIRI(ctx.getText())); + } + + private IRI extractVerb(TurtleParser.VerbContext ctx) { + if (ctx.predicate() != null) { + return extractPredicate(ctx.predicate()); + } + else return factory.createIRI(resolveIRI(ctx.getText())); + } +} \ No newline at end of file diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java index 69be4314f..c20045dab 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java @@ -13,6 +13,6 @@ public RDFParser createRDFParser(RDFFormat format, Model model) { if (!format.equals(RDFFormats.TURTLE)) { throw new IllegalArgumentException("Unsupported format : " + format); } - return new TurtleParser(model); + return new ANTLRTurtleParser(model); } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index da52e9920..9a9b111d2 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -13,6 +13,7 @@ requires org.json; // requires org.apache.commons.lang3; requires org.slf4j; + requires org.antlr.antlr4.runtime; exports fr.inria.corese.core.load; exports fr.inria.corese.core.load.result; diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java b/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java new file mode 100644 index 000000000..3f8724d2d --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java @@ -0,0 +1,30 @@ +package fr.inria.corese.core.next.impl.parser.turtle; + +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.base.parser.RDFParser; +import fr.inria.corese.core.next.impl.temp.CoreseModel; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ANTLRTurtleParserSpec { + private Model parseFromString(String turtleData, String baseURI) throws Exception { + Model model = new CoreseModel(); + RDFParser parser = new ANTLRTurtleParser(model); + parser.parse(new StringReader(turtleData), baseURI); + return model; + } + + @Test + public void testParseWithPrefixAndTriple() throws Exception { + String turtle = " @prefix ex: . " + + "ex:Alice ex:knows ex:Bob ."; + + Model model = parseFromString(turtle, null); + assertEquals(1, model.size()); + assertEquals(1, model.getNamespaces().size()); + } + +} diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java b/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java new file mode 100644 index 000000000..fb85e80b6 --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java @@ -0,0 +1,99 @@ +package fr.inria.corese.core.next.impl.parser.turtle; + +import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; +import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; +import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.impl.temp.CoreseModel; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.tree.ParseTree; +import org.antlr.v4.runtime.tree.ParseTreeListener; +import org.antlr.v4.runtime.tree.ParseTreeWalker; +import org.junit.jupiter.api.Test; + +import java.io.StringReader; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class TurtleListenerImplSpec { + private Model parseAndPrintModel(String turtleData) throws Exception { + CharStream input = CharStreams.fromReader(new StringReader(turtleData)); + TurtleLexer lexer = new TurtleLexer(input); + CommonTokenStream tokens = new CommonTokenStream(lexer); + TurtleParser parser = new TurtleParser(tokens); + ParseTreeWalker walker = new ParseTreeWalker(); + ParseTree tree = parser.turtleDoc(); + + Model model = new CoreseModel(); + TurtleListenerImpl listener = new TurtleListenerImpl(model, null); + walker.walk((ParseTreeListener) listener, tree); + + + model.forEach(stmt -> { + System.out.println(stmt.getSubject().stringValue() + " " + + stmt.getPredicate().stringValue() + " " + + stmt.getObject().stringValue()); + }); + + + return model; + } + + @Test + public void testNamespace() throws Exception { + String turtleData = " @prefix ex: . " + + "ex:subject ex:predicate 1 . "; + + Model model = parseAndPrintModel(turtleData); + assertEquals(model.getNamespaces().size(), 1); + } + + @Test + public void testTypedLiteral() throws Exception { + String turtleData = "@prefix ex: .\n" + + "@prefix xsd: .\n" + + "ex:subject ex:age \"27\"^^xsd:integer ."; + + Model model = parseAndPrintModel(turtleData); + assertEquals(model.size(), 1); + assertEquals(model.getNamespaces().size(), 2); + + } + + @Test + public void testMultipleObjects() throws Exception { + String turtleData = "@prefix ex: .\n" + + "ex:subject ex:knows ex:Alice , ex:Bob ; ex:likes ex:Pizza ."; + + Model model = parseAndPrintModel(turtleData); + assertEquals(model.size(), 3); + assertEquals(model.getNamespaces().size(), 1); + + } + + @Test + public void testRDFtype() throws Exception { + String turtleData = "@prefix ex: .\n" + + "ex:Alice a ex:Person .\n" + + "ex:subject ex:knows ex:Alice , ex:Bob ; ex:likes ex:Pizza ."; + + Model model = parseAndPrintModel(turtleData); + assertEquals(model.size(), 4); + assertEquals(model.getNamespaces().size(), 1); + } + + @Test + public void testBaseIRI() throws Exception { + String turtleData = "@base .\n" + + "@prefix : .\n" + + "@prefix rdf: . \n" + + "\n" + + " rdf:type rdf:Property .\n" + + ":phone rdf:type rdf:Property ."; + + Model model = parseAndPrintModel(turtleData); + assertEquals(model.size(), 2); + assertEquals(model.getNamespaces().size(), 2); + } +} \ No newline at end of file From c9b2f7315ccc7538798604115b76ad8ff3129dbc Mon Sep 17 00:00:00 2001 From: pierrerene Date: Fri, 27 Jun 2025 18:04:39 +0200 Subject: [PATCH 15/31] - changes in the package structure - add factory to listenerImpl --- .../api/base/parser/RDFParserFactory.java | 3 +- .../parser/turtle/ANTLRTurtleParser.java | 9 ++-- .../parser/turtle/TurtleListenerImpl.java | 23 +++------- .../parser/turtle/TurtleParserFactory.java | 11 +++-- .../next/impl/parser/turtle/TurtleParser.java | 46 ------------------- .../parser/turtle/ANTLRTurtleParserSpec.java | 7 ++- .../parser/turtle/TurtleListenerImplSpec.java | 37 +++++++++++++-- 7 files changed, 62 insertions(+), 74 deletions(-) rename src/main/java/fr/inria/corese/core/next/impl/{ => io}/parser/turtle/ANTLRTurtleParser.java (89%) rename src/main/java/fr/inria/corese/core/next/impl/{ => io}/parser/turtle/TurtleListenerImpl.java (90%) rename src/main/java/fr/inria/corese/core/next/impl/{ => io}/parser/turtle/TurtleParserFactory.java (70%) delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java rename src/test/java/fr/inria/corese/core/next/impl/{ => io}/parser/turtle/ANTLRTurtleParserSpec.java (74%) rename src/test/java/fr/inria/corese/core/next/impl/{ => io}/parser/turtle/TurtleListenerImplSpec.java (73%) 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 index 950de673e..9124ee5e8 100644 --- 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 @@ -1,6 +1,7 @@ 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 { @@ -11,6 +12,6 @@ public interface RDFParserFactory { * @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); + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java similarity index 89% rename from src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java rename to src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java index 875d6c738..7fe167569 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParser.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParser.java @@ -1,5 +1,6 @@ -package fr.inria.corese.core.next.impl.parser.turtle; +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.Model; import fr.inria.corese.core.next.api.base.parser.RDFFormat; @@ -23,9 +24,11 @@ public class ANTLRTurtleParser implements RDFParser { private final Model model; private final RDFFormat format = RDFFormats.TURTLE; + private final ValueFactory factory; - public ANTLRTurtleParser(Model model) { + public ANTLRTurtleParser(Model model, ValueFactory factory) { this.model = model; + this.factory = factory; } @Override @@ -63,7 +66,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); + TurtleListenerImpl listener = new TurtleListenerImpl(model, baseURI, factory); walker.walk((ParseTreeListener) listener, tree); diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java similarity index 90% rename from src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java rename to src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java index 8488f8968..ae3f28f95 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImpl.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImpl.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.parser.turtle; +package fr.inria.corese.core.next.impl.io.parser.turtle; import fr.inria.corese.core.next.api.*; import fr.inria.corese.core.next.impl.common.literal.XSD; @@ -21,14 +21,15 @@ public class TurtleListenerImpl extends TurtleBaseListener { private final Model model; private String baseURI; private final Map prefixMap = new HashMap<>(); - private final ValueFactory factory = new CoreseAdaptedValueFactory(); + private final ValueFactory factory; private Resource currentSubject; private IRI currentPredicate; - public TurtleListenerImpl(Model model, String baseURI) { + public TurtleListenerImpl(Model model, String baseURI, ValueFactory factory) { this.model = model; this.baseURI = baseURI != null ? baseURI : ""; + this.factory = factory; } public void exitPrefixID(TurtleParser.PrefixIDContext ctx) { @@ -47,7 +48,7 @@ public void exitSparqlBase(TurtleParser.SparqlBaseContext ctx) { baseURI = iri.substring(1, iri.length() - 1); } - public void enterTriples(TurtleParser.TriplesContext ctx) { + public void enterTriples(TurtleParser.TriplesContext ctx) { currentSubject = extractSubject(ctx.subject()); } @@ -60,16 +61,6 @@ public void exitObject_(TurtleParser.Object_Context ctx) { model.add(currentSubject, currentPredicate, object); } - - @Override public void enterEveryRule(ParserRuleContext ctx) {} - - @Override public void exitEveryRule(ParserRuleContext ctx) { } - - @Override public void visitTerminal(TerminalNode node) { } - - @Override public void visitErrorNode(ErrorNode node) { } - - private String resolveIRI(String raw) { if (raw.startsWith("<") && raw.endsWith(">")) { return raw.substring(1, raw.length() - 1); @@ -146,10 +137,10 @@ private Literal extractLiteral(TurtleParser.LiteralContext ctx) { private Value extractObject(TurtleParser.Object_Context ctx) { if (ctx.iri() != null) { - return new CoreseIRI(resolveIRI(ctx.iri().getText())); + return factory.createIRI(resolveIRI(ctx.iri().getText())); } if (ctx.BlankNode() != null) { - return new CoreseBNode(ctx.BlankNode().getText()); + return factory.createBNode(ctx.BlankNode().getText()); } if (ctx.literal() != null) { return extractLiteral(ctx.literal()); diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java similarity index 70% rename from src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java rename to src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java index c20045dab..1c9a9de66 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParserFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java @@ -1,6 +1,7 @@ -package fr.inria.corese.core.next.impl.parser.turtle; +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; @@ -8,11 +9,15 @@ public class TurtleParserFactory implements RDFParserFactory { + public TurtleParserFactory() { + super(); + } + @Override - public RDFParser createRDFParser(RDFFormat format, Model model) { + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { if (!format.equals(RDFFormats.TURTLE)) { throw new IllegalArgumentException("Unsupported format : " + format); } - return new ANTLRTurtleParser(model); + return new ANTLRTurtleParser(model, factory); } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java b/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java deleted file mode 100644 index bae3779fa..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleParser.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.inria.corese.core.next.impl.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 java.io.InputStream; -import java.io.Reader; - -public class TurtleParser implements RDFParser { - - private final Model model; - private final RDFFormat format = RDFFormats.TURTLE; - - public TurtleParser(Model model) { - this.model = model; - } - - - @Override - public RDFFormat getRDFFormat() { - return format; - } - - @Override - public void parse(InputStream in) { - - } - - @Override - public void parse(InputStream in, String baseURI) { - - } - - @Override - public void parse(Reader reader) { - - } - - @Override - public void parse(Reader reader, String baseURI) { - - } -} diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java similarity index 74% rename from src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java rename to src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java index 3f8724d2d..6d8f12c83 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/ANTLRTurtleParserSpec.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java @@ -1,7 +1,9 @@ -package fr.inria.corese.core.next.impl.parser.turtle; +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.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; @@ -12,7 +14,8 @@ public class ANTLRTurtleParserSpec { private Model parseFromString(String turtleData, String baseURI) throws Exception { Model model = new CoreseModel(); - RDFParser parser = new ANTLRTurtleParser(model); + ValueFactory factory = new CoreseAdaptedValueFactory(); + RDFParser parser = new ANTLRTurtleParser(model, factory); parser.parse(new StringReader(turtleData), baseURI); return model; } diff --git a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java similarity index 73% rename from src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java rename to src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java index fb85e80b6..3f7326452 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/parser/turtle/TurtleListenerImplSpec.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleListenerImplSpec.java @@ -1,8 +1,10 @@ -package fr.inria.corese.core.next.impl.parser.turtle; +package fr.inria.corese.core.next.impl.io.parser.turtle; +import fr.inria.corese.core.next.api.ValueFactory; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; import fr.inria.corese.core.next.impl.temp.CoreseModel; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; @@ -14,10 +16,12 @@ import java.io.StringReader; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; public class TurtleListenerImplSpec { private Model parseAndPrintModel(String turtleData) throws Exception { + ValueFactory factory = new CoreseAdaptedValueFactory(); + CharStream input = CharStreams.fromReader(new StringReader(turtleData)); TurtleLexer lexer = new TurtleLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); @@ -26,16 +30,19 @@ private Model parseAndPrintModel(String turtleData) throws Exception { ParseTree tree = parser.turtleDoc(); Model model = new CoreseModel(); - TurtleListenerImpl listener = new TurtleListenerImpl(model, null); + TurtleListenerImpl listener = new TurtleListenerImpl(model, null, factory); walker.walk((ParseTreeListener) listener, tree); + /* model.forEach(stmt -> { System.out.println(stmt.getSubject().stringValue() + " " + stmt.getPredicate().stringValue() + " " + stmt.getObject().stringValue()); }); + */ + return model; } @@ -96,4 +103,28 @@ public void testBaseIRI() throws Exception { assertEquals(model.size(), 2); assertEquals(model.getNamespaces().size(), 2); } + + @Test + public void testTypedIntegerLiteral() throws Exception { + String turtleData = + "@prefix : .\n" + + "@prefix xsd: .\n" + + ":John :age \"42\"^^xsd:integer ."; + + Model model = parseAndPrintModel(turtleData); + model.objects().forEach(obj -> { + assertTrue(obj.isLiteral(), "Expected object to be a literal"); + // test if we can parse the literal to int. Should be ok + try { + int value = Integer.parseInt(obj.stringValue()); + System.out.println("Parsed integer: " + value); + } catch (NumberFormatException e) { + fail("Literal is not a valid integer: " + obj.stringValue()); + } + }); + + + assertEquals(model.size(), 1); + assertEquals(model.getNamespaces().size(), 2); + } } \ No newline at end of file From 737fe5cb5f28c5fc5d599fa8955dfbe0d4f90010 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 30 Jun 2025 11:07:19 +0200 Subject: [PATCH 16/31] Unifying PR and A implementations --- build.gradle.kts | 7 ++++++- .../io/parser/turtle/ANTLRTurtleParser.java | 19 ++++++++----------- .../io/parser/turtle/TurtleParserFactory.java | 19 +++++++++++++------ .../impl/io/serialization/FormatConfig.java | 2 +- .../parser/turtle/ANTLRTurtleParserSpec.java | 2 +- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8904d7c8f..40ac352ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -118,6 +118,11 @@ dependencies { antlr("org.antlr:antlr4:$antlr_version") //antlr("org.antlr:antlr4-runtime:$antlr_version") + // === JSONLD + implementation("com.apicatalog:titanium-json-ld:1.6.0") + implementation("com.apicatalog:titanium-rdf-api:1.0.0") + implementation("jakarta.json:jakarta.json-api:2.1.3") + // === Internal implementations === implementation("fr.com.hp.hpl.jena.rdf.arp:arp:2.2.b") // Exposed: RDF/XML parser implementation("org.apache.commons:commons-text:1.10.0") // Used internally (text manipulation) @@ -148,7 +153,7 @@ dependencies { // === For viewing logs during development (DO NOT include in production) === runtimeOnly("org.slf4j:slf4j-simple:2.0.9") // Simple SLF4J implementation for logging -} + // === Test dependencies === testImplementation(platform("org.junit:junit-bom:5.12.2")) // JUnit BOM for consistent test versions 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..d228a1632 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.parser.AbstractParser; +import fr.inria.corese.core.next.api.io.parser.RDFParser; 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.base.io.RdfFormat; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; @@ -20,19 +20,16 @@ import java.io.InputStreamReader; import java.io.Reader; -public class ANTLRTurtleParser implements RDFParser { +public class ANTLRTurtleParser extends AbstractParser { - private final Model model; - private final RDFFormat format = RDFFormats.TURTLE; - private final ValueFactory factory; + private final RdfFormat format = RdfFormat.TURTLE; public ANTLRTurtleParser(Model model, ValueFactory factory) { - this.model = model; - this.factory = factory; + super(model, factory); } @Override - public RDFFormat getRDFFormat() { + public RdfFormat getRDFFormat() { return format; } @@ -66,7 +63,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(this.getModel(), baseURI, this.getValueFactory()); walker.walk((ParseTreeListener) listener, tree); 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 index 1c9a9de66..1943fbc35 100644 --- 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 @@ -2,10 +2,10 @@ 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; +import fr.inria.corese.core.next.api.base.io.RdfFormat; +import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.api.io.parser.RDFParser; +import fr.inria.corese.core.next.api.io.parser.RDFParserFactory; public class TurtleParserFactory implements RDFParserFactory { @@ -14,10 +14,17 @@ public TurtleParserFactory() { } @Override - public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { - if (!format.equals(RDFFormats.TURTLE)) { + public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory) { + if (!format.equals(RdfFormat.TURTLE)) { throw new IllegalArgumentException("Unsupported format : " + format); } return new ANTLRTurtleParser(model, factory); } + + @Override + public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory, IOConfig config) { + RDFParser parser = createRDFParser(format, model, factory); + parser.setConfig(config); + return parser; + } } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java index 888b5c3c2..705dc0da1 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java @@ -44,7 +44,7 @@ public static class Builder { * Default constructor for the Builder. * Initializes fields with default values. */ - Builder() { + public Builder() { } 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/ANTLRTurtleParserSpec.java index 6d8f12c83..8d0882c9e 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/ANTLRTurtleParserSpec.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; From af118569731c80d6360f2351414b18a9848395e1 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 30 Jun 2025 16:20:53 +0200 Subject: [PATCH 17/31] UT test with graph probem to solve before push --- build.gradle.kts | 1 + .../impl/io/parser/jsonld/JSONLDParser.java | 12 +- .../io/parser/jsonld/JSONLDParserTest.java | 120 +++++++++--------- 3 files changed, 70 insertions(+), 63 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 40ac352ac..fffb6a89b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -122,6 +122,7 @@ dependencies { implementation("com.apicatalog:titanium-json-ld:1.6.0") implementation("com.apicatalog:titanium-rdf-api:1.0.0") implementation("jakarta.json:jakarta.json-api:2.1.3") + implementation("org.eclipse.parsson:parsson:1.1.7") // === Internal implementations === implementation("fr.com.hp.hpl.jena.rdf.arp:arp:2.2.b") // Exposed: RDF/XML parser 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 index 0f01cac0b..93dc30b33 100644 --- 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 @@ -95,15 +95,19 @@ public RdfQuadConsumer quad(String subject, String predicate, String object, Str // Graph Resource graphResource = null; - if (RdfQuadConsumer.isBlank(graph)) { - graphResource = getValueFactory().createBNode(graph); - } else if(! graph.equals(JSONLD_JAVA_DEFAULT_GRAPH)) { - graphResource = getValueFactory().createIRI(graph); + if(graph != null) { + if (RdfQuadConsumer.isBlank(graph)) { + graphResource = getValueFactory().createBNode(graph); + } else if (!graph.equals(JSONLD_JAVA_DEFAULT_GRAPH)) { + graphResource = getValueFactory().createIRI(graph); + } } if(graphResource == null) { + logger.debug("Adding triple: {} {} {}", subjResource.stringValue(), predicateIRI.stringValue(), objValue.stringValue()); getModel().add(subjResource, predicateIRI, objValue); } else { + logger.debug("Adding quad: {} {} {} {}", subjResource.stringValue(), predicateIRI.stringValue(), objValue.stringValue(), graphResource.stringValue()); getModel().add(subjResource, predicateIRI, objValue, graphResource); } 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 index 609aee582..859589cbe 100644 --- 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 @@ -1,9 +1,6 @@ package fr.inria.corese.core.next.impl.io.parser.jsonld; -import fr.inria.corese.core.next.api.BNode; -import fr.inria.corese.core.next.api.IRI; -import fr.inria.corese.core.next.api.Literal; -import fr.inria.corese.core.next.api.Statement; +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; @@ -12,6 +9,7 @@ import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; +import java.io.Reader; import java.io.StringReader; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -20,10 +18,11 @@ public class JSONLDParserTest { private final ParserFactory factory = new ParserFactory(); + private final ValueFactory valueFactory = new CoreseAdaptedValueFactory(); @Test void testGetRDFFormat() { - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, new CoreseModel(), new CoreseAdaptedValueFactory()); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, new CoreseModel(), valueFactory); assertEquals(RdfFormat.JSONLD, parser.getRDFFormat()); } @@ -48,17 +47,17 @@ public void testParseInputStream() { ] } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); assertEquals(3, model.size()); - IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); - IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); - Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); - Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); - Statement daveNameStatement = new CoreseAdaptedValueFactory().createStatement(subject, namePredicate, nameMarkusObject); + 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)); @@ -86,17 +85,17 @@ public void testParseInputStreamString() { ] } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + 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 = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); - IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); - Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); - Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); - Statement daveNameStatement = new CoreseAdaptedValueFactory().createStatement(subject, namePredicate, nameMarkusObject); + 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)); @@ -124,17 +123,17 @@ public void testParseReader() { ] } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); parser.parse(new StringReader(sampleJsonLD)); assertEquals(3, model.size()); - IRI subject = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); - IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); - Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); - Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); - Statement daveNameStatement = new CoreseAdaptedValueFactory().createStatement(subject, namePredicate, nameMarkusObject); + 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)); @@ -162,17 +161,17 @@ public void testParseReaderString() { ] } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + 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 = new CoreseAdaptedValueFactory().createIRI("http://me.markus-lanthaler.com/"); - IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); - Literal nameMarkusObject = new CoreseAdaptedValueFactory().createLiteral("Markus Lanthaler"); - Literal nameDaveObject = new CoreseAdaptedValueFactory().createLiteral("Dave Longley"); - Statement daveNameStatement = new CoreseAdaptedValueFactory().createStatement(subject, namePredicate, nameMarkusObject); + 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)); @@ -205,14 +204,15 @@ public void testParseJsonLDWithBlankNodes() { } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); - parser.parse(new StringReader(sampleJsonLD)); + 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 = new CoreseAdaptedValueFactory().createBNode("b0"); - BNode b1 = new CoreseAdaptedValueFactory().createBNode("b1"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); + 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)); } @@ -251,25 +251,29 @@ public void testParseJSONLDWithGraphs() { } """; - CoreseModel model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, new CoreseAdaptedValueFactory()); + Model model = new CoreseModel(); + RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); parser.parse(new StringReader(sampleJsonLD)); assertEquals(7, model.size()); - IRI graphIRI = new CoreseAdaptedValueFactory().createIRI("http://example.org/foaf-graph"); - IRI generatedAt = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/ns/prov#generatedAtTime"); - IRI datetimeDatatype = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/2001/XMLSchema#dateTime"); - Literal generatedAtValue = new CoreseAdaptedValueFactory().createLiteral("2012-04-09T00:00:00", datetimeDatatype) ; - IRI manuIRI = new CoreseAdaptedValueFactory().createIRI("http://manu.sporny.org/about#manu"); - Literal manuName = new CoreseAdaptedValueFactory().createLiteral("Manu Sporny"); - IRI greggIRI = new CoreseAdaptedValueFactory().createIRI("https://greggkellogg.net/foaf#me"); - Literal greggName = new CoreseAdaptedValueFactory().createLiteral("Gregg Kellogg"); - IRI typeIRI = new CoreseAdaptedValueFactory().createIRI("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - IRI knowsPredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/knows"); - IRI personType = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/Person"); - IRI namePredicate = new CoreseAdaptedValueFactory().createIRI("http://xmlns.com/foaf/0.1/name"); + 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"); + Statement stat1 = valueFactory.createStatement(graphIRI, generatedAt, generatedAtValue); + Statement stat2 = valueFactory.createStatement(manuIRI, typeIRI, personType, graphIRI); + // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . + assertTrue(model.contains(stat1)); // { // a foaf:Person; assertTrue(model.contains(manuIRI, typeIRI, personType, graphIRI)); @@ -285,7 +289,5 @@ public void testParseJSONLDWithGraphs() { // foaf:knows . assertTrue(model.contains(greggIRI, knowsPredicate, manuIRI, graphIRI)); //} - // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . - assertTrue(model.contains(graphIRI, generatedAt, generatedAtValue)); } } From 21ad8ffdf348aa09312544dbafbdc42eb7a4f11f Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 3 Jul 2025 15:39:38 +0200 Subject: [PATCH 18/31] Fixing Object handling in json parsing --- .../impl/io/parser/jsonld/JSONLDParser.java | 21 +++++----- .../inria/corese/core/producer/DataFrom.java | 5 ++- .../fr/inria/corese/core/util/Property.java | 19 +-------- .../io/parser/jsonld/JSONLDParserTest.java | 39 ++++++++++--------- 4 files changed, 38 insertions(+), 46 deletions(-) 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 index 93dc30b33..16d9dba9a 100644 --- 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 @@ -10,6 +10,7 @@ import fr.inria.corese.core.next.api.base.io.parser.AbstractParser; import fr.inria.corese.core.next.api.base.io.RdfFormat; import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.impl.common.util.IRIUtils; import fr.inria.corese.core.next.impl.exception.ParsingErrorException; import java.io.InputStream; @@ -74,12 +75,11 @@ public RdfQuadConsumer quad(String subject, String predicate, String object, Str // Object Value objValue = null; - if (RdfQuadConsumer.isValidObject(object, datatype, language)) { // Object is a BN if (RdfQuadConsumer.isBlank(object)) { objValue = getValueFactory().createBNode(object); // Object is a Literal - } else if (RdfQuadConsumer.isLiteral(object, datatype, language)) { + } else if (RdfQuadConsumer.isLiteral(datatype, language, direction)) { if (RdfQuadConsumer.isLangString(datatype, language, direction)) { objValue = getValueFactory().createLiteral(object, language); } else if( datatype != null ){ @@ -88,9 +88,10 @@ public RdfQuadConsumer quad(String subject, String predicate, String object, Str objValue = getValueFactory().createLiteral(object); } // Object is a IRI - } else { + } else if(IRIUtils.isStandardIRI(object)) { objValue = getValueFactory().createIRI(object); - } + } else { + throw new RdfConsumerException("Invalid object: " + object); } // Graph @@ -98,18 +99,20 @@ public RdfQuadConsumer quad(String subject, String predicate, String object, Str if(graph != null) { if (RdfQuadConsumer.isBlank(graph)) { graphResource = getValueFactory().createBNode(graph); - } else if (!graph.equals(JSONLD_JAVA_DEFAULT_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) { - logger.debug("Adding triple: {} {} {}", subjResource.stringValue(), predicateIRI.stringValue(), objValue.stringValue()); - getModel().add(subjResource, predicateIRI, objValue); + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue); } else { - logger.debug("Adding quad: {} {} {} {}", subjResource.stringValue(), predicateIRI.stringValue(), objValue.stringValue(), graphResource.stringValue()); - getModel().add(subjResource, predicateIRI, objValue, graphResource); + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue, graphResource); } + getModel().add(statement); return this; } 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/io/parser/jsonld/JSONLDParserTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserTest.java index 859589cbe..5b2c4a59d 100644 --- 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 @@ -7,6 +7,8 @@ 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; @@ -17,6 +19,7 @@ public class JSONLDParserTest { + private static final Logger logger = LoggerFactory.getLogger(JSONLDParserTest.class); private final ParserFactory factory = new ParserFactory(); private final ValueFactory valueFactory = new CoreseAdaptedValueFactory(); @@ -226,8 +229,12 @@ public void testParseJSONLDWithGraphs() { "generatedAt": { "@id": "http://www.w3.org/ns/prov#generatedAtTime" }, - "Person": "http://xmlns.com/foaf/0.1/Person", - "name": "http://xmlns.com/foaf/0.1/name", + "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", @@ -269,25 +276,19 @@ public void testParseJSONLDWithGraphs() { IRI personType = valueFactory.createIRI("http://xmlns.com/foaf/0.1/Person"); IRI namePredicate = valueFactory.createIRI("http://xmlns.com/foaf/0.1/name"); - Statement stat1 = valueFactory.createStatement(graphIRI, generatedAt, generatedAtValue); - Statement stat2 = valueFactory.createStatement(manuIRI, typeIRI, personType, graphIRI); - - // prov:generatedAtTime "2012-04-09T00:00:00"^^xsd:dateTime . - assertTrue(model.contains(stat1)); - // { - // a foaf:Person; - assertTrue(model.contains(manuIRI, typeIRI, personType, graphIRI)); - // foaf:name "Manu Sporny"; - assertTrue(model.contains(manuIRI, namePredicate, manuName, graphIRI)); - // foaf:knows . + // . assertTrue(model.contains(manuIRI, knowsPredicate, greggIRI, graphIRI)); - // - // a foaf:Person; - assertTrue(model.contains(greggIRI, typeIRI, personType, graphIRI)); - // foaf:name "Gregg Kellogg"; + // "Gregg Kellogg" . assertTrue(model.contains(greggIRI, namePredicate, greggName, graphIRI)); - // foaf:knows . + // . 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)); } } From 57d2dcbe2328f313e18c2c5e23b4ce5c35b49b1f Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Fri, 4 Jul 2025 14:41:18 +0200 Subject: [PATCH 19/31] Spring prunning of the package tree and UTs --- .../next/api/base/io/AbstractIOOptions.java | 14 + ...ractParser.java => AbstractRDFParser.java} | 13 +- .../core/next/api/base/parser/RDFFormat.java | 114 -------- .../core/next/api/base/parser/RDFFormats.java | 255 ------------------ .../core/next/api/base/parser/RDFParser.java | 42 --- .../api/base/parser/RDFParserFactory.java | 17 -- .../api/io/{IOConfig.java => IOOptions.java} | 2 +- .../api/io/parser/ParserBaseIRIOptions.java | 7 + .../core/next/api/io/parser/RDFParser.java | 6 +- .../next/api/io/parser/RDFParserFactory.java | 4 +- .../next/api/io/parser/RDFParserOptions.java | 6 + .../serialization/BlankNodePrefixOptions.java | 5 + .../io/TitaniumJSONLDProcessorOptions.java | 142 ++++++++++ .../next/impl/io/parser/ParserFactory.java | 7 +- .../impl/io/parser/jsonld/JSONLDParser.java | 139 +++++----- .../io/parser/jsonld/JSONLDParserConfig.java | 21 -- .../io/parser/turtle/ANTLRTurtleParser.java | 37 ++- .../io/parser/turtle/TurtleParserFactory.java | 23 -- .../impl/io/serialization/FormatConfig.java | 10 +- .../jsonld/JSONLDSerializer.java | 13 +- .../jsonld/JSONLDSerializerConfig.java | 50 ---- .../jsonld/JSONLDSerializerFactory.java | 9 +- .../TitaniumJSONLDProcessorOptionsTest.java | 109 ++++++++ .../parser/turtle/ANTLRTurtleParserSpec.java | 2 +- 24 files changed, 418 insertions(+), 629 deletions(-) create mode 100644 src/main/java/fr/inria/corese/core/next/api/base/io/AbstractIOOptions.java rename src/main/java/fr/inria/corese/core/next/api/base/io/parser/{AbstractParser.java => AbstractRDFParser.java} (74%) delete mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormat.java delete mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFFormats.java delete mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java delete mode 100644 src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParserFactory.java rename src/main/java/fr/inria/corese/core/next/api/io/{IOConfig.java => IOOptions.java} (60%) create mode 100644 src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserOptions.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java create mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/parser/turtle/TurtleParserFactory.java delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java 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..a97c242ce --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/AbstractIOOptions.java @@ -0,0 +1,14 @@ +package fr.inria.corese.core.next.api.base.io; + +import fr.inria.corese.core.next.api.io.IOOptions; + +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/api/base/io/parser/AbstractParser.java b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java similarity index 74% rename from src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java rename to src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java index a2c9a06db..4eb9387c6 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/parser/AbstractRDFParser.java @@ -2,29 +2,28 @@ import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.ValueFactory; -import fr.inria.corese.core.next.api.io.IOConfig; 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; -public abstract class AbstractParser implements RDFParser { +public abstract class AbstractRDFParser implements RDFParser { private final Model model; private final ValueFactory valueFactory; - private IOConfig config; + private RDFParserOptions config; - public IOConfig getConfig() { + public RDFParserOptions getConfig() { return config; } - @Override - public void setConfig(IOConfig config) { + public void setConfig(RDFParserOptions config) { this.config = config; } - protected AbstractParser(Model model, ValueFactory factory) { + protected AbstractRDFParser(Model model, ValueFactory factory) { this.model = model; this.valueFactory = factory; 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/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java deleted file mode 100644 index cf8da275c..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/base/parser/RDFParser.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.inria.corese.core.next.api.base.parser; - -import java.io.InputStream; -import java.io.Reader; - -public interface RDFParser { - - /** - * Gets the RDF format that this parser can parse. - */ - RDFFormat getRDFFormat(); - - /** - * Parses RDF data from the specified InputStream or Reader and adds it to the model. - * - * @param in The InputStream to read RDF data from. - */ - void parse(InputStream in); - - /** - * Parses RDF data from the specified InputStream or Reader and adds it to the model. - * - * @param in The InputStream to read RDF data from. - * @param baseURI The base URI for resolving relative URIs in the RDF data. - */ - void parse(InputStream in, String baseURI); - - /** - * Parses RDF data from the specified InputStream or Reader and adds it to the model. - * - * @param reader The Reader to read RDF data from. - */ - void parse(Reader reader); - - /** - * Parses RDF data from the specified InputStream or Reader and adds it to the model. - * - * @param reader The Reader to read RDF data from. - * @param baseURI The base URI for resolving relative URIs in the RDF data. - */ - void parse(Reader reader, String baseURI); -} 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/IOConfig.java b/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java similarity index 60% rename from src/main/java/fr/inria/corese/core/next/api/io/IOConfig.java rename to src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java index 0c6adbb54..8e56df1a8 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/IOConfig.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java @@ -1,4 +1,4 @@ package fr.inria.corese.core.next.api.io; -public interface IOConfig { +public interface IOOptions { } diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java new file mode 100644 index 000000000..12a4b5550 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java @@ -0,0 +1,7 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.io.IOOptions; + +public interface ParserBaseIRIOptions extends RDFParserOptions, IOOptions { + String getBase(); +} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index 7b7758815..ecf093107 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -1,7 +1,7 @@ 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.IOConfig; +import fr.inria.corese.core.next.api.io.IOOptions; import java.io.InputStream; import java.io.Reader; @@ -13,8 +13,8 @@ public interface RDFParser { */ RdfFormat getRDFFormat(); - public void setConfig(IOConfig config); - public IOConfig getConfig(); + public void setConfig(RDFParserOptions config); + public RDFParserOptions 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/RDFParserFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserFactory.java index cb86b263d..1d8805151 100644 --- 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 @@ -3,7 +3,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.io.RdfFormat; -import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.api.io.IOOptions; public interface RDFParserFactory { @@ -25,6 +25,6 @@ public interface RDFParserFactory { * @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, IOConfig config); + 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..cc65d5d44 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserOptions.java @@ -0,0 +1,6 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.io.IOOptions; + +public interface RDFParserOptions extends IOOptions { +} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java new file mode 100644 index 000000000..f4b751c1a --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java @@ -0,0 +1,5 @@ +package fr.inria.corese.core.next.api.io.serialization; + +public interface BlankNodePrefixOptions { + public String getBlankNodePrefix(); +} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java new file mode 100644 index 000000000..b773ae798 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java @@ -0,0 +1,142 @@ +package fr.inria.corese.core.next.impl.io; + +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.ParserBaseIRIOptions; + +import java.net.URI; +import java.time.Duration; + +/** + * Wrapper around the JsonLdOptions class for the Titanium JSONLD parser and serializer. + * @see JsonLdOptions + */ +public class TitaniumJSONLDProcessorOptions extends AbstractIOOptions implements ParserBaseIRIOptions { + + private final Builder builder; + + protected TitaniumJSONLDProcessorOptions(Builder builder) { + this.builder = builder; + } + + public boolean isCompactArrays() { + return this.builder.options.isCompactArrays(); + } + + public boolean isCompactToRelative() { + return this.builder.options.isCompactToRelative(); + } + + public boolean isExtractAllScripts() { + return this.builder.options.isExtractAllScripts(); + } + + public boolean isOmitDefault() { + return this.builder.options.isOmitDefault(); + } + + public boolean isOmitGraph() { + return this.builder.options.isOmitGraph(); + } + + public boolean isOrdered() { + return this.builder.options.isOrdered(); + } + + public JsonLdVersion getProcessingMode() { + return this.builder.options.getProcessingMode(); + } + + public Duration getTimeout() { + return this.builder.options.getTimeout(); + } + + public boolean isUseNativeTypes() { + return this.builder.options.isUseNativeTypes(); + } + + public boolean isUseRdfType() { + return this.builder.options.isUseRdfType(); + } + + 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 TitaniumJSONLDProcessorOptions build() { + return new TitaniumJSONLDProcessorOptions(this); + } + + public Builder base(String base) { + this.options.setBase(URI.create(base)); + return this; + } + + public Builder base(IRI baseIRI) { + this.options.setBase(URI.create(baseIRI.stringValue())); + return this; + } + + public Builder compactArrays(boolean compactArrays) { + this.options.setCompactArrays(compactArrays); + return this; + } + + public Builder compactToRelative(boolean compactToRelative) { + this.options.setCompactToRelative(compactToRelative); + return this; + } + + public Builder extractAllScripts(boolean extractAllScripts) { + this.options.setExtractAllScripts(extractAllScripts); + return this; + } + + public Builder omitDefault(boolean omitDefault) { + this.options.setOmitDefault(omitDefault); + return this; + } + + public Builder omitGraph(boolean omitGraph) { + this.options.setOmitGraph(omitGraph); + return this; + } + + public Builder ordered(boolean ordered) { + this.options.setOrdered(ordered); + return this; + } + + public Builder timeout(Duration timeout) { + this.options.setTimeout(timeout); + return this; + } + + public Builder useRdfType(boolean useRdfType) { + this.options.setUseRdfType(useRdfType); + return this; + } + + public Builder useNativeTypes(boolean useNativeTypes) { + this.options.setUseNativeTypes(useNativeTypes); + return this; + } + + 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 index 3f99ad1fb..dc308016b 100644 --- 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 @@ -4,9 +4,10 @@ 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.IOConfig; 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; public class ParserFactory extends AbstractRDFParserFactory { @@ -15,9 +16,11 @@ public ParserFactory() { } @Override - public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory, IOConfig config) { + 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); } 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 index 16d9dba9a..1d52ba758 100644 --- 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 @@ -1,22 +1,26 @@ package fr.inria.corese.core.next.impl.io.parser.jsonld; -import com.apicatalog.jsonld.JsonLd; import com.apicatalog.jsonld.JsonLdError; +import com.apicatalog.jsonld.JsonLdOptions; import com.apicatalog.jsonld.document.Document; import com.apicatalog.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.AbstractParser; +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.IOConfig; +import fr.inria.corese.core.next.api.base.io.AbstractIOOptions; +import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; 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.TitaniumJSONLDProcessorOptions; import java.io.InputStream; import java.io.Reader; +import java.net.URI; -public class JSONLDParser extends AbstractParser { +public class JSONLDParser extends AbstractRDFParser { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(JSONLDParser.class); @@ -26,9 +30,9 @@ public JSONLDParser(Model model, ValueFactory factory) { super(model, factory); } - public JSONLDParser(Model model, ValueFactory factory, IOConfig config) { + public JSONLDParser(Model model, ValueFactory factory, RDFParserOptions config) { super(model, factory); - if(config instanceof JSONLDParserConfig) { + if(config instanceof AbstractIOOptions) { setConfig(config); } } @@ -58,65 +62,72 @@ public void parse(Reader reader, String baseURI) { private void parseJSONLDDocument(Document document, String baseURI) { try { - JsonLd.toRdf(document) - .base(baseURI) - .provide(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 != null ){ - 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; + JsonLdOptions options = new JsonLdOptions(); + if(this.getConfig() instanceof TitaniumJSONLDProcessorOptions) { + options = ((TitaniumJSONLDProcessorOptions) this.getConfig()).getJsonLdOptions(); + } + if(baseURI != null && !baseURI.isEmpty()) { + options.setBase(URI.create(baseURI)); + } + RdfQuadConsumer consumer = 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 != null ){ + 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; + } + }; + + ToRdfProcessor.toRdf(consumer, document, options); } catch (JsonLdError e) { throw new ParsingErrorException(e); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java deleted file mode 100644 index 9909f2412..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/io/parser/jsonld/JSONLDParserConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.inria.corese.core.next.impl.io.parser.jsonld; - -import fr.inria.corese.core.next.api.IRI; -import fr.inria.corese.core.next.api.io.IOConfig; - -public class JSONLDParserConfig implements IOConfig { - - private IRI baseIRI = null; - - public JSONLDParserConfig() { - super(); - } - - public void setBaseIRI(IRI baseIRI) { - this.baseIRI = baseIRI; - } - - public IRI getBaseIRI() { - return baseIRI; - } -} 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..a42568585 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.parser.RDFParserOptions; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; @@ -20,20 +20,31 @@ 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; +public class ANTLRTurtleParser extends AbstractRDFParser { public ANTLRTurtleParser(Model model, ValueFactory factory) { - this.model = model; - this.factory = factory; + super(model, factory); + } + + @Override + public RdfFormat getRDFFormat() { + return RdfFormat.TURTLE; } + /** + * @param config we are not using any config in this parser implementation + */ + @Override + public void setConfig(RDFParserOptions config) { + // nothing to do + } + + /** + * @return null, we are not using any config in this parser implementation + */ @Override - public RDFFormat getRDFFormat() { - return format; + public RDFParserOptions getConfig() { + return null; } @Override @@ -66,7 +77,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(), baseURI, getValueFactory()); walker.walk((ParseTreeListener) listener, tree); 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/io/serialization/FormatConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java index 705dc0da1..fa45ba8ce 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/FormatConfig.java @@ -1,6 +1,7 @@ package fr.inria.corese.core.next.impl.io.serialization; -import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.api.base.io.AbstractIOOptions; +import fr.inria.corese.core.next.api.io.serialization.BlankNodePrefixOptions; import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; import java.util.Objects; @@ -9,7 +10,7 @@ * Configuration options for the {@link NTriplesFormat} serializer. * Use {@link FormatConfig # Builder} to create instances. */ -public class FormatConfig implements IOConfig { +public class FormatConfig extends AbstractIOOptions implements BlankNodePrefixOptions { private final String blankNodePrefix; @@ -29,6 +30,7 @@ private FormatConfig(Builder builder) { * * @return The blank node prefix. */ + @Override public String getBlankNodePrefix() { return blankNodePrefix; } @@ -36,7 +38,7 @@ public String getBlankNodePrefix() { /** * Builder class for {@link FormatConfig}. */ - public static class Builder { + public static class Builder extends AbstractIOOptions.Builder { private String blankNodePrefix = "_:"; @@ -45,7 +47,7 @@ public static class Builder { * Initializes fields with default values. */ public Builder() { - + super(); } /** 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 index c59394e1e..13aa11b90 100644 --- 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 @@ -5,6 +5,7 @@ import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.exception.SerializationException; +import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; import java.io.IOException; import java.io.Writer; @@ -16,15 +17,15 @@ public class JSONLDSerializer implements FormatSerializer { private Model model; - private JSONLDSerializerConfig config; + private TitaniumJSONLDProcessorOptions config; - public JSONLDSerializer(Model model, JSONLDSerializerConfig config) { + public JSONLDSerializer(Model model, TitaniumJSONLDProcessorOptions config) { this.model = Objects.requireNonNull(model); this.config = Objects.requireNonNull(config); } public JSONLDSerializer(Model model) { - this(model, new JSONLDSerializerConfig()); + this(model, new TitaniumJSONLDProcessorOptions.Builder().build()); } @Override @@ -33,9 +34,9 @@ public void write(Writer writer) throws SerializationException { try { RdfToJsonld builder = RdfToJsonld.with(adapter) .ordered(this.config.isOrdered()) - .processingMode(this.config.getVersion()) - .useNativeTypes(this.config.usesNativeTypes()) - .useRdfType(this.config.usesRdfType()); + .processingMode(this.config.getProcessingMode()) + .useNativeTypes(this.config.isUseNativeTypes()) + .useRdfType(this.config.isUseRdfType()); jakarta.json.JsonArray jsonArray = builder.build(); writer.write(jsonArray.toString()); } catch (JsonLdError | IOException e) { diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java deleted file mode 100644 index 1e3427013..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerConfig.java +++ /dev/null @@ -1,50 +0,0 @@ -package fr.inria.corese.core.next.impl.io.serialization.jsonld; - -import com.apicatalog.jsonld.JsonLdVersion; -import fr.inria.corese.core.next.api.io.IOConfig; - -public class JSONLDSerializerConfig implements IOConfig { - - private boolean ordered = false; - private JsonLdVersion version = JsonLdVersion.V1_1; - private boolean useNativeTypes = false; - private boolean useRdfType = false; - public JSONLDSerializerConfig() { - } - - public boolean isOrdered() { - return ordered; - } - - public void setOrdered(boolean ordered) { - this.ordered = ordered; - } - - public void setVersionTo10() { - version = JsonLdVersion.V1_0; - } - - public void setVersionTo11() { - version = JsonLdVersion.V1_1; - } - - public JsonLdVersion getVersion() { - return version; - } - - public boolean usesNativeTypes() { - return useNativeTypes; - } - - public void setUseNativeTypes(boolean useNativeTypes) { - this.useNativeTypes = useNativeTypes; - } - - public boolean usesRdfType() { - return useRdfType; - } - - public void setUseRdfType(boolean useRdfType) { - this.useRdfType = useRdfType; - } -} diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java index 9331e563e..f67357e1d 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java @@ -2,7 +2,8 @@ import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.base.io.RdfFormat; -import fr.inria.corese.core.next.api.io.IOConfig; +import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; /** * Placeholder class while waiting for the general serializer factory to be implemented @@ -16,12 +17,12 @@ public JSONLDSerializer createSerializer(Model model) { return createSerializer(RdfFormat.JSONLD, model, null); } - public JSONLDSerializer createSerializer(RdfFormat format, Model model, IOConfig config) { + public JSONLDSerializer createSerializer(RdfFormat format, Model model, IOOptions config) { if(format == RdfFormat.JSONLD) { if(config == null) { return new JSONLDSerializer(model); - } else if(config instanceof JSONLDSerializerConfig) { - return new JSONLDSerializer(model, (JSONLDSerializerConfig) config); + } else if(config instanceof TitaniumJSONLDProcessorOptions) { + return new JSONLDSerializer(model, (TitaniumJSONLDProcessorOptions) config); } else { throw new IllegalArgumentException("Unsupported config for JSONLD serialization: " + config); } diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java new file mode 100644 index 000000000..62f16600a --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java @@ -0,0 +1,109 @@ +package fr.inria.corese.core.next.impl.io; + +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.*; + +class TitaniumJSONLDProcessorOptionsTest { + + private TitaniumJSONLDProcessorOptions optionAllTrue = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().base("http://example.org/AllTrue") + .extractAllScripts(true) + .compactToRelative(true) + .compactArrays(true) + .omitDefault(true) + .omitGraph(true) + .ordered(true) + .useRdfType(true) + .useNativeTypes(true) + ); + + private TitaniumJSONLDProcessorOptions optionAllFalse = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().base("http://example.org/AllFalse") + .extractAllScripts(false) + .compactArrays(false) + .compactToRelative(false) + .omitDefault(false) + .omitGraph(false) + .ordered(false) + .useRdfType(false) + .useNativeTypes(false) + ); + + @Test + void isCompactArrays() { + assertTrue(optionAllTrue.isCompactArrays()); + assertFalse(optionAllFalse.isCompactArrays()); + } + + @Test + void isCompactToRelative() { + assertTrue(optionAllTrue.isCompactToRelative()); + assertFalse(optionAllFalse.isCompactToRelative()); + } + + @Test + void isExtractAllScripts() { + assertTrue(optionAllTrue.isExtractAllScripts()); + assertFalse(optionAllFalse.isExtractAllScripts()); + } + + @Test + void isOmitDefault() { + assertTrue(optionAllTrue.isOmitDefault()); + assertFalse(optionAllFalse.isOmitDefault()); + } + + @Test + void isOmitGraph() { + assertTrue(optionAllTrue.isOmitGraph()); + assertFalse(optionAllFalse.isOmitGraph()); + } + + @Test + void isOrdered() { + assertTrue(optionAllTrue.isOrdered()); + assertFalse(optionAllFalse.isOrdered()); + } + + @Test + void getProcessingMode() { + TitaniumJSONLDProcessorOptions option10 = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().processingMode(JsonLdVersion.V1_0)); + TitaniumJSONLDProcessorOptions option11 = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().processingMode(JsonLdVersion.V1_1)); + assertEquals(JsonLdVersion.V1_0, option10.getProcessingMode()); + assertEquals(JsonLdVersion.V1_1, option11.getProcessingMode()); + } + + @Test + void getTimeout() { + TitaniumJSONLDProcessorOptions option10seconds = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().timeout(Duration.of(10, ChronoUnit.SECONDS))); + assertNull(optionAllTrue.getTimeout()); + assertEquals(Duration.of(10, ChronoUnit.SECONDS), option10seconds.getTimeout()); + } + + @Test + void isUseNativeTypes() { + assertTrue(optionAllTrue.isUseNativeTypes()); + assertFalse(optionAllFalse.isUseNativeTypes()); + } + + @Test + void isUseRdfType() { + assertTrue(optionAllTrue.isUseRdfType()); + assertFalse(optionAllFalse.isUseRdfType()); + } + + @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/turtle/ANTLRTurtleParserSpec.java b/src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/ANTLRTurtleParserSpec.java index 6d8f12c83..8d0882c9e 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/ANTLRTurtleParserSpec.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; From 0915c253a4b5e5175f3ab7bb08f03a41f6034207 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 7 Jul 2025 14:31:51 +0200 Subject: [PATCH 20/31] remove old shex file --- src/test/java/fr/inria/corese/core/shex/TestShex.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/test/java/fr/inria/corese/core/shex/TestShex.java 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 From 924243a7bead5d6f6719a7528aa5f46b4c8b4452 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 7 Jul 2025 16:23:48 +0200 Subject: [PATCH 21/31] Paser with UT --- .../api/base/io/parser/AbstractRDFParser.java | 24 +++- .../corese/core/next/api/io/IOOptions.java | 3 + .../api/io/parser/ParserBaseIRIOptions.java | 7 - .../core/next/api/io/parser/RDFParser.java | 4 +- .../io/parser/RDFParserBaseIRIOptions.java | 12 ++ .../serialization/BlankNodePrefixOptions.java | 6 +- .../exception/SerializationException.java | 6 +- .../io/TitaniumJSONLDProcessorOptions.java | 96 ++++++++++--- .../next/impl/io/parser/ParserFactory.java | 11 ++ .../impl/io/parser/jsonld/JSONLDParser.java | 135 ++++++++++-------- .../io/parser/turtle/ANTLRTurtleParser.java | 11 +- .../TitaniumJSONLDProcessorOptionsTest.java | 19 +-- .../io/parser/jsonld/JSONLDParserTest.java | 25 +++- .../parser/turtle/TurtleListenerImplSpec.java | 13 +- 14 files changed, 241 insertions(+), 131 deletions(-) delete mode 100644 src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java create mode 100644 src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserBaseIRIOptions.java 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 index 4eb9387c6..080992321 100644 --- 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 @@ -2,31 +2,39 @@ 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; public abstract class AbstractRDFParser implements RDFParser { private final Model model; private final ValueFactory valueFactory; - private RDFParserOptions config; + private IOOptions config; - public RDFParserOptions getConfig() { + public IOOptions getConfig() { return config; } - public void setConfig(RDFParserOptions config) { + public void setConfig(IOOptions config) { this.config = config; } protected AbstractRDFParser(Model model, ValueFactory factory) { - this.model = model; - this.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 @@ -39,10 +47,16 @@ public void parse(Reader reader) throws ParsingErrorException { 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/io/IOOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/IOOptions.java index 8e56df1a8..f36446291 100644 --- 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 @@ -1,4 +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/io/parser/ParserBaseIRIOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java deleted file mode 100644 index 12a4b5550..000000000 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/ParserBaseIRIOptions.java +++ /dev/null @@ -1,7 +0,0 @@ -package fr.inria.corese.core.next.api.io.parser; - -import fr.inria.corese.core.next.api.io.IOOptions; - -public interface ParserBaseIRIOptions extends RDFParserOptions, IOOptions { - String getBase(); -} diff --git a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index ecf093107..900ea550d 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -13,8 +13,8 @@ public interface RDFParser { */ RdfFormat getRDFFormat(); - public void setConfig(RDFParserOptions config); - public RDFParserOptions getConfig(); + 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..58e85cae6 --- /dev/null +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParserBaseIRIOptions.java @@ -0,0 +1,12 @@ +package fr.inria.corese.core.next.api.io.parser; + +import fr.inria.corese.core.next.api.io.IOOptions; + +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/serialization/BlankNodePrefixOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java index f4b751c1a..3985cc7a9 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java @@ -1,5 +1,9 @@ package fr.inria.corese.core.next.api.io.serialization; public interface BlankNodePrefixOptions { - public String getBlankNodePrefix(); + + /** + * @return the prefix used for blank nodes ids in the serialization. + */ + String getBlankNodePrefix(); } 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 710ba0c93..95714b9c9 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 @@ -4,11 +4,15 @@ * Exception levée lors d'échecs de sérialisation/désérialisation RDF. * Peut contenir des détails spécifiques au format (NTriples, JSON-LD, etc.). */ -public class SerializationException extends Exception { +public class SerializationException extends RuntimeException { private final String formatName; private final int lineNumber; private final int columnNumber; + public SerializationException(String message, String formatName) { + this(message, formatName, -1, -1, null); + } + public SerializationException(String message, String formatName, Throwable cause) { this(message, formatName, -1, -1, cause); } diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java index b773ae798..55c3ea101 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java @@ -4,7 +4,8 @@ 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.ParserBaseIRIOptions; +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; @@ -13,7 +14,7 @@ * Wrapper around the JsonLdOptions class for the Titanium JSONLD parser and serializer. * @see JsonLdOptions */ -public class TitaniumJSONLDProcessorOptions extends AbstractIOOptions implements ParserBaseIRIOptions { +public class TitaniumJSONLDProcessorOptions extends AbstractIOOptions implements RDFParserOptions, RDFParserBaseIRIOptions { private final Builder builder; @@ -21,46 +22,68 @@ protected TitaniumJSONLDProcessorOptions(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 isCompactArrays() { return this.builder.options.isCompactArrays(); } + /** + * @return if true, the serializer will compact IRIs to be relative to document base. See standard. + */ public boolean isCompactToRelative() { 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 isOmitDefault() { - return this.builder.options.isOmitDefault(); - } - - public boolean isOmitGraph() { - 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 isUseNativeTypes() { return this.builder.options.isUseNativeTypes(); } + /** + * @return If true, the serializer will produce JSON-LD using RDF type. See standard. + */ public boolean isUseRdfType() { return this.builder.options.isUseRdfType(); } + /** + * + * @return the inner JsonLdOptions object. + */ public JsonLdOptions getJsonLdOptions() { return this.builder.options; } @@ -79,61 +102,94 @@ public TitaniumJSONLDProcessorOptions build() { return new TitaniumJSONLDProcessorOptions(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 + */ 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 omitDefault(boolean omitDefault) { - this.options.setOmitDefault(omitDefault); - return this; - } - - public Builder omitGraph(boolean omitGraph) { - this.options.setOmitGraph(omitGraph); - 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 index dc308016b..7a9ddeff1 100644 --- 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 @@ -19,9 +19,20 @@ public ParserFactory() { 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); + } + + @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 index 1d52ba758..6a4d6449a 100644 --- 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 @@ -10,8 +10,7 @@ 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.base.io.AbstractIOOptions; -import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; +import fr.inria.corese.core.next.api.io.IOOptions; 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.TitaniumJSONLDProcessorOptions; @@ -27,14 +26,11 @@ public class JSONLDParser extends AbstractRDFParser { private static final String JSONLD_JAVA_DEFAULT_GRAPH = "@default"; public JSONLDParser(Model model, ValueFactory factory) { - super(model, factory); + super(model, factory, new TitaniumJSONLDProcessorOptions.Builder().build()); } - public JSONLDParser(Model model, ValueFactory factory, RDFParserOptions config) { - super(model, factory); - if(config instanceof AbstractIOOptions) { - setConfig(config); - } + public JSONLDParser(Model model, ValueFactory factory, IOOptions config) { + super(model, factory, config); } @Override @@ -42,6 +38,13 @@ 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) throws ParsingErrorException { try { @@ -51,6 +54,12 @@ public void parse(InputStream in, String baseURI) throws ParsingErrorException { } } + /** + * 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 { @@ -69,67 +78,71 @@ private void parseJSONLDDocument(Document document, String baseURI) { if(baseURI != null && !baseURI.isEmpty()) { options.setBase(URI.create(baseURI)); } - RdfQuadConsumer consumer = 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); - } + RdfQuadConsumer consumer = getConsumer(); - 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 != null ){ - 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); - } + ToRdfProcessor.toRdf(consumer, document, options); + } catch (JsonLdError e) { + throw new ParsingErrorException(e); + } + } - // 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); - } + 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 != null ){ + 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); + } - Statement statement = null; - if(graphResource == null) { - statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue); + // 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 { - statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue, graphResource); + throw new ParsingErrorException("Invalid graph: " + graph); } - getModel().add(statement); + } - return this; + Statement statement = null; + if(graphResource == null) { + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue); + } else { + statement = getValueFactory().createStatement(subjResource, predicateIRI, objValue, graphResource); } - }; + getModel().add(statement); - ToRdfProcessor.toRdf(consumer, document, options); - } catch (JsonLdError e) { - throw new ParsingErrorException(e); - } + 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 a42568585..d29968443 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 @@ -4,6 +4,7 @@ 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.io.IOOptions; import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; @@ -26,6 +27,10 @@ public ANTLRTurtleParser(Model model, ValueFactory factory) { super(model, factory); } + public ANTLRTurtleParser(Model model, ValueFactory factory, IOOptions config) { + super(model, factory, config); + } + @Override public RdfFormat getRDFFormat() { return RdfFormat.TURTLE; @@ -35,7 +40,7 @@ public RdfFormat getRDFFormat() { * @param config we are not using any config in this parser implementation */ @Override - public void setConfig(RDFParserOptions config) { + public void setConfig(IOOptions config) { // nothing to do } @@ -43,7 +48,7 @@ public void setConfig(RDFParserOptions config) { * @return null, we are not using any config in this parser implementation */ @Override - public RDFParserOptions getConfig() { + public IOOptions getConfig() { return null; } @@ -77,7 +82,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(getModel(), baseURI, getValueFactory()); + TurtleListenerImpl listener = new TurtleListenerImpl(getModel(), getValueFactory(), this.getConfig()); walker.walk((ParseTreeListener) listener, tree); diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java index 62f16600a..7c0165ead 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java @@ -8,14 +8,15 @@ import static org.junit.jupiter.api.Assertions.*; +/** + * Tests to check that values are properly set + */ class TitaniumJSONLDProcessorOptionsTest { private TitaniumJSONLDProcessorOptions optionAllTrue = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().base("http://example.org/AllTrue") .extractAllScripts(true) .compactToRelative(true) .compactArrays(true) - .omitDefault(true) - .omitGraph(true) .ordered(true) .useRdfType(true) .useNativeTypes(true) @@ -25,8 +26,6 @@ class TitaniumJSONLDProcessorOptionsTest { .extractAllScripts(false) .compactArrays(false) .compactToRelative(false) - .omitDefault(false) - .omitGraph(false) .ordered(false) .useRdfType(false) .useNativeTypes(false) @@ -50,18 +49,6 @@ void isExtractAllScripts() { assertFalse(optionAllFalse.isExtractAllScripts()); } - @Test - void isOmitDefault() { - assertTrue(optionAllTrue.isOmitDefault()); - assertFalse(optionAllFalse.isOmitDefault()); - } - - @Test - void isOmitGraph() { - assertTrue(optionAllTrue.isOmitGraph()); - assertFalse(optionAllFalse.isOmitGraph()); - } - @Test void isOrdered() { assertTrue(optionAllTrue.isOrdered()); 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 index 5b2c4a59d..5ca02acb1 100644 --- 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 @@ -14,8 +14,7 @@ import java.io.Reader; import java.io.StringReader; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; public class JSONLDParserTest { @@ -24,7 +23,27 @@ public class JSONLDParserTest { private final ValueFactory valueFactory = new CoreseAdaptedValueFactory(); @Test - void testGetRDFFormat() { + 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()); } 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/TurtleListenerImplSpec.java index 3f7326452..31d9bba0a 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/TurtleListenerImplSpec.java @@ -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; } From 170eca8aef3802300dd24c592989ee7ccbbff3b6 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Mon, 7 Jul 2025 17:39:27 +0200 Subject: [PATCH 22/31] jsonld UT init --- .../common/util/SerializationConstants.java | 1 + .../io/parser/turtle/TurtleListenerImpl.java | 18 +-- .../jsonld/JSONLDSerializer.java | 25 ++-- .../jsonld/JSONLDSerializerFactory.java | 34 ----- ...itaniumRDFDatasetSerializationAdapter.java | 121 +++++++++++++++--- .../next/impl/temp/CoreseValueConverter.java | 2 +- .../next/impl/io/CircularJSONLDIOTest.java | 28 ++++ .../jsonld/JSONLDSerializerTest.java | 110 ++++++++++++++++ 8 files changed, 272 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/io/CircularJSONLDIOTest.java create mode 100644 src/test/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerTest.java diff --git a/src/main/java/fr/inria/corese/core/next/impl/common/util/SerializationConstants.java b/src/main/java/fr/inria/corese/core/next/impl/common/util/SerializationConstants.java index 54dfdca54..46f8b88b3 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/common/util/SerializationConstants.java +++ b/src/main/java/fr/inria/corese/core/next/impl/common/util/SerializationConstants.java @@ -73,6 +73,7 @@ public class SerializationConstants { // Nouvelle constante pour le séparateur de datatype public static final String DATATYPE_SEPARATOR = "^^"; + public static final String DEFAULT_GRAPH_IRI = "http://ns.inria.fr/corese/default-graph"; /** * Private constructor to prevent instantiation of this utility class. 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/serialization/jsonld/JSONLDSerializer.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializer.java index 13aa11b90..c55455297 100644 --- 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 @@ -1,8 +1,12 @@ 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 com.apicatalog.jsonld.serialization.RdfToJsonld; import fr.inria.corese.core.next.api.Model; +import fr.inria.corese.core.next.api.io.IOOptions; import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.exception.SerializationException; import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; @@ -17,9 +21,14 @@ public class JSONLDSerializer implements FormatSerializer { private Model model; - private TitaniumJSONLDProcessorOptions config; + private IOOptions config; - public JSONLDSerializer(Model model, TitaniumJSONLDProcessorOptions config) { + /** + * Constructor. + * @param model + * @param config + */ + public JSONLDSerializer(Model model, IOOptions config) { this.model = Objects.requireNonNull(model); this.config = Objects.requireNonNull(config); } @@ -32,12 +41,12 @@ public JSONLDSerializer(Model model) { public void write(Writer writer) throws SerializationException { TitaniumRDFDatasetSerializationAdapter adapter = new TitaniumRDFDatasetSerializationAdapter(model); try { - RdfToJsonld builder = RdfToJsonld.with(adapter) - .ordered(this.config.isOrdered()) - .processingMode(this.config.getProcessingMode()) - .useNativeTypes(this.config.isUseNativeTypes()) - .useRdfType(this.config.isUseRdfType()); - jakarta.json.JsonArray jsonArray = builder.build(); + FromRdfApi fromRdfApi = JsonLd.fromRdf(RdfDocument.of(adapter)); + if(this.config instanceof TitaniumJSONLDProcessorOptions 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/JSONLDSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java deleted file mode 100644 index f67357e1d..000000000 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -package fr.inria.corese.core.next.impl.io.serialization.jsonld; - -import fr.inria.corese.core.next.api.Model; -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.io.TitaniumJSONLDProcessorOptions; - -/** - * Placeholder class while waiting for the general serializer factory to be implemented - */ -public class JSONLDSerializerFactory { - - public JSONLDSerializerFactory() { - } - - public JSONLDSerializer createSerializer(Model model) { - return createSerializer(RdfFormat.JSONLD, model, null); - } - - public JSONLDSerializer createSerializer(RdfFormat format, Model model, IOOptions config) { - if(format == RdfFormat.JSONLD) { - if(config == null) { - return new JSONLDSerializer(model); - } else if(config instanceof TitaniumJSONLDProcessorOptions) { - return new JSONLDSerializer(model, (TitaniumJSONLDProcessorOptions) config); - } else { - throw new IllegalArgumentException("Unsupported config for JSONLD serialization: " + config); - } - } else { - throw new IllegalArgumentException("Unsupported format: " + format); - } - - } -} 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 index a87732e1f..57e085256 100644 --- 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 @@ -4,6 +4,8 @@ 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.XSD; +import fr.inria.corese.core.next.impl.exception.SerializationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,6 +20,8 @@ import java.time.temporal.TemporalAmount; import java.util.*; +import static fr.inria.corese.core.next.impl.common.util.SerializationConstants.DEFAULT_GRAPH_IRI; + /** * Adapter class from Model to RdfDataset for usage in the JSON-LD serialization process using the titanium library. */ @@ -63,7 +67,27 @@ public List toList() { @Override public Set getGraphNames() { - return new HashSet<>(this.model.contexts().stream().map(this::toRdfResource).toList()); + return new HashSet<>(this.model.contexts().stream().map( context -> { + if (context == null) { + return new RdfResource() { + @Override + public boolean isIRI() { + return true; + } + + @Override + public boolean isBlankNode() { + return false; + } + + @Override + public String getValue() { + return DEFAULT_GRAPH_IRI; + } + }; + } + return toRdfResource(context); + }).toList()); } @Override @@ -71,13 +95,21 @@ public Optional getGraph(RdfResource graphName) { return Optional.of(new RdfGraph() { @Override public boolean contains(RdfTriple triple) { - return model.contains(toResource(triple.getSubject()), toIRI(triple.getPredicate()), toValue(triple.getObject()), toResource(graphName)); + 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<>(); - model.getStatements(null, null, null, toResource(graphName)).forEach(statement -> result.add(toRdfNQuad(statement))); + 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; } }); @@ -116,42 +148,99 @@ private RdfTriple toRdfTriple(Statement statement) { return new RdfTriple() { @Override public RdfResource getSubject() { + logger.debug("getSubject: {}", statement.getSubject().stringValue()); return toRdfResource(statement.getSubject()); } @Override public RdfResource getPredicate() { + logger.debug("getPredicate: {}", statement.getPredicate().stringValue()); return toRdfResource(statement.getPredicate()); } @Override public RdfValue getObject() { + logger.debug("getObject: {}", statement.getObject().stringValue()); return toRdfValue(statement.getObject()); } }; } private RdfResource toRdfResource(Resource resource) { - return () -> { - if (resource != null) { + 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(); - } else { - return null; } }; } private RdfValue toRdfValue(Value value) { - if (value.isResource()) { - return toRdfResource((Resource) value); + if (value.isIRI()) { + logger.debug("toRdfValue: {} -> IRI", value.stringValue()); + return toRdfIRI((IRI) value); + } else if (value.isBNode()) { + logger.debug("toRdfValue: {} -> BNode", value.stringValue()); + return toRdfBlankNode((BNode) value); } else if (value.isLiteral()) { + logger.debug("toRdfValue: {} -> Literal", value.stringValue()); return toRdfLiteral((Literal) value); } else { - throw new IllegalArgumentException("Unknown value type"); + throw new SerializationException("Unknown value type " + value.stringValue(), "JSON-LD"); } } + private RdfResource toRdfIRI(IRI iri) { + return new RdfResource() { + @Override + public boolean isIRI() { + return true; + } + @Override + public boolean isBlankNode() { + return false; + } + @Override + public String getValue() { + return iri.stringValue(); + } + }; + } + + private RdfResource toRdfBlankNode(BNode bnode) { + return new RdfResource() { + @Override + public boolean isIRI() { + return false; + } + @Override + public boolean isBlankNode() { + return true; + } + @Override + public String getValue() { + return bnode.stringValue(); + } + }; + } + private RdfLiteral toRdfLiteral(Literal literal) { + logger.debug("toRdfLiteral: {} {} {}", literal.stringValue(), literal.getDatatype().stringValue(), literal.getLanguage()); return new RdfLiteral() { @Override public String getValue() { @@ -160,7 +249,7 @@ public String getValue() { @Override public String getDatatype() { - if (literal.getDatatype() != null) { + if (literal.getDatatype() != null && !literal.getDatatype().equals(XSD.xsdString.getIRI())) { return literal.getDatatype().stringValue(); } else { return ""; @@ -182,7 +271,7 @@ private Value toValue(RdfValue value) { } else if (value.isBlankNode()) { return toBNode((RdfResource) value); } else { - throw new IllegalArgumentException("Unknown value type"); + throw new SerializationException("Unknown value type " + value.getValue(), "JSON-LD"); } } @@ -192,7 +281,7 @@ private Resource toResource(RdfResource resource) { } else if (resource.isBlankNode()) { return toBNode(resource); } else { - throw new IllegalArgumentException("Unknown resource type"); + throw new SerializationException("Unknown resource type " + resource.getValue(), "JSON-LD"); } } @@ -221,6 +310,7 @@ public String getID() { } private Literal toLiteral(RdfLiteral literal) { + logger.debug("Converting literal: {}", literal); return new Literal() { @Override public String stringValue() { @@ -302,9 +392,8 @@ public XMLGregorianCalendar calendarValue() { try { return DatatypeFactory.newInstance().newXMLGregorianCalendar(literal.getValue()); } catch (DatatypeConfigurationException e) { - logger.error("Literal couldn't be converted to XMLGregorianCalendar", e); + throw new SerializationException("Literal couldn't be converted to XMLGregorianCalendar", "JSON-LD", e); } - return null; } @Override @@ -316,7 +405,7 @@ public CoreDatatype getCoreDatatype() { private IRI stringToIRI(String iri) { if (iri == null || !IRIUtils.isStandardIRI(iri)) { - return null; + throw new SerializationException("Invalid IRI: " + iri, "JSON-LD"); } return new IRI() { @Override 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/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/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..0cf5a58ad --- /dev/null +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/jsonld/JSONLDSerializerTest.java @@ -0,0 +1,110 @@ +package fr.inria.corese.core.next.impl.io.serialization.jsonld; + +import fr.inria.corese.core.next.api.*; +import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; +import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; +import fr.inria.corese.core.next.impl.temp.CoreseModel; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +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(); + } + + @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); + + FormatSerializer serializer = new JSONLDSerializer(this.model); + + StringWriter writer = new StringWriter(); + serializer.write(writer); + String result = writer.toString(); + + String expectedResult= "[\n" + + " {\n" + + " \"@id\": \"http://example.org/iri1\",\n" + + " \"http://example.org/pred1\": [\n" + + " {\n" + + " \"@id\": \"http://example.org/iri1\"\n" + + " },\n" + + " {\n" + + " \"@type\": \"http://example.org/datatype1\",\n" + + " \"@value\": \"literal2\"\n" + + " },\n" + + " {\n" + + " \"@value\": \"literal1\"\n" + + " },\n" + + " {\n" + + " \"@language\": \"en\",\n" + + " \"@value\": \"literal3\"\n" + + " }\n" + + " ]\n" + + " }\n" + + "]"; + assertEquals(expectedResult.replace('\n', ' ').replaceAll("\\s+", ""), result, "The result should be a JSON object"); + } + + @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); + + FormatSerializer serializer = new JSONLDSerializer(this.model); + + StringWriter writer = new StringWriter(); + serializer.write(writer); + String result = writer.toString(); + assertEquals("{}", result, "The result should be an empty JSON object"); + } + + @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); + + FormatSerializer serializer = new JSONLDSerializer(this.model); + + StringWriter writer = new StringWriter(); + serializer.write(writer); + String result = writer.toString(); + assertEquals("{}", result, "The result should be an empty JSON object"); + } +} \ No newline at end of file From 11b6e4d6cede4829d9b17da34f7999834318e7a3 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 9 Jul 2025 11:13:51 +0200 Subject: [PATCH 23/31] fix my personal page --- .sonarlint/connectedMode.json | 4 ++++ build.gradle.kts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .sonarlint/connectedMode.json diff --git a/.sonarlint/connectedMode.json b/.sonarlint/connectedMode.json new file mode 100644 index 000000000..f19bbef82 --- /dev/null +++ b/.sonarlint/connectedMode.json @@ -0,0 +1,4 @@ +{ + "sonarQubeUri": "https://sonarqube.inria.fr/sonarqube", + "projectKey": "corese" +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index f41762fef..0e925e654 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -209,7 +209,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/") } From e4b1fb9a3d22a252272d5de37f12620b24af60a9 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 9 Jul 2025 11:14:51 +0200 Subject: [PATCH 24/31] refining json serializer --- .../io/TitaniumJSONLDProcessorOptions.java | 28 ++++++++-- ...itaniumRDFDatasetSerializationAdapter.java | 53 ++++++++----------- .../TitaniumJSONLDProcessorOptionsTest.java | 16 +++--- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java index 55c3ea101..f61be9313 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java @@ -25,14 +25,14 @@ protected TitaniumJSONLDProcessorOptions(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 isCompactArrays() { + 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 isCompactToRelative() { + public boolean compactsToRelative() { return this.builder.options.isCompactToRelative(); } @@ -43,6 +43,14 @@ 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. @@ -69,14 +77,14 @@ public Duration getTimeout() { /** * @return If true, the serializer will produce JSON-LD using native types. See standard. */ - public boolean isUseNativeTypes() { + public boolean usesNativeTypes() { return this.builder.options.isUseNativeTypes(); } /** * @return If true, the serializer will produce JSON-LD using RDF type. See standard. */ - public boolean isUseRdfType() { + public boolean usesRdfType() { return this.builder.options.isUseRdfType(); } @@ -132,7 +140,7 @@ public Builder compactArrays(boolean compactArrays) { /** * @param compactToRelative if true, compact IRIs to be relative to document base. - * @return + * @return this builder */ public Builder compactToRelative(boolean compactToRelative) { this.options.setCompactToRelative(compactToRelative); @@ -148,6 +156,16 @@ public Builder extractAllScripts(boolean 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. 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 index 57e085256..bb0b0010c 100644 --- 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 @@ -4,6 +4,7 @@ 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; @@ -67,27 +68,13 @@ public List toList() { @Override public Set getGraphNames() { - return new HashSet<>(this.model.contexts().stream().map( context -> { - if (context == null) { - return new RdfResource() { - @Override - public boolean isIRI() { - return true; - } - - @Override - public boolean isBlankNode() { - return false; - } - - @Override - public String getValue() { - return DEFAULT_GRAPH_IRI; - } - }; - } - return toRdfResource(context); - }).toList()); + HashSet result = new HashSet<>(); + this.model.contexts().forEach(context -> { + if(context != null) { + result.add(toRdfResource(context)); + } + }); + return result; } @Override @@ -212,10 +199,6 @@ public boolean isIRI() { return true; } @Override - public boolean isBlankNode() { - return false; - } - @Override public String getValue() { return iri.stringValue(); } @@ -224,10 +207,6 @@ public String getValue() { private RdfResource toRdfBlankNode(BNode bnode) { return new RdfResource() { - @Override - public boolean isIRI() { - return false; - } @Override public boolean isBlankNode() { return true; @@ -242,6 +221,11 @@ public String getValue() { private RdfLiteral toRdfLiteral(Literal literal) { logger.debug("toRdfLiteral: {} {} {}", literal.stringValue(), literal.getDatatype().stringValue(), literal.getLanguage()); return new RdfLiteral() { + @Override + public boolean isLiteral() { + return true; + } + @Override public String getValue() { return literal.getLabel(); @@ -249,10 +233,17 @@ public String getValue() { @Override public String getDatatype() { - if (literal.getDatatype() != null && !literal.getDatatype().equals(XSD.xsdString.getIRI())) { + 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 ""; + return XSD.xsdString.getIRI().stringValue(); } } diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java index 7c0165ead..f3f983563 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java @@ -33,14 +33,14 @@ class TitaniumJSONLDProcessorOptionsTest { @Test void isCompactArrays() { - assertTrue(optionAllTrue.isCompactArrays()); - assertFalse(optionAllFalse.isCompactArrays()); + assertTrue(optionAllTrue.compactsArrays()); + assertFalse(optionAllFalse.compactsArrays()); } @Test void isCompactToRelative() { - assertTrue(optionAllTrue.isCompactToRelative()); - assertFalse(optionAllFalse.isCompactToRelative()); + assertTrue(optionAllTrue.compactsToRelative()); + assertFalse(optionAllFalse.compactsToRelative()); } @Test @@ -72,14 +72,14 @@ void getTimeout() { @Test void isUseNativeTypes() { - assertTrue(optionAllTrue.isUseNativeTypes()); - assertFalse(optionAllFalse.isUseNativeTypes()); + assertTrue(optionAllTrue.usesNativeTypes()); + assertFalse(optionAllFalse.usesNativeTypes()); } @Test void isUseRdfType() { - assertTrue(optionAllTrue.isUseRdfType()); - assertFalse(optionAllFalse.isUseRdfType()); + assertTrue(optionAllTrue.usesRdfType()); + assertFalse(optionAllFalse.usesRdfType()); } @Test From 99e5e342356aa4f6539031db7c6716258545638a Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 9 Jul 2025 17:24:18 +0200 Subject: [PATCH 25/31] Fixed Typed Literal bug --- .../impl/io/parser/jsonld/JSONLDParser.java | 3 +- .../jsonld/JSONLDSerializer.java | 2 +- .../next/impl/temp/literal/CoreseTyped.java | 36 ++-- .../jsonld/JSONLDSerializerTest.java | 164 +++++++++++++++--- ...reseTypeTest.java => CoreseTypedTest.java} | 3 +- 5 files changed, 157 insertions(+), 51 deletions(-) rename src/test/java/fr/inria/corese/core/next/impl/temp/literal/{CoreseTypeTest.java => CoreseTypedTest.java} (98%) 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 index 6a4d6449a..bb7c320fe 100644 --- 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 @@ -11,6 +11,7 @@ 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.TitaniumJSONLDProcessorOptions; @@ -109,7 +110,7 @@ public RdfQuadConsumer quad(String subject, String predicate, String object, Str } else if (RdfQuadConsumer.isLiteral(datatype, language, direction)) { if (RdfQuadConsumer.isLangString(datatype, language, direction)) { objValue = getValueFactory().createLiteral(object, language); - } else if( datatype != null ){ + } else if( ! datatype.equals(XSD.STRING.toString()) ){ objValue = getValueFactory().createLiteral(object, getValueFactory().createIRI(datatype)); } else { objValue = getValueFactory().createLiteral(object); 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 index c55455297..9389a71ca 100644 --- 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 @@ -4,7 +4,6 @@ import com.apicatalog.jsonld.JsonLdError; import com.apicatalog.jsonld.api.FromRdfApi; import com.apicatalog.jsonld.document.RdfDocument; -import com.apicatalog.jsonld.serialization.RdfToJsonld; import fr.inria.corese.core.next.api.Model; import fr.inria.corese.core.next.api.io.IOOptions; import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; @@ -40,6 +39,7 @@ public JSONLDSerializer(Model model) { @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 TitaniumJSONLDProcessorOptions options) { 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/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 index 0cf5a58ad..04f91d7f5 100644 --- 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 @@ -1,12 +1,19 @@ 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.FormatSerializer; +import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; 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.*; @@ -40,34 +47,44 @@ public void smallModelTest() { // IRI IRI LangLiteral this.model.add(iriNode, iriPred, langLiteral); - FormatSerializer serializer = new JSONLDSerializer(this.model); + FormatSerializer serializer = new JSONLDSerializer(this.model, (new TitaniumJSONLDProcessorOptions.Builder()).ordered(true).build()); StringWriter writer = new StringWriter(); + serializer.write(writer); String result = writer.toString(); - String expectedResult= "[\n" + - " {\n" + - " \"@id\": \"http://example.org/iri1\",\n" + - " \"http://example.org/pred1\": [\n" + - " {\n" + - " \"@id\": \"http://example.org/iri1\"\n" + - " },\n" + - " {\n" + - " \"@type\": \"http://example.org/datatype1\",\n" + - " \"@value\": \"literal2\"\n" + - " },\n" + - " {\n" + - " \"@value\": \"literal1\"\n" + - " },\n" + - " {\n" + - " \"@language\": \"en\",\n" + - " \"@value\": \"literal3\"\n" + - " }\n" + - " ]\n" + - " }\n" + - "]"; - assertEquals(expectedResult.replace('\n', ' ').replaceAll("\\s+", ""), result, "The result should be a JSON object"); + 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 @@ -86,7 +103,39 @@ public void modelWithBlankNodesTest() { StringWriter writer = new StringWriter(); serializer.write(writer); String result = writer.toString(); - assertEquals("{}", result, "The result should be an empty JSON object"); + + 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 @@ -105,6 +154,71 @@ public void modelWithNamedGraphsTest() { StringWriter writer = new StringWriter(); serializer.write(writer); String result = writer.toString(); - assertEquals("{}", result, "The result should be an empty JSON object"); + + 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/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; From 9a3594511cea73f359a0bbdd36a40c220e3b0d14 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 10 Jul 2025 11:02:58 +0200 Subject: [PATCH 26/31] fixing Exception heritage --- .../core/next/impl/exception/ParsingErrorException.java | 4 +++- .../core/next/impl/exception/SerializationException.java | 4 +++- .../next/impl/exception/UnsupportedFileFormatException.java | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) 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..9c05f646f 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,8 @@ package fr.inria.corese.core.next.impl.exception; -public class ParsingErrorException extends RuntimeException { +import fr.inria.corese.core.sparql.exceptions.CoreseException; + +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 cb00159ab..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,11 +1,13 @@ 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 RuntimeException { +public class SerializationException extends CoreseException { private final String formatName; private final int lineNumber; private final int columnNumber; 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..2521fa74c 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,8 @@ package fr.inria.corese.core.next.impl.exception; -public class UnsupportedFileFormatException extends Exception { +import fr.inria.corese.core.next.api.base.exception.CoreseException; + +public class UnsupportedFileFormatException extends CoreseException { private static final long serialVersionUID = 7963163989802143570L; From 0f9221d0128cdaf441c3ebd910136ced96bafb62 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 10 Jul 2025 11:46:46 +0200 Subject: [PATCH 27/31] Reorganizing and standardizing classes and packages --- .../io/{RdfFormat.java => RDFFormat.java} | 26 +-- .../api/base/io/parser/AbstractRDFParser.java | 4 +- .../io/parser/AbstractRDFParserFactory.java | 4 +- .../core/next/api/io/parser/RDFParser.java | 4 +- .../next/api/io/parser/RDFParserFactory.java | 7 +- .../serialization/RDFSerializer.java} | 7 +- ...java => RDFSerializerBNPrefixOptions.java} | 2 +- .../serialization}/SerializationConfig.java | 2 +- .../serialization}/SerializerFactory.java | 11 +- .../impl/exception/ParsingErrorException.java | 3 +- .../next/impl/io/parser/ParserFactory.java | 14 +- .../impl/io/parser/jsonld/JSONLDParser.java | 16 +- .../io/parser/turtle/ANTLRTurtleParser.java | 7 +- .../DefaultSerializerFactory.java | 77 ++++--- .../base/AbstractGraphSerializer.java | 97 ++++----- .../base/AbstractLineBasedSerializer.java | 18 +- .../jsonld/JSONLDSerializer.java | 10 +- ...itaniumRDFDatasetSerializationAdapter.java | 2 +- .../serialization/nquads/NQuadsOption.java} | 24 ++- .../nquads}/NQuadsSerializer.java | 16 +- .../ntriples/NTriplesOption.java} | 28 +-- .../ntriples}/NTriplesSerializer.java | 14 +- .../option/AbstractNFamilyOption.java} | 18 +- .../option/AbstractSerializerOption.java} | 16 +- .../option/AbstractTFamilyOption.java} | 20 +- .../option}/BlankNodeStyleEnum.java | 2 +- .../option}/LiteralDatatypePolicyEnum.java | 2 +- .../option}/PrefixOrderingEnum.java | 2 +- .../TitaniumJSONLDProcessorOption.java} | 12 +- .../serialization/rdfxml/XmlOption.java} | 25 ++- .../serialization/rdfxml}/XmlSerializer.java | 22 +- .../serialization/trig/TriGOption.java} | 30 +-- .../serialization/trig}/TriGSerializer.java | 27 ++- .../serialization/turtle/TurtleOption.java} | 30 +-- .../turtle}/TurtleSerializer.java | 21 +- .../util/SerializationConstants.java | 4 +- ...{RdfFormatTest.java => RDFFormatTest.java} | 100 ++++----- .../DefaultSerializerFactoryTest.java | 31 +-- .../serialization/NQuadsSerializerTest.java | 67 +----- .../serialization/NTriplesSerializerTest.java | 204 +----------------- .../serialization/TriGSerializerTest.java | 23 +- .../serialization/TurtleSerializerTest.java | 23 +- .../serialization/XmlSerializerTest.java | 41 ++-- .../config/NQuadsConfigTest.java | 28 +-- .../config/NTriplesConfigTest.java | 28 +-- .../serialization/config/TriGConfigTest.java | 58 ++--- .../config/TurtleConfigTest.java | 58 ++--- .../serialization/config/XmlConfigTest.java | 49 +++-- ...=> TitaniumJSONLDProcessorOptionTest.java} | 17 +- .../io/parser/jsonld/JSONLDParserTest.java | 18 +- .../jsonld/JSONLDSerializerTest.java | 10 +- .../nquads/NQuadsFormatTest.java | 67 +----- .../ntriples/NTriplesFormatTest.java | 203 +---------------- 53 files changed, 609 insertions(+), 1040 deletions(-) rename src/main/java/fr/inria/corese/core/next/api/base/io/{RdfFormat.java => RDFFormat.java} (88%) rename src/main/java/fr/inria/corese/core/next/api/{RdfSerializer.java => io/serialization/RDFSerializer.java} (85%) rename src/main/java/fr/inria/corese/core/next/api/io/serialization/{BlankNodePrefixOptions.java => RDFSerializerBNPrefixOptions.java} (79%) rename src/main/java/fr/inria/corese/core/next/api/{ => io/serialization}/SerializationConfig.java (89%) rename src/main/java/fr/inria/corese/core/next/api/{ => io/serialization}/SerializerFactory.java (56%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/DefaultSerializerFactory.java (56%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/base/AbstractGraphSerializer.java (91%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/base/AbstractLineBasedSerializer.java (96%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/NQuadsConfig.java => io/serialization/nquads/NQuadsOption.java} (70%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/nquads}/NQuadsSerializer.java (82%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/NTriplesConfig.java => io/serialization/ntriples/NTriplesOption.java} (66%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/ntriples}/NTriplesSerializer.java (85%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/AbstractNFamilyConfig.java => io/serialization/option/AbstractNFamilyOption.java} (80%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/AbstractSerializerConfig.java => io/serialization/option/AbstractSerializerOption.java} (95%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/AbstractTFamilyConfig.java => io/serialization/option/AbstractTFamilyOption.java} (96%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config => io/serialization/option}/BlankNodeStyleEnum.java (82%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config => io/serialization/option}/LiteralDatatypePolicyEnum.java (86%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config => io/serialization/option}/PrefixOrderingEnum.java (86%) rename src/main/java/fr/inria/corese/core/next/impl/io/{TitaniumJSONLDProcessorOptions.java => serialization/option/TitaniumJSONLDProcessorOption.java} (94%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/XmlConfig.java => io/serialization/rdfxml/XmlOption.java} (93%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/rdfxml}/XmlSerializer.java (96%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/TriGConfig.java => io/serialization/trig/TriGOption.java} (69%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/trig}/TriGSerializer.java (93%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization/config/TurtleConfig.java => io/serialization/turtle/TurtleOption.java} (69%) rename src/main/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/turtle}/TurtleSerializer.java (90%) rename src/main/java/fr/inria/corese/core/next/impl/{common => io}/serialization/util/SerializationConstants.java (96%) rename src/test/java/fr/inria/corese/core/next/api/base/io/{RdfFormatTest.java => RDFFormatTest.java} (59%) rename src/test/java/fr/inria/corese/core/next/impl/io/{TitaniumJSONLDProcessorOptionsTest.java => TitaniumJSONLDProcessorOptionTest.java} (71%) diff --git a/src/main/java/fr/inria/corese/core/next/api/base/io/RdfFormat.java b/src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java similarity index 88% rename from src/main/java/fr/inria/corese/core/next/api/base/io/RdfFormat.java rename to src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java index 49739c7f9..bcd84f5a6 100644 --- a/src/main/java/fr/inria/corese/core/next/api/base/io/RdfFormat.java +++ b/src/main/java/fr/inria/corese/core/next/api/base/io/RDFFormat.java @@ -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 index 080992321..0ed5dd3e7 100644 --- 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 @@ -38,12 +38,12 @@ protected AbstractRDFParser(Model model, ValueFactory factory, IOOptions config) } @Override - public void parse(InputStream in) throws ParsingErrorException { + public void parse(InputStream in) { parse(in, null); } @Override - public void parse(Reader reader) throws ParsingErrorException { + public void parse(Reader reader) { parse(reader, null); } 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 index d8dcbf76f..adc0e2702 100644 --- 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 @@ -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.io.RdfFormat; +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; @@ -12,7 +12,7 @@ protected AbstractRDFParserFactory() { } @Override - public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory) { + 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/io/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index 900ea550d..34c851c57 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -1,6 +1,6 @@ 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.base.io.RDFFormat; import fr.inria.corese.core.next.api.io.IOOptions; import java.io.InputStream; @@ -11,7 +11,7 @@ public interface RDFParser { /** * Gets the RDF format that this parser can parse. */ - RdfFormat getRDFFormat(); + RDFFormat getRDFFormat(); void setConfig(IOOptions config); IOOptions getConfig(); 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 index 1d8805151..5c5d7596e 100644 --- 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 @@ -2,8 +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.io.RdfFormat; -import fr.inria.corese.core.next.api.io.IOOptions; +import fr.inria.corese.core.next.api.base.io.RDFFormat; public interface RDFParserFactory { @@ -15,7 +14,7 @@ public interface RDFParserFactory { * @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); + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory); /** * Creates a new RDF parser for the specified format and model. @@ -25,6 +24,6 @@ public interface RDFParserFactory { * @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); + RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory, RDFParserOptions config); } 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 85% 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..bc08a5592 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,11 +1,12 @@ -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.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 @@ -14,7 +15,7 @@ * 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/BlankNodePrefixOptions.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java similarity index 79% rename from src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java index 3985cc7a9..cb9ffff92 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/serialization/BlankNodePrefixOptions.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializerBNPrefixOptions.java @@ -1,6 +1,6 @@ package fr.inria.corese.core.next.api.io.serialization; -public interface BlankNodePrefixOptions { +public interface RDFSerializerBNPrefixOptions { /** * @return the prefix used for blank nodes ids in the serialization. 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/SerializationConfig.java similarity index 89% 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/SerializationConfig.java index 47b9f8cbe..982bf8e41 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/SerializationConfig.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.api; +package fr.inria.corese.core.next.api.io.serialization; /** diff --git a/src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java similarity index 56% rename from src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java index b30177181..b049c6419 100644 --- a/src/main/java/fr/inria/corese/core/next/api/SerializerFactory.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializerFactory.java @@ -1,12 +1,13 @@ -package fr.inria.corese.core.next.api; +package fr.inria.corese.core.next.api.io.serialization; -import fr.inria.corese.core.next.impl.common.serialization.RdfFormat; +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. + * 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 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 @@ -15,5 +16,5 @@ public interface SerializerFactory { - RdfSerializer createSerializer(RdfFormat format, Model model, SerializationConfig config); + RDFSerializer createSerializer(RDFFormat format, Model model, SerializationConfig config); } 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 9c05f646f..8eded6714 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,7 @@ package fr.inria.corese.core.next.impl.exception; -import fr.inria.corese.core.sparql.exceptions.CoreseException; + +import fr.inria.corese.core.next.api.base.exception.CoreseException; public class ParsingErrorException extends CoreseException { 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 index 7a9ddeff1..25507e24c 100644 --- 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 @@ -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.io.RdfFormat; +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; @@ -16,20 +16,20 @@ public ParserFactory() { } @Override - public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory, RDFParserOptions config) { - if(format == RdfFormat.JSONLD) { + 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) { + } else if(format == RDFFormat.TURTLE) { return new ANTLRTurtleParser(model, factory, config); } throw new IllegalArgumentException("Unsupported format: " + format); } @Override - public RDFParser createRDFParser(RdfFormat format, Model model, ValueFactory factory) { - if(format == RdfFormat.JSONLD) { + public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory factory) { + if(format == RDFFormat.JSONLD) { return new JSONLDParser(model, factory); - } else if(format == RdfFormat.TURTLE) { + } 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 index bb7c320fe..4a344f969 100644 --- 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 @@ -9,12 +9,12 @@ 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.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.TitaniumJSONLDProcessorOptions; +import fr.inria.corese.core.next.impl.io.serialization.option.TitaniumJSONLDProcessorOption; import java.io.InputStream; import java.io.Reader; @@ -27,7 +27,7 @@ public class JSONLDParser extends AbstractRDFParser { private static final String JSONLD_JAVA_DEFAULT_GRAPH = "@default"; public JSONLDParser(Model model, ValueFactory factory) { - super(model, factory, new TitaniumJSONLDProcessorOptions.Builder().build()); + super(model, factory, new TitaniumJSONLDProcessorOption.Builder().build()); } public JSONLDParser(Model model, ValueFactory factory, IOOptions config) { @@ -35,8 +35,8 @@ public JSONLDParser(Model model, ValueFactory factory, IOOptions config) { } @Override - public RdfFormat getRDFFormat() { - return RdfFormat.JSONLD; + public RDFFormat getRDFFormat() { + return RDFFormat.JSONLD; } /** @@ -47,7 +47,7 @@ public RdfFormat getRDFFormat() { * @throws ParsingErrorException */ @Override - public void parse(InputStream in, String baseURI) throws ParsingErrorException { + public void parse(InputStream in, String baseURI) { try { parseJSONLDDocument(JsonDocument.of(in), baseURI); } catch (JsonLdError e) { @@ -73,8 +73,8 @@ public void parse(Reader reader, String baseURI) { private void parseJSONLDDocument(Document document, String baseURI) { try { JsonLdOptions options = new JsonLdOptions(); - if(this.getConfig() instanceof TitaniumJSONLDProcessorOptions) { - options = ((TitaniumJSONLDProcessorOptions) this.getConfig()).getJsonLdOptions(); + if(this.getConfig() instanceof TitaniumJSONLDProcessorOption) { + options = ((TitaniumJSONLDProcessorOption) this.getConfig()).getJsonLdOptions(); } if(baseURI != null && !baseURI.isEmpty()) { options.setBase(URI.create(baseURI)); 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 d29968443..dca347f8a 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,11 +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.io.RdfFormat; +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.io.IOOptions; -import fr.inria.corese.core.next.api.io.parser.RDFParserOptions; import fr.inria.corese.core.next.impl.parser.antlr.TurtleLexer; import fr.inria.corese.core.next.impl.parser.antlr.TurtleParser; @@ -32,8 +31,8 @@ public ANTLRTurtleParser(Model model, ValueFactory factory, IOOptions config) { } @Override - public RdfFormat getRDFFormat() { - return RdfFormat.TURTLE; + public RDFFormat getRDFFormat() { + return RDFFormat.TURTLE; } /** 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 56% 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..b07fa390e 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,21 @@ -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.SerializationConfig; +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.option.*; +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,8 +27,8 @@ /** * 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. * @@ -29,65 +40,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. + * with constructors for all known {@link RDFFormat} implementations. * Each constructor attempts to cast the generic {@link SerializationConfig} 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 +106,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. + * @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, SerializationConfig 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 index 9389a71ca..843a6ab00 100644 --- 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 @@ -5,10 +5,10 @@ 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.api.io.serialization.FormatSerializer; import fr.inria.corese.core.next.impl.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; +import fr.inria.corese.core.next.impl.io.serialization.option.TitaniumJSONLDProcessorOption; import java.io.IOException; import java.io.Writer; @@ -17,7 +17,7 @@ /** * Serializer for JSON-LD format. */ -public class JSONLDSerializer implements FormatSerializer { +public class JSONLDSerializer implements RDFSerializer { private Model model; private IOOptions config; @@ -33,7 +33,7 @@ public JSONLDSerializer(Model model, IOOptions config) { } public JSONLDSerializer(Model model) { - this(model, new TitaniumJSONLDProcessorOptions.Builder().build()); + this(model, new TitaniumJSONLDProcessorOption.Builder().build()); } @Override @@ -42,7 +42,7 @@ public void write(Writer writer) throws SerializationException { try { FromRdfApi fromRdfApi = JsonLd.fromRdf(RdfDocument.of(adapter)); - if(this.config instanceof TitaniumJSONLDProcessorOptions options) { + if(this.config instanceof TitaniumJSONLDProcessorOption options) { fromRdfApi.options(options.getJsonLdOptions()); } 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 index bb0b0010c..794e1ca53 100644 --- 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 @@ -21,7 +21,7 @@ import java.time.temporal.TemporalAmount; import java.util.*; -import static fr.inria.corese.core.next.impl.common.util.SerializationConstants.DEFAULT_GRAPH_IRI; +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. 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 95% 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..1c8aa8d6a 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.SerializationConfig; +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 SerializationConfig { /** * 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/io/TitaniumJSONLDProcessorOptions.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java similarity index 94% rename from src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java rename to src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java index f61be9313..e3034c471 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptions.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.io; +package fr.inria.corese.core.next.impl.io.serialization.option; import com.apicatalog.jsonld.JsonLdOptions; import com.apicatalog.jsonld.JsonLdVersion; @@ -14,11 +14,11 @@ * Wrapper around the JsonLdOptions class for the Titanium JSONLD parser and serializer. * @see JsonLdOptions */ -public class TitaniumJSONLDProcessorOptions extends AbstractIOOptions implements RDFParserOptions, RDFParserBaseIRIOptions { +public class TitaniumJSONLDProcessorOption extends AbstractIOOptions implements RDFParserOptions, RDFParserBaseIRIOptions { private final Builder builder; - protected TitaniumJSONLDProcessorOptions(Builder builder) { + protected TitaniumJSONLDProcessorOption(Builder builder) { this.builder = builder; } @@ -101,13 +101,13 @@ public String getBase() { return this.builder.options.getBase().toString(); } - public static class Builder extends AbstractIOOptions.Builder { + public static class Builder extends AbstractIOOptions.Builder { private final JsonLdOptions options = new JsonLdOptions(); @Override - public TitaniumJSONLDProcessorOptions build() { - return new TitaniumJSONLDProcessorOptions(this); + public TitaniumJSONLDProcessorOption build() { + return new TitaniumJSONLDProcessorOption(this); } /** 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/test/java/fr/inria/corese/core/next/api/base/io/RdfFormatTest.java b/src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java similarity index 59% rename from src/test/java/fr/inria/corese/core/next/api/base/io/RdfFormatTest.java rename to src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java index 8a7c40229..e5859edfa 100644 --- a/src/test/java/fr/inria/corese/core/next/api/base/io/RdfFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/api/base/io/RDFFormatTest.java @@ -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; - fr.inria.corese.core.next.api.base.io.RdfFormat format = new fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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 fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format = fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t1"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t1"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, true); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test", List.of("t"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat format1 = new fr.inria.corese.core.next.api.base.io.RdfFormat("Test1", List.of("t"), List.of("text/t"), true, false); - fr.inria.corese.core.next.api.base.io.RdfFormat format2 = new fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat turtle = fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat ntriples = fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat nquads = fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat jsonld = fr.inria.corese.core.next.api.base.io.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() { - fr.inria.corese.core.next.api.base.io.RdfFormat rdfxml = fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byName("TuRtLe"); + Optional format = RDFFormat.byName("TuRtLe"); assertTrue(format.isPresent(), "Turtle format should be found by name"); - assertEquals(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byExtension("TTL"); + Optional format = RDFFormat.byExtension("TTL"); assertTrue(format.isPresent(), "Turtle format should be found by extension"); - assertEquals(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byExtension("XML"); + Optional rdfXmlFormat = RDFFormat.byExtension("XML"); assertTrue(rdfXmlFormat.isPresent()); - assertEquals(fr.inria.corese.core.next.api.base.io.RdfFormat.RDFXML, rdfXmlFormat.get()); + assertEquals(RDFFormat.RDFXML, rdfXmlFormat.get()); } @Test @DisplayName("byExtension() should return empty Optional for non-existent extension") void byExtensionNotFound() { - Optional format = fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byMimeType("text/TuRtLe"); + Optional format = RDFFormat.byMimeType("text/TuRtLe"); assertTrue(format.isPresent(), "Turtle format should be found by MIME type"); - assertEquals(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.RdfFormat.byMimeType("text/plain"); + Optional nTriplesFormat = RDFFormat.byMimeType("text/plain"); assertTrue(nTriplesFormat.isPresent()); - assertEquals(fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.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 = fr.inria.corese.core.next.api.base.io.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/common/serialization/DefaultSerializerFactoryTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/DefaultSerializerFactoryTest.java index b6ad13c7e..6d4729446 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/common/serialization/DefaultSerializerFactoryTest.java @@ -1,8 +1,15 @@ package fr.inria.corese.core.next.impl.common.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.SerializationConfig; +import fr.inria.corese.core.next.impl.io.serialization.*; +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,8 +22,8 @@ /** * 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 { @@ -36,7 +43,7 @@ void setUp() { @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 +55,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 +67,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 +79,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 +91,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 +104,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 +119,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/NQuadsSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java index b776617cb..2487730bd 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/common/serialization/NQuadsSerializerTest.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.impl.io.serialization; +package fr.inria.corese.core.next.impl.common.serialization; 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.common.serialization.TestStatementFactory; +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.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -22,14 +23,9 @@ class NQuadsSerializerTest { private Model model; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat nQuadsFormat; -======== - private NQuadsConfig config; + private NQuadsOption config; private NQuadsSerializer nQuadsSerializer; private TestStatementFactory factory; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java private Resource mockExPerson; private IRI mockExName; @@ -46,14 +42,9 @@ class NQuadsSerializerTest { @BeforeEach void setUp() { model = mock(Model.class); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nQuadsFormat = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, config); -======== - config = NQuadsConfig.defaultConfig(); + config = NQuadsOption.defaultConfig(); nQuadsSerializer = new NQuadsSerializer(model, config); factory = new TestStatementFactory(); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java mockExPerson = factory.createIRI("http://example.org/Person"); mockExName = factory.createIRI("http://example.org/name"); @@ -69,22 +60,13 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null, config), "Model cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NQuadsSerializer(null), "Model cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java } @Test @DisplayName("Constructor should throw NullPointerException for null configuration") void constructorShouldThrowForNullConfig() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, null), "Configuration cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NQuadsSerializer(model, null), "Configuration cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java } @Test @@ -154,35 +136,6 @@ void writeShouldHandleBlankNodesInContext() throws SerializationException { } @Test -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - @DisplayName("Write should handle blank nodes with custom prefix") - void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, customConfig); - - Statement stmt = createStatement( - mockBNode1, - mockExKnows, - mockBNode2, - createBlankNode("b3") - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - customSerializer.write(writer); - - String expected = String.format("genid-%s <%s> genid-%s genid-%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue(), - createBlankNode("b3").stringValue()) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @Test -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java @DisplayName("Write should throw SerializationException on IO error") void writeShouldThrowOnIOException() throws IOException { Statement stmt = factory.createStatement( @@ -310,12 +263,8 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat serializer = new NQuadsFormat(currentTestModel); -======== - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsConfig.defaultConfig()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java + NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -338,7 +287,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/NTriplesSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java index 21d5b3550..47fa91787 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/common/serialization/NTriplesSerializerTest.java @@ -1,13 +1,10 @@ -package fr.inria.corese.core.next.impl.io.serialization; +package fr.inria.corese.core.next.impl.common.serialization; import fr.inria.corese.core.next.api.*; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java -import fr.inria.corese.core.next.impl.common.vocabulary.RDF; -======== -import fr.inria.corese.core.next.impl.common.serialization.config.NTriplesConfig; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java +import fr.inria.corese.core.next.impl.common.serialization.TestStatementFactory; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; import fr.inria.corese.core.next.impl.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesSerializer; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -22,13 +19,6 @@ import java.io.Writer; import java.util.Iterator; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java -class NTriplesFormatTest { - - private Model model; - private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat nTriplesFormat; -======== import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @@ -36,10 +26,9 @@ class NTriplesFormatTest { class NTriplesSerializerTest { private Model model; - private NTriplesConfig config; + private NTriplesOption config; private NTriplesSerializer nTriplesSerializer; private TestStatementFactory factory; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java private Resource mockExPerson; private IRI mockExName; @@ -55,16 +44,10 @@ class NTriplesSerializerTest { @BeforeEach void setUp() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - model = Mockito.mock(Model.class); - config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nTriplesFormat = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, config); -======== model = mock(Model.class); - config = NTriplesConfig.defaultConfig(); + config = NTriplesOption.defaultConfig(); nTriplesSerializer = new NTriplesSerializer(model, config); factory = new TestStatementFactory(); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java mockExPerson = factory.createIRI("http://example.org/Person"); mockExName = factory.createIRI("http://example.org/name"); @@ -80,22 +63,13 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null), "Model cannot be null"); - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null, config), "Model cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NTriplesSerializer(null), "Model cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Constructor should throw NullPointerException for null configuration") void constructorShouldThrowForNullConfig() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, null), "Configuration cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NTriplesSerializer(model, null), "Configuration cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @@ -164,33 +138,6 @@ void writeShouldHandleBlankNodes() throws SerializationException { } @Test -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - @DisplayName("Write should handle blank nodes with custom prefix") - void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, customConfig); - - Statement stmt = createStatement( - mockBNode1, - mockExKnows, - mockBNode2 - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - customSerializer.write(writer); - - String expected = String.format("genid-%s <%s> genid-%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue()) + " .\n"; - - Assertions.assertEquals(expected, writer.toString()); - } - - @Test -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java @DisplayName("Write should throw SerializationException on IO error") void writeShouldThrowOnIOException() throws IOException { Statement stmt = factory.createStatement( @@ -202,11 +149,6 @@ void writeShouldThrowOnIOException() throws IOException { Writer faultyWriter = Mockito.mock(Writer.class); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Mockito.doThrow(new IOException("Simulated IO error")).when(faultyWriter).write(ArgumentMatchers.anyString()); - - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(faultyWriter)); -======== 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()); doThrow(new IOException("Simulated IO error (close)")).when(faultyWriter).close(); @@ -214,23 +156,12 @@ void writeShouldThrowOnIOException() throws IOException { SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(faultyWriter)); assertEquals("N-Triples serialization failed [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Write should throw SerializationException for null subject value in strict mode") void writeShouldThrowOnNullSubjectValue() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(null); - Mockito.when(stmt.getPredicate()).thenReturn(mockExName); - Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== Statement stmt = mock(Statement.class); when(stmt.getSubject()).thenReturn(null); when(stmt.getPredicate()).thenReturn(mockExName); @@ -242,22 +173,11 @@ void writeShouldThrowOnNullSubjectValue() { SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Write should throw SerializationException for null predicate value in strict mode") void writeShouldThrowOnNullPredicateValue() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(mockExPerson); - Mockito.when(stmt.getPredicate()).thenReturn(null); - Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== Statement stmt = mock(Statement.class); when(stmt.getSubject()).thenReturn(mockExPerson); when(stmt.getPredicate()).thenReturn(null); @@ -268,7 +188,6 @@ void writeShouldThrowOnNullPredicateValue() { StringWriter writer = new StringWriter(); SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @@ -281,9 +200,6 @@ void writeShouldThrowOnNullObjectValue() { Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); } @@ -310,7 +226,6 @@ void writeShouldHandleNullContext() throws SerializationException { escapeNTriplesString(lexJohn)) + " .\n"; assertEquals(expected, writer.toString()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @ParameterizedTest @@ -348,40 +263,6 @@ void writeShouldHandleVariousLiterals(String literalValue) throws SerializationE Assertions.assertEquals(expectedOutput, writer.toString()); } -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - @Test - @DisplayName("Write should handle multiple statements") - void writeShouldHandleMultipleStatements() throws SerializationException { - Statement stmt1 = createStatement( - mockExPerson, - mockExName, - createLiteral("o1", null, null) - ); - Statement stmt2 = createStatement( - mockBNode1, - mockExKnows, - mockExPerson, - createIRI("http://example.org/ctx") - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt1, stmt2)); - - StringWriter writer = new StringWriter(); - nTriplesFormat.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNTriplesString("o1")) + " .\n" + - String.format("_:%s <%s> <%s>", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockExPerson.stringValue()) + " .\n"; - - Assertions.assertEquals(expectedOutput, writer.toString()); - } -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java - @Test @DisplayName("Should handle literals with language tags") void shouldHandleLiteralsWithLanguageTags() throws SerializationException { @@ -391,12 +272,8 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Mockito.when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat serializer = new NTriplesFormat(currentTestModel); -======== - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesConfig.defaultConfig()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java + NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -420,7 +297,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); @@ -490,69 +367,4 @@ public Statement next() { return statements[index++]; } } -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - - - /** - * Creates a mocked Literal object. - * Important: The `lexicalForm` is the *raw string value* of the literal, - * without N-Triples specific quotes, lang tags, or datatype URIs. - * The `NTriplesFormat` class is responsible for adding those. - * - * @param lexicalForm The raw string value of the literal (e.g., "hello", "123"). - * @param dataTypeIRI The IRI of the literal's datatype (e.g., XSD.INTEGER.getIRI()), or null for plain/lang-tagged. - * @param langTag The language tag (e.g., "en"), or null if not language-tagged. - * @return A mocked Literal instance. - */ - private Literal createLiteral(String lexicalForm, IRI dataTypeIRI, String langTag) { - Literal literal = Mockito.mock(Literal.class); - Mockito.when(literal.isLiteral()).thenReturn(true); - Mockito.when(literal.isResource()).thenReturn(false); - Mockito.when(literal.stringValue()).thenReturn(lexicalForm); - - if (langTag != null && !langTag.isEmpty()) { - Mockito.when(literal.getLanguage()).thenReturn(Optional.of(langTag)); - - - Mockito.when(literal.getDatatype()).thenReturn(RDF.langString.getIRI()); - } else { - Mockito.when(literal.getLanguage()).thenReturn(Optional.empty()); - Mockito.when(literal.getDatatype()).thenReturn(dataTypeIRI); - } - return literal; - } - - private Statement createStatement(Resource subject, IRI predicate, Value object) { - return createStatement(subject, predicate, object, null); - } - - private Statement createStatement(Resource subject, IRI predicate, Value object, Resource context) { - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(subject); - Mockito.when(stmt.getPredicate()).thenReturn(predicate); - Mockito.when(stmt.getObject()).thenReturn(object); - Mockito.when(stmt.getContext()).thenReturn(context); - return stmt; - } - - private Resource createBlankNode(String id) { - Resource blankNode = Mockito.mock(Resource.class); - Mockito.when(blankNode.isResource()).thenReturn(true); - Mockito.when(blankNode.isBNode()).thenReturn(true); - Mockito.when(blankNode.isIRI()).thenReturn(false); - Mockito.when(blankNode.stringValue()).thenReturn(id); - return blankNode; - } - - private IRI createIRI(String uri) { - IRI iri = Mockito.mock(IRI.class); - Mockito.when(iri.isResource()).thenReturn(true); - Mockito.when(iri.isIRI()).thenReturn(true); - Mockito.when(iri.isBNode()).thenReturn(false); - Mockito.when(iri.stringValue()).thenReturn(uri); - return iri; - } -} -======== } ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java 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/common/serialization/TriGSerializerTest.java index cda7322cc..64f5cdd8f 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/common/serialization/TriGSerializerTest.java @@ -4,9 +4,10 @@ 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.option.LiteralDatatypePolicyEnum; +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.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 +28,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 +156,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 +206,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 +256,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 +339,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 +375,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 +412,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/TurtleSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/TurtleSerializerTest.java index 053e111ef..f05c93574 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/common/serialization/TurtleSerializerTest.java @@ -4,9 +4,10 @@ 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.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleOption; +import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleSerializer; +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 +30,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 +153,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 +214,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 +315,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 +399,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 +435,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 +471,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/common/serialization/XmlSerializerTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/XmlSerializerTest.java index 54d27e46c..0b1f12ebe 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/common/serialization/XmlSerializerTest.java @@ -2,10 +2,11 @@ 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.rdfxml.XmlSerializer; +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.rdfxml.XmlOption; +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 +28,7 @@ class XmlSerializerTest { @Mock private Model mockModel; - XmlConfig mockConfig; + XmlOption mockConfig; private TestStatementFactory factory; private StringWriter writer; @@ -38,7 +39,7 @@ void setUp() { writer = new StringWriter(); factory = new TestStatementFactory(); - mockConfig = XmlConfig.defaultConfig(); + mockConfig = XmlOption.defaultConfig(); } @@ -53,7 +54,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 +89,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 +122,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 +155,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 +186,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 +218,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 +255,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 +297,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 +333,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 +363,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 +397,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 +429,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 +467,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 +498,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/NQuadsConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NQuadsConfigTest.java index 8fdb09247..c86abc768 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/common/serialization/config/NQuadsConfigTest.java @@ -1,12 +1,14 @@ package fr.inria.corese.core.next.impl.common.serialization.config; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; 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. */ @@ -15,11 +17,11 @@ class NQuadsConfigTest { @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 +33,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 +43,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 +53,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 +63,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 +85,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 +95,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 +105,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 +115,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/config/NTriplesConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/NTriplesConfigTest.java index 0f7ec0927..fea4ed524 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/common/serialization/config/NTriplesConfigTest.java @@ -1,12 +1,14 @@ package fr.inria.corese.core.next.impl.common.serialization.config; +import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; 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. */ @@ -15,11 +17,11 @@ class NTriplesConfigTest { @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 +33,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 +43,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 +53,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 +63,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 +85,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 +95,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 +105,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 +115,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/config/TriGConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TriGConfigTest.java index ff16f055f..0b33125e9 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/common/serialization/config/TriGConfigTest.java @@ -1,6 +1,10 @@ package 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.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.trig.TriGOption; +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 +14,7 @@ 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. */ @@ -19,7 +23,7 @@ class TriGConfigTest { @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 +52,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 +61,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 +70,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 +79,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 +90,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 +103,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 +112,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 +121,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 +130,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 +139,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 +148,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 +157,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 +167,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 +177,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 +186,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 +195,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 +204,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 +213,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 +233,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 +243,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 +252,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 +261,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/config/TurtleConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/TurtleConfigTest.java index 482d9718c..3183074d9 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/common/serialization/config/TurtleConfigTest.java @@ -1,6 +1,10 @@ package 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.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.turtle.TurtleOption; +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 +14,7 @@ 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. */ @@ -19,7 +23,7 @@ class TurtleConfigTest { @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 +50,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 +62,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 +71,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 +82,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 +95,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 +104,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 +113,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 +122,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 +131,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 +140,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 +149,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 +159,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 +169,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 +178,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 +187,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 +196,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 +205,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 +225,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 +235,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 +244,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 +253,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 +262,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/config/XmlConfigTest.java b/src/test/java/fr/inria/corese/core/next/impl/common/serialization/config/XmlConfigTest.java index 7e55fd903..9bced5a61 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/common/serialization/config/XmlConfigTest.java @@ -1,6 +1,9 @@ package 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.LiteralDatatypePolicyEnum; +import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; +import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlOption; +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 +13,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 +22,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 +45,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 +55,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 +64,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 +73,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 +84,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 +97,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 +107,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 +117,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 +126,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 +135,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 +144,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 +153,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 +171,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 +181,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 +191,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 +200,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 +209,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 +218,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/io/TitaniumJSONLDProcessorOptionsTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java similarity index 71% rename from src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java index f3f983563..8fb3abca9 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionsTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java @@ -1,6 +1,7 @@ package fr.inria.corese.core.next.impl.io; import com.apicatalog.jsonld.JsonLdVersion; +import fr.inria.corese.core.next.impl.io.serialization.option.TitaniumJSONLDProcessorOption; import org.junit.jupiter.api.Test; import java.time.Duration; @@ -11,25 +12,25 @@ /** * Tests to check that values are properly set */ -class TitaniumJSONLDProcessorOptionsTest { +class TitaniumJSONLDProcessorOptionTest { - private TitaniumJSONLDProcessorOptions optionAllTrue = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().base("http://example.org/AllTrue") + 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 TitaniumJSONLDProcessorOptions optionAllFalse = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().base("http://example.org/AllFalse") + 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() { @@ -57,15 +58,15 @@ void isOrdered() { @Test void getProcessingMode() { - TitaniumJSONLDProcessorOptions option10 = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().processingMode(JsonLdVersion.V1_0)); - TitaniumJSONLDProcessorOptions option11 = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().processingMode(JsonLdVersion.V1_1)); + 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() { - TitaniumJSONLDProcessorOptions option10seconds = new TitaniumJSONLDProcessorOptions(new TitaniumJSONLDProcessorOptions.Builder().timeout(Duration.of(10, ChronoUnit.SECONDS))); + TitaniumJSONLDProcessorOption option10seconds = new TitaniumJSONLDProcessorOption.Builder().timeout(Duration.of(10, ChronoUnit.SECONDS)).build(); assertNull(optionAllTrue.getTimeout()); assertEquals(Duration.of(10, ChronoUnit.SECONDS), option10seconds.getTimeout()); } 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 index 5ca02acb1..08d7dbf72 100644 --- 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 @@ -1,7 +1,7 @@ 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.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; @@ -44,8 +44,8 @@ void constructorConfigNoThrowsTest() { @Test void getRDFFormatTest() { - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, new CoreseModel(), valueFactory); - assertEquals(RdfFormat.JSONLD, parser.getRDFFormat()); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, new CoreseModel(), valueFactory); + assertEquals(RDFFormat.JSONLD, parser.getRDFFormat()); } /** @@ -70,7 +70,7 @@ public void testParseInputStream() { } """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes())); assertEquals(3, model.size()); @@ -108,7 +108,7 @@ public void testParseInputStreamString() { } """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); parser.parse(new ByteArrayInputStream(sampleJsonLD.getBytes()), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -146,7 +146,7 @@ public void testParseReader() { } """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); parser.parse(new StringReader(sampleJsonLD)); assertEquals(3, model.size()); @@ -184,7 +184,7 @@ public void testParseReaderString() { } """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); parser.parse(new StringReader(sampleJsonLD), "http://me.markus-lanthaler.com/"); assertEquals(3, model.size()); @@ -227,7 +227,7 @@ public void testParseJsonLDWithBlankNodes() { """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); Reader reader = new StringReader(sampleJsonLD); parser.parse(reader); @@ -278,7 +278,7 @@ public void testParseJSONLDWithGraphs() { """; Model model = new CoreseModel(); - RDFParser parser = factory.createRDFParser(RdfFormat.JSONLD, model, valueFactory); + RDFParser parser = factory.createRDFParser(RDFFormat.JSONLD, model, valueFactory); parser.parse(new StringReader(sampleJsonLD)); assertEquals(7, model.size()); 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 index 04f91d7f5..64a959017 100644 --- 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 @@ -2,8 +2,8 @@ import com.apicatalog.jsonld.json.JsonLdComparison; import fr.inria.corese.core.next.api.*; -import fr.inria.corese.core.next.api.io.serialization.FormatSerializer; -import fr.inria.corese.core.next.impl.io.TitaniumJSONLDProcessorOptions; +import fr.inria.corese.core.next.api.io.serialization.RDFSerializer; +import fr.inria.corese.core.next.impl.io.serialization.option.TitaniumJSONLDProcessorOption; import fr.inria.corese.core.next.impl.temp.CoreseAdaptedValueFactory; import fr.inria.corese.core.next.impl.temp.CoreseModel; import jakarta.json.Json; @@ -47,7 +47,7 @@ public void smallModelTest() { // IRI IRI LangLiteral this.model.add(iriNode, iriPred, langLiteral); - FormatSerializer serializer = new JSONLDSerializer(this.model, (new TitaniumJSONLDProcessorOptions.Builder()).ordered(true).build()); + RDFSerializer serializer = new JSONLDSerializer(this.model, (new TitaniumJSONLDProcessorOption.Builder()).ordered(true).build()); StringWriter writer = new StringWriter(); @@ -98,7 +98,7 @@ public void modelWithBlankNodesTest() { // BlankNode IRI BlankNode this.model.add(blankNode, iriPred, blankNode); - FormatSerializer serializer = new JSONLDSerializer(this.model); + RDFSerializer serializer = new JSONLDSerializer(this.model); StringWriter writer = new StringWriter(); serializer.write(writer); @@ -149,7 +149,7 @@ public void modelWithNamedGraphsTest() { // IRI IRI LangLiteral this.model.add(iriNode, iriPred, langLiteral, graph1, graph2); - FormatSerializer serializer = new JSONLDSerializer(this.model); + RDFSerializer serializer = new JSONLDSerializer(this.model); StringWriter writer = new StringWriter(); serializer.write(writer); diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java index b776617cb..26f4af1d8 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java @@ -1,9 +1,10 @@ -package fr.inria.corese.core.next.impl.io.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.common.serialization.TestStatementFactory; +import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; import fr.inria.corese.core.next.impl.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -22,14 +23,9 @@ class NQuadsSerializerTest { private Model model; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat nQuadsFormat; -======== - private NQuadsConfig config; + private NQuadsOption config; private NQuadsSerializer nQuadsSerializer; private TestStatementFactory factory; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java private Resource mockExPerson; private IRI mockExName; @@ -46,14 +42,9 @@ class NQuadsSerializerTest { @BeforeEach void setUp() { model = mock(Model.class); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nQuadsFormat = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, config); -======== - config = NQuadsConfig.defaultConfig(); + config = NQuadsOption.defaultConfig(); nQuadsSerializer = new NQuadsSerializer(model, config); factory = new TestStatementFactory(); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java mockExPerson = factory.createIRI("http://example.org/Person"); mockExName = factory.createIRI("http://example.org/name"); @@ -69,22 +60,13 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null), "Model cannot be null"); - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(null, config), "Model cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NQuadsSerializer(null), "Model cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java } @Test @DisplayName("Constructor should throw NullPointerException for null configuration") void constructorShouldThrowForNullConfig() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, null), "Configuration cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NQuadsSerializer(model, null), "Configuration cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java } @Test @@ -154,35 +136,6 @@ void writeShouldHandleBlankNodesInContext() throws SerializationException { } @Test -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - @DisplayName("Write should handle blank nodes with custom prefix") - void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat(model, customConfig); - - Statement stmt = createStatement( - mockBNode1, - mockExKnows, - mockBNode2, - createBlankNode("b3") - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - customSerializer.write(writer); - - String expected = String.format("genid-%s <%s> genid-%s genid-%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue(), - createBlankNode("b3").stringValue()) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @Test -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java @DisplayName("Write should throw SerializationException on IO error") void writeShouldThrowOnIOException() throws IOException { Statement stmt = factory.createStatement( @@ -310,12 +263,8 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java - fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsFormat serializer = new NQuadsFormat(currentTestModel); -======== - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsConfig.defaultConfig()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NQuadsSerializerTest.java + NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -338,7 +287,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/io/serialization/ntriples/NTriplesFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java index 21d5b3550..3c24b1896 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java @@ -1,20 +1,14 @@ -package fr.inria.corese.core.next.impl.io.serialization; +package fr.inria.corese.core.next.impl.io.serialization.ntriples; import fr.inria.corese.core.next.api.*; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java -import fr.inria.corese.core.next.impl.common.vocabulary.RDF; -======== -import fr.inria.corese.core.next.impl.common.serialization.config.NTriplesConfig; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java +import fr.inria.corese.core.next.impl.common.serialization.TestStatementFactory; import fr.inria.corese.core.next.impl.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat; 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.ArgumentMatchers; import org.mockito.Mockito; import java.io.IOException; @@ -22,13 +16,6 @@ import java.io.Writer; import java.util.Iterator; -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java -class NTriplesFormatTest { - - private Model model; - private fr.inria.corese.core.next.impl.io.serialization.FormatConfig config; - private fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat nTriplesFormat; -======== import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; @@ -36,10 +23,9 @@ class NTriplesFormatTest { class NTriplesSerializerTest { private Model model; - private NTriplesConfig config; + private NTriplesOption config; private NTriplesSerializer nTriplesSerializer; private TestStatementFactory factory; ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java private Resource mockExPerson; private IRI mockExName; @@ -55,16 +41,10 @@ class NTriplesSerializerTest { @BeforeEach void setUp() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - model = Mockito.mock(Model.class); - config = new fr.inria.corese.core.next.impl.io.serialization.FormatConfig.Builder().build(); - nTriplesFormat = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, config); -======== model = mock(Model.class); - config = NTriplesConfig.defaultConfig(); + config = NTriplesOption.defaultConfig(); nTriplesSerializer = new NTriplesSerializer(model, config); factory = new TestStatementFactory(); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java mockExPerson = factory.createIRI("http://example.org/Person"); mockExName = factory.createIRI("http://example.org/name"); @@ -80,22 +60,13 @@ void setUp() { @Test @DisplayName("Constructor should throw NullPointerException for null model") void constructorShouldThrowForNullModel() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null), "Model cannot be null"); - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(null, config), "Model cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NTriplesSerializer(null), "Model cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Constructor should throw NullPointerException for null configuration") void constructorShouldThrowForNullConfig() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(NullPointerException.class, () -> new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, null), "Configuration cannot be null"); -======== assertThrows(NullPointerException.class, () -> new NTriplesSerializer(model, null), "Configuration cannot be null"); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @@ -164,33 +135,6 @@ void writeShouldHandleBlankNodes() throws SerializationException { } @Test -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - @DisplayName("Write should handle blank nodes with custom prefix") - void writeShouldHandleBlankNodesWithCustomPrefix() throws SerializationException { - fr.inria.corese.core.next.impl.io.serialization.FormatConfig customConfig = new FormatConfig.Builder().blankNodePrefix("genid-").build(); - fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat customSerializer = new fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat(model, customConfig); - - Statement stmt = createStatement( - mockBNode1, - mockExKnows, - mockBNode2 - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - customSerializer.write(writer); - - String expected = String.format("genid-%s <%s> genid-%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue()) + " .\n"; - - Assertions.assertEquals(expected, writer.toString()); - } - - @Test -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java @DisplayName("Write should throw SerializationException on IO error") void writeShouldThrowOnIOException() throws IOException { Statement stmt = factory.createStatement( @@ -202,11 +146,6 @@ void writeShouldThrowOnIOException() throws IOException { Writer faultyWriter = Mockito.mock(Writer.class); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Mockito.doThrow(new IOException("Simulated IO error")).when(faultyWriter).write(ArgumentMatchers.anyString()); - - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(faultyWriter)); -======== 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()); doThrow(new IOException("Simulated IO error (close)")).when(faultyWriter).close(); @@ -214,23 +153,12 @@ void writeShouldThrowOnIOException() throws IOException { SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(faultyWriter)); assertEquals("N-Triples serialization failed [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Write should throw SerializationException for null subject value in strict mode") void writeShouldThrowOnNullSubjectValue() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(null); - Mockito.when(stmt.getPredicate()).thenReturn(mockExName); - Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== Statement stmt = mock(Statement.class); when(stmt.getSubject()).thenReturn(null); when(stmt.getPredicate()).thenReturn(mockExName); @@ -242,22 +170,11 @@ void writeShouldThrowOnNullSubjectValue() { SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @DisplayName("Write should throw SerializationException for null predicate value in strict mode") void writeShouldThrowOnNullPredicateValue() { -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(mockExPerson); - Mockito.when(stmt.getPredicate()).thenReturn(null); - Mockito.when(stmt.getObject()).thenReturn(mockLiteralJohn); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== Statement stmt = mock(Statement.class); when(stmt.getSubject()).thenReturn(mockExPerson); when(stmt.getPredicate()).thenReturn(null); @@ -268,7 +185,6 @@ void writeShouldThrowOnNullPredicateValue() { StringWriter writer = new StringWriter(); SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @Test @@ -281,9 +197,6 @@ void writeShouldThrowOnNullObjectValue() { Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); StringWriter writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - Assertions.assertThrows(SerializationException.class, () -> nTriplesFormat.write(writer)); -======== SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); } @@ -310,7 +223,6 @@ void writeShouldHandleNullContext() throws SerializationException { escapeNTriplesString(lexJohn)) + " .\n"; assertEquals(expected, writer.toString()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java } @ParameterizedTest @@ -348,40 +260,6 @@ void writeShouldHandleVariousLiterals(String literalValue) throws SerializationE Assertions.assertEquals(expectedOutput, writer.toString()); } -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - @Test - @DisplayName("Write should handle multiple statements") - void writeShouldHandleMultipleStatements() throws SerializationException { - Statement stmt1 = createStatement( - mockExPerson, - mockExName, - createLiteral("o1", null, null) - ); - Statement stmt2 = createStatement( - mockBNode1, - mockExKnows, - mockExPerson, - createIRI("http://example.org/ctx") - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt1, stmt2)); - - StringWriter writer = new StringWriter(); - nTriplesFormat.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNTriplesString("o1")) + " .\n" + - String.format("_:%s <%s> <%s>", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockExPerson.stringValue()) + " .\n"; - - Assertions.assertEquals(expectedOutput, writer.toString()); - } -======== ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java - @Test @DisplayName("Should handle literals with language tags") void shouldHandleLiteralsWithLanguageTags() throws SerializationException { @@ -391,12 +269,8 @@ void shouldHandleLiteralsWithLanguageTags() throws SerializationException { Mockito.when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); Writer writer = new StringWriter(); -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesFormat serializer = new NTriplesFormat(currentTestModel); -======== - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesConfig.defaultConfig()); ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java + NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); serializer.write(writer); String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", @@ -420,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); @@ -490,69 +364,4 @@ public Statement next() { return statements[index++]; } } -<<<<<<<< HEAD:src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java - - - /** - * Creates a mocked Literal object. - * Important: The `lexicalForm` is the *raw string value* of the literal, - * without N-Triples specific quotes, lang tags, or datatype URIs. - * The `NTriplesFormat` class is responsible for adding those. - * - * @param lexicalForm The raw string value of the literal (e.g., "hello", "123"). - * @param dataTypeIRI The IRI of the literal's datatype (e.g., XSD.INTEGER.getIRI()), or null for plain/lang-tagged. - * @param langTag The language tag (e.g., "en"), or null if not language-tagged. - * @return A mocked Literal instance. - */ - private Literal createLiteral(String lexicalForm, IRI dataTypeIRI, String langTag) { - Literal literal = Mockito.mock(Literal.class); - Mockito.when(literal.isLiteral()).thenReturn(true); - Mockito.when(literal.isResource()).thenReturn(false); - Mockito.when(literal.stringValue()).thenReturn(lexicalForm); - - if (langTag != null && !langTag.isEmpty()) { - Mockito.when(literal.getLanguage()).thenReturn(Optional.of(langTag)); - - - Mockito.when(literal.getDatatype()).thenReturn(RDF.langString.getIRI()); - } else { - Mockito.when(literal.getLanguage()).thenReturn(Optional.empty()); - Mockito.when(literal.getDatatype()).thenReturn(dataTypeIRI); - } - return literal; - } - - private Statement createStatement(Resource subject, IRI predicate, Value object) { - return createStatement(subject, predicate, object, null); - } - - private Statement createStatement(Resource subject, IRI predicate, Value object, Resource context) { - Statement stmt = Mockito.mock(Statement.class); - Mockito.when(stmt.getSubject()).thenReturn(subject); - Mockito.when(stmt.getPredicate()).thenReturn(predicate); - Mockito.when(stmt.getObject()).thenReturn(object); - Mockito.when(stmt.getContext()).thenReturn(context); - return stmt; - } - - private Resource createBlankNode(String id) { - Resource blankNode = Mockito.mock(Resource.class); - Mockito.when(blankNode.isResource()).thenReturn(true); - Mockito.when(blankNode.isBNode()).thenReturn(true); - Mockito.when(blankNode.isIRI()).thenReturn(false); - Mockito.when(blankNode.stringValue()).thenReturn(id); - return blankNode; - } - - private IRI createIRI(String uri) { - IRI iri = Mockito.mock(IRI.class); - Mockito.when(iri.isResource()).thenReturn(true); - Mockito.when(iri.isIRI()).thenReturn(true); - Mockito.when(iri.isBNode()).thenReturn(false); - Mockito.when(iri.stringValue()).thenReturn(uri); - return iri; - } -} -======== } ->>>>>>>> feature/corese-next:src/test/java/fr/inria/corese/core/next/impl/common/serialization/NTriplesSerializerTest.java From baed5bc955e2fe72633c362b87eaa11339a3b6ca Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 10 Jul 2025 15:03:10 +0200 Subject: [PATCH 28/31] Fixing test names and packages following review --- .../option/TitaniumJSONLDProcessorOption.java | 2 +- .../impl/io/parser/jsonld/JSONLDParser.java | 2 +- .../jsonld/JSONLDSerializer.java | 2 +- .../TitaniumJSONLDProcessorOptionTest.java | 3 +- ...erSpec.java => ANTLRTurtleParserTest.java} | 2 +- ...lSpec.java => TurtleListenerImplTest.java} | 2 +- .../DefaultSerializerFactoryTest.java | 2 +- .../serialization/TestStatementFactory.java | 2 +- .../jsonld/JSONLDSerializerTest.java | 2 +- .../nquads/NQuadsFormatTest.java | 370 ------------------ .../nquads/NQuadsOptionTest.java} | 5 +- .../nquads}/NQuadsSerializerTest.java | 7 +- .../ntriples/NTriplesFormatTest.java | 367 ----------------- .../ntriples/NTriplesOptionTest.java} | 5 +- .../ntriples}/NTriplesSerializerTest.java | 7 +- .../serialization/rdfxml}/XmlConfigTest.java | 3 +- .../rdfxml}/XmlSerializerTest.java | 5 +- .../serialization/trig/TriGOptionTest.java} | 5 +- .../trig}/TriGSerializerTest.java | 5 +- .../turtle/TurtleOptionTest.java} | 5 +- .../turtle}/TurtleSerializerTest.java | 5 +- 21 files changed, 29 insertions(+), 779 deletions(-) rename src/main/java/fr/inria/corese/core/next/impl/io/{serialization => }/option/TitaniumJSONLDProcessorOption.java (99%) rename src/test/java/fr/inria/corese/core/next/impl/io/{ => option}/TitaniumJSONLDProcessorOptionTest.java (95%) rename src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/{ANTLRTurtleParserSpec.java => ANTLRTurtleParserTest.java} (96%) rename src/test/java/fr/inria/corese/core/next/impl/io/parser/turtle/{TurtleListenerImplSpec.java => TurtleListenerImplTest.java} (99%) rename src/test/java/fr/inria/corese/core/next/impl/{common => io}/serialization/DefaultSerializerFactoryTest.java (98%) rename src/test/java/fr/inria/corese/core/next/impl/{common => io}/serialization/TestStatementFactory.java (98%) delete mode 100644 src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization/config/NQuadsConfigTest.java => io/serialization/nquads/NQuadsOptionTest.java} (96%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/nquads}/NQuadsSerializerTest.java (97%) delete mode 100644 src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization/config/NTriplesConfigTest.java => io/serialization/ntriples/NTriplesOptionTest.java} (96%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/ntriples}/NTriplesSerializerTest.java (97%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization/config => io/serialization/rdfxml}/XmlConfigTest.java (98%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/rdfxml}/XmlSerializerTest.java (99%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization/config/TriGConfigTest.java => io/serialization/trig/TriGOptionTest.java} (98%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/trig}/TriGSerializerTest.java (98%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization/config/TurtleConfigTest.java => io/serialization/turtle/TurtleOptionTest.java} (98%) rename src/test/java/fr/inria/corese/core/next/impl/{common/serialization => io/serialization/turtle}/TurtleSerializerTest.java (98%) diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java b/src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java similarity index 99% rename from src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java rename to src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java index e3034c471..1663be302 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/TitaniumJSONLDProcessorOption.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOption.java @@ -1,4 +1,4 @@ -package fr.inria.corese.core.next.impl.io.serialization.option; +package fr.inria.corese.core.next.impl.io.option; import com.apicatalog.jsonld.JsonLdOptions; import com.apicatalog.jsonld.JsonLdVersion; 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 index 4a344f969..245c0de7d 100644 --- 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 @@ -14,7 +14,7 @@ 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.serialization.option.TitaniumJSONLDProcessorOption; +import fr.inria.corese.core.next.impl.io.option.TitaniumJSONLDProcessorOption; import java.io.InputStream; import java.io.Reader; 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 index 843a6ab00..f9e67bec7 100644 --- 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 @@ -8,7 +8,7 @@ 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.serialization.option.TitaniumJSONLDProcessorOption; +import fr.inria.corese.core.next.impl.io.option.TitaniumJSONLDProcessorOption; import java.io.IOException; import java.io.Writer; diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java similarity index 95% rename from src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java rename to src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java index 8fb3abca9..5b0ac465d 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/TitaniumJSONLDProcessorOptionTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/option/TitaniumJSONLDProcessorOptionTest.java @@ -1,7 +1,6 @@ -package fr.inria.corese.core.next.impl.io; +package fr.inria.corese.core.next.impl.io.option; import com.apicatalog.jsonld.JsonLdVersion; -import fr.inria.corese.core.next.impl.io.serialization.option.TitaniumJSONLDProcessorOption; import org.junit.jupiter.api.Test; import java.time.Duration; 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 96% 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 8d0882c9e..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 @@ -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 99% 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 31d9bba0a..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(); 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 98% 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 6d4729446..5b3eaa15e 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,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.Model; import fr.inria.corese.core.next.api.base.io.RDFFormat; 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 index 64a959017..3c33b08e9 100644 --- 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 @@ -3,7 +3,7 @@ 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.serialization.option.TitaniumJSONLDProcessorOption; +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; diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java deleted file mode 100644 index 26f4af1d8..000000000 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/nquads/NQuadsFormatTest.java +++ /dev/null @@ -1,370 +0,0 @@ -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.TestStatementFactory; -import fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; -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; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.Iterator; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -class NQuadsSerializerTest { - - private Model model; - private NQuadsOption config; - private NQuadsSerializer nQuadsSerializer; - private TestStatementFactory factory; - - private Resource mockExPerson; - private IRI mockExName; - private IRI mockExKnows; - - private final String lexJohn = "John Doe"; - private final String hello = "Hello"; - - private Literal mockLiteralJohn; - private Literal mockLiteralHelloEn; - private Resource mockBNode1; - private Resource mockBNode2; - - @BeforeEach - void setUp() { - model = mock(Model.class); - config = NQuadsOption.defaultConfig(); - nQuadsSerializer = new NQuadsSerializer(model, config); - factory = new TestStatementFactory(); - - mockExPerson = factory.createIRI("http://example.org/Person"); - mockExName = factory.createIRI("http://example.org/name"); - mockExKnows = factory.createIRI("http://example.org/knows"); - - mockLiteralJohn = factory.createLiteral(lexJohn, null, null); - mockLiteralHelloEn = factory.createLiteral(hello, null, "en"); - - mockBNode1 = factory.createBlankNode("b1"); - mockBNode2 = factory.createBlankNode("b2"); - } - - @Test - @DisplayName("Constructor should throw NullPointerException for null model") - void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new NQuadsSerializer(null), "Model cannot be null"); - } - - @Test - @DisplayName("Constructor should throw NullPointerException for null configuration") - void constructorShouldThrowForNullConfig() { - assertThrows(NullPointerException.class, () -> new NQuadsSerializer(model, null), "Configuration cannot be null"); - } - - @Test - @DisplayName("Write should serialize a simple statement correctly (default graph)") - void writeShouldSerializeSimpleStatement() throws SerializationException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nQuadsSerializer.write(writer); - - String expected = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNQuadsString(lexJohn)) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should handle blank nodes with default prefix") - void writeShouldHandleBlankNodes() throws SerializationException { - Statement stmt = factory.createStatement( - mockBNode1, - mockExKnows, - mockBNode2 - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nQuadsSerializer.write(writer); - - String expected = String.format("_:%s <%s> _:%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue()) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should handle blank nodes in context with default prefix") - void writeShouldHandleBlankNodesInContext() throws SerializationException { - Resource blankNodeContext = factory.createBlankNode("b3"); - Statement stmt = factory.createStatement( - mockBNode1, - mockExKnows, - mockExPerson, - blankNodeContext - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nQuadsSerializer.write(writer); - - String expected = String.format("_:%s <%s> <%s> _:%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockExPerson.stringValue(), - blankNodeContext.stringValue()) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should throw SerializationException on IO error") - void writeShouldThrowOnIOException() throws IOException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - Writer faultyWriter = 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()); - doThrow(new IOException("Simulated IO error (close)")).when(faultyWriter).close(); - - SerializationException thrown = assertThrows(SerializationException.class, () -> nQuadsSerializer.write(faultyWriter)); - assertEquals("N-Quads serialization failed [Format: N-Quads]", thrown.getMessage()); - } - - @Test - @DisplayName("Write should throw SerializationException for null subject value in strict mode") - void writeShouldThrowOnNullSubjectValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(null); - when(stmt.getPredicate()).thenReturn(mockExName); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(stmt.getContext()).thenReturn(null); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - SerializationException thrown = assertThrows(SerializationException.class, () -> nQuadsSerializer.write(writer)); - assertEquals("Invalid N-Quads data: Value cannot be null in N-Quads format when strictMode is enabled. [Format: N-Quads]", thrown.getMessage()); - } - - @Test - @DisplayName("Write should throw SerializationException for null predicate value in strict mode") - void writeShouldThrowOnNullPredicateValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(mockExPerson); - when(stmt.getPredicate()).thenReturn(null); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(stmt.getContext()).thenReturn(null); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - SerializationException thrown = assertThrows(SerializationException.class, () -> nQuadsSerializer.write(writer)); - assertEquals("Invalid N-Quads data: Value cannot be null in N-Quads format when strictMode is enabled. [Format: N-Quads]", thrown.getMessage()); - } - - @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)); - - StringWriter writer = new StringWriter(); - SerializationException thrown = assertThrows(SerializationException.class, () -> nQuadsSerializer.write(writer)); - assertEquals("Invalid N-Quads data: Value cannot be null in N-Quads format when strictMode is enabled. [Format: N-Quads]", thrown.getMessage()); - } - - @Test - @DisplayName("Write should handle null context correctly (default graph)") - void writeShouldHandleNullContext() throws SerializationException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn, - null - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nQuadsSerializer.write(writer); - - String expected = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNQuadsString(lexJohn)) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @ParameterizedTest - @ValueSource(strings = { - "simple literal", - "literal with \"quotes\"", - "literal with \\ backslash", - "literal with \n newline", - "literal with \t tab", - "literal with \r carriage return", - "literal with \u0001 (SOH)", - "literal with \u007F (DEL)" - }) - @DisplayName("Write should handle various literal values with appropriate escaping (including Unicode)") - void writeShouldHandleVariousLiterals(String literalValue) throws SerializationException { - Literal literalMock = factory.createLiteral(literalValue, null, null); - - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - literalMock - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nQuadsSerializer.write(writer); - - String expectedEscapedLiteral = escapeNQuadsString(literalValue); - String expectedOutput = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - expectedEscapedLiteral) + " .\n"; - - 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)); - - Writer writer = new StringWriter(); - - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); - serializer.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", - mockExPerson.stringValue(), - factory.createIRI("http://example.org/greeting").stringValue(), - escapeNQuadsString(hello), - mockLiteralHelloEn.getLanguage().get()) + " .\n"; - - assertEquals(expectedOutput, writer.toString()); - } - - @Test - @DisplayName("Should handle literals with custom datatypes") - void shouldHandleLiteralsWithCustomDatatypes() throws SerializationException { - IRI customDatatype = factory.createIRI("http://example.org/myDataType"); - Literal customLiteral = factory.createLiteral("123", customDatatype, null); - - Statement stmt = factory.createStatement(mockExPerson, factory.createIRI("http://example.org/value"), customLiteral); - - Model currentTestModel = mock(Model.class); - when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); - - NQuadsSerializer serializer = new NQuadsSerializer(currentTestModel, NQuadsOption.defaultConfig()); - - StringWriter writer = new StringWriter(); - serializer.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"^^<%s>", - mockExPerson.stringValue(), - factory.createIRI("http://example.org/value").stringValue(), - escapeNQuadsString("123"), - customDatatype.stringValue()) + " .\n"; - - assertEquals(expectedOutput, writer.toString()); - } - - - private String escapeNQuadsString(String s) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\n': - sb.append("\\n"); - break; - case '\r': - sb.append("\\r"); - break; - case '\t': - sb.append("\\t"); - break; - case '\b': // backspace - sb.append("\\b"); - break; - case '\f': // form feed - sb.append("\\f"); - break; - case '"': - sb.append("\\\""); - break; - case '\\': - sb.append("\\\\"); - break; - default: - if (c <= 0x1F || c == 0x7F) { - sb.append(String.format("\\u%04X", (int) c)); - } else if (c >= 0x80 && c <= 0xFFFF) { - sb.append(String.format("\\u%04X", (int) c)); - } else if (Character.isHighSurrogate(c)) { - int codePoint = s.codePointAt(i); - if (Character.isValidCodePoint(codePoint)) { - sb.append(String.format("\\U%08X", codePoint)); - i++; - } else { - sb.append(c); - } - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - - private static class MockStatementIterator implements Iterator { - private final Statement[] statements; - private int index = 0; - - MockStatementIterator(Statement... statements) { - this.statements = statements; - } - - @Override - public boolean hasNext() { - return index < statements.length; - } - - @Override - public Statement next() { - return statements[index++]; - } - } -} 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 96% 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 c86abc768..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,7 +1,6 @@ -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 fr.inria.corese.core.next.impl.io.serialization.nquads.NQuadsOption; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -12,7 +11,7 @@ * 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") 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 2487730bd..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,10 +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.TestStatementFactory; -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.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; diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java deleted file mode 100644 index 3c24b1896..000000000 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/ntriples/NTriplesFormatTest.java +++ /dev/null @@ -1,367 +0,0 @@ -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.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; -import java.io.Writer; -import java.util.Iterator; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -class NTriplesSerializerTest { - - private Model model; - private NTriplesOption config; - private NTriplesSerializer nTriplesSerializer; - private TestStatementFactory factory; - - private Resource mockExPerson; - private IRI mockExName; - private IRI mockExKnows; - - private final String lexJohn = "John Doe"; - private final String hello = "Hello"; - - private Literal mockLiteralJohn; - private Literal mockLiteralHelloEn; - private Resource mockBNode1; - private Resource mockBNode2; - - @BeforeEach - void setUp() { - model = mock(Model.class); - config = NTriplesOption.defaultConfig(); - nTriplesSerializer = new NTriplesSerializer(model, config); - factory = new TestStatementFactory(); - - mockExPerson = factory.createIRI("http://example.org/Person"); - mockExName = factory.createIRI("http://example.org/name"); - mockExKnows = factory.createIRI("http://example.org/knows"); - - mockLiteralJohn = factory.createLiteral(lexJohn, null, null); - mockLiteralHelloEn = factory.createLiteral(hello, null, "en"); - - mockBNode1 = factory.createBlankNode("b1"); - mockBNode2 = factory.createBlankNode("b2"); - } - - @Test - @DisplayName("Constructor should throw NullPointerException for null model") - void constructorShouldThrowForNullModel() { - assertThrows(NullPointerException.class, () -> new NTriplesSerializer(null), "Model cannot be null"); - } - - @Test - @DisplayName("Constructor should throw NullPointerException for null configuration") - void constructorShouldThrowForNullConfig() { - assertThrows(NullPointerException.class, () -> new NTriplesSerializer(model, null), "Configuration cannot be null"); - } - - @Test - @DisplayName("Write should serialize a simple statement correctly (default graph)") - void writeShouldSerializeSimpleStatement() throws SerializationException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nTriplesSerializer.write(writer); - - String expected = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNTriplesString(lexJohn)) + " .\n"; - - Assertions.assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should serialize a statement with context but ignore it (N-Triples)") - void writeShouldSerializeStatementWithContext() throws SerializationException { - IRI mockContext = factory.createIRI("http://example.org/ctx"); - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn, - mockContext - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nTriplesSerializer.write(writer); - - String expected = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNTriplesString(lexJohn)) + " .\n"; - - Assertions.assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should handle blank nodes with default N-Triples prefix (_:)") - void writeShouldHandleBlankNodes() throws SerializationException { - Statement stmt = factory.createStatement( - mockBNode1, - mockExKnows, - mockBNode2 - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nTriplesSerializer.write(writer); - - String expected = String.format("_:%s <%s> _:%s", - mockBNode1.stringValue(), - mockExKnows.stringValue(), - mockBNode2.stringValue()) + " .\n"; - - Assertions.assertEquals(expected, writer.toString()); - } - - @Test - @DisplayName("Write should throw SerializationException on IO error") - void writeShouldThrowOnIOException() throws IOException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - 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()); - doThrow(new IOException("Simulated IO error (close)")).when(faultyWriter).close(); - - SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(faultyWriter)); - - assertEquals("N-Triples serialization failed [Format: N-Triples]", thrown.getMessage()); - } - - - @Test - @DisplayName("Write should throw SerializationException for null subject value in strict mode") - void writeShouldThrowOnNullSubjectValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(null); - when(stmt.getPredicate()).thenReturn(mockExName); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(stmt.getContext()).thenReturn(null); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); - - assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); - } - - @Test - @DisplayName("Write should throw SerializationException for null predicate value in strict mode") - void writeShouldThrowOnNullPredicateValue() { - Statement stmt = mock(Statement.class); - when(stmt.getSubject()).thenReturn(mockExPerson); - when(stmt.getPredicate()).thenReturn(null); - when(stmt.getObject()).thenReturn(mockLiteralJohn); - when(stmt.getContext()).thenReturn(null); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - SerializationException thrown = assertThrows(SerializationException.class, () -> nTriplesSerializer.write(writer)); - assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); - } - - @Test - @DisplayName("Write should throw SerializationException for null object value in strict mode") - void writeShouldThrowOnNullObjectValue() { - 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)); - assertEquals("Invalid N-Triples data: Value cannot be null in N-Triples format when strictMode is enabled. [Format: N-Triples]", thrown.getMessage()); - } - - - @Test - @DisplayName("Should handle null context correctly (default graph)") - void writeShouldHandleNullContext() throws SerializationException { - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - mockLiteralJohn, - null - ); - when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nTriplesSerializer.write(writer); - - - String expected = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - escapeNTriplesString(lexJohn)) + " .\n"; - - assertEquals(expected, writer.toString()); - } - - @ParameterizedTest - @ValueSource(strings = { - "simple literal", - "literal with \"quotes\"", - "literal with \\ backslash", - "literal with \n newline", - "literal with \t tab", - "literal with \r carriage return", - "literal with \u0001 (SOH)", - "literal with \u007F (DEL)" - }) - @DisplayName("Write should handle various literal values with appropriate escaping (including Unicode)") - void writeShouldHandleVariousLiterals(String literalValue) throws SerializationException { - Literal literalMock = factory.createLiteral(literalValue, null, null); - - Statement stmt = factory.createStatement( - mockExPerson, - mockExName, - literalMock - ); - Mockito.when(model.iterator()).thenReturn(new MockStatementIterator(stmt)); - - StringWriter writer = new StringWriter(); - nTriplesSerializer.write(writer); - - - String expectedEscapedLiteral = escapeNTriplesString(literalValue); - String expectedOutput = String.format("<%s> <%s> \"%s\"", - mockExPerson.stringValue(), - mockExName.stringValue(), - expectedEscapedLiteral) + " .\n"; - - 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 = Mockito.mock(Model.class); - Mockito.when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); - - Writer writer = new StringWriter(); - - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); - serializer.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"@%s", - mockExPerson.stringValue(), - factory.createIRI("http://example.org/greeting").stringValue(), - escapeNTriplesString(hello), - mockLiteralHelloEn.getLanguage().get()) + " .\n"; - - Assertions.assertEquals(expectedOutput, writer.toString()); - } - - - @Test - @DisplayName("Should handle literals with custom datatypes") - void shouldHandleLiteralsWithCustomDatatypes() throws SerializationException { - IRI customDatatype = factory.createIRI("http://example.org/myDataType"); - Literal customLiteral = factory.createLiteral("123", customDatatype, null); - - Statement stmt = factory.createStatement(mockExPerson, factory.createIRI("http://example.org/value"), customLiteral); - - Model currentTestModel = mock(Model.class); - when(currentTestModel.iterator()).thenReturn(new MockStatementIterator(stmt)); - - NTriplesSerializer serializer = new NTriplesSerializer(currentTestModel, NTriplesOption.defaultConfig()); - - StringWriter writer = new StringWriter(); - serializer.write(writer); - - String expectedOutput = String.format("<%s> <%s> \"%s\"^^<%s>", - mockExPerson.stringValue(), - factory.createIRI("http://example.org/value").stringValue(), - escapeNTriplesString("123"), - customDatatype.stringValue()) + " .\n"; - - assertEquals(expectedOutput, writer.toString()); - } - - - private String escapeNTriplesString(String s) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\n': - sb.append("\\n"); - break; - case '\r': - sb.append("\\r"); - break; - case '\t': - sb.append("\\t"); - break; - case '\b': - sb.append("\\b"); - break; - case '\f': - sb.append("\\f"); - break; - case '"': - sb.append("\\\""); - break; - case '\\': - sb.append("\\\\"); - break; - default: - if (c <= 0x1F || c == 0x7F) { - sb.append(String.format("\\u%04X", (int) c)); - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - - private static class MockStatementIterator implements Iterator { - private final Statement[] statements; - private int index = 0; - - MockStatementIterator(Statement... statements) { - this.statements = statements; - } - - @Override - public boolean hasNext() { - return index < statements.length; - } - - @Override - public Statement next() { - return statements[index++]; - } - } -} 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 96% 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 fea4ed524..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,7 +1,6 @@ -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 fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -12,7 +11,7 @@ * 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") 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 97% 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 47fa91787..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,17 +1,14 @@ -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.TestStatementFactory; -import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesOption; +import fr.inria.corese.core.next.impl.io.serialization.TestStatementFactory; import fr.inria.corese.core.next.impl.exception.SerializationException; -import fr.inria.corese.core.next.impl.io.serialization.ntriples.NTriplesSerializer; 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.ArgumentMatchers; import org.mockito.Mockito; import java.io.IOException; 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 98% 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 9bced5a61..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,8 +1,7 @@ -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.io.serialization.option.LiteralDatatypePolicyEnum; import fr.inria.corese.core.next.impl.io.serialization.option.PrefixOrderingEnum; -import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlOption; import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; 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 99% 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 0b1f12ebe..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,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.Model; import fr.inria.corese.core.next.api.Statement; -import fr.inria.corese.core.next.impl.io.serialization.rdfxml.XmlSerializer; +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.rdfxml.XmlOption; 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; 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 98% 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 0b33125e9..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,9 +1,8 @@ -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.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.trig.TriGOption; import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,7 +17,7 @@ * 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") 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 98% 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 64f5cdd8f..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,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.Statement; import fr.inria.corese.core.next.impl.common.literal.RDF; +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.trig.TriGOption; -import fr.inria.corese.core.next.impl.io.serialization.trig.TriGSerializer; 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; 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 98% 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 3183074d9..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,9 +1,8 @@ -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.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.turtle.TurtleOption; import fr.inria.corese.core.next.impl.io.serialization.util.SerializationConstants; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,7 +17,7 @@ * 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") 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 98% 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 f05c93574..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,11 @@ -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.io.serialization.TestStatementFactory; import fr.inria.corese.core.next.impl.io.serialization.option.LiteralDatatypePolicyEnum; -import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleOption; -import fr.inria.corese.core.next.impl.io.serialization.turtle.TurtleSerializer; 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; From cf4f824b7bb2dbd8b40071ab29523139599d35b0 Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Wed, 16 Jul 2025 17:34:52 +0200 Subject: [PATCH 29/31] removing unwanted file --- .gitignore | 1 + .sonarlint/connectedMode.json | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 .sonarlint/connectedMode.json diff --git a/.gitignore b/.gitignore index 2885ea863..c1877fba4 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,4 @@ gradle/gradle-daemon-jvm.properties # Fichiers de logs logs/ *.log +.sonarlint/ diff --git a/.sonarlint/connectedMode.json b/.sonarlint/connectedMode.json deleted file mode 100644 index f19bbef82..000000000 --- a/.sonarlint/connectedMode.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "sonarQubeUri": "https://sonarqube.inria.fr/sonarqube", - "projectKey": "corese" -} \ No newline at end of file From cd1ac3bac06abb05abd087f976be4de4a0041f0e Mon Sep 17 00:00:00 2001 From: Pierre Maillot Date: Thu, 17 Jul 2025 14:22:26 +0200 Subject: [PATCH 30/31] Comments, comments everywhere --- .../next/api/base/io/AbstractIOOptions.java | 3 + .../api/base/io/parser/AbstractRDFParser.java | 3 + .../io/parser/AbstractRDFParserFactory.java | 10 +++ .../core/next/api/io/parser/RDFParser.java | 6 ++ .../io/parser/RDFParserBaseIRIOptions.java | 3 + .../next/api/io/parser/RDFParserFactory.java | 3 + .../next/api/io/parser/RDFParserOptions.java | 3 + .../api/io/serialization/RDFSerializer.java | 5 +- .../RDFSerializerBNPrefixOptions.java | 3 + ...onConfig.java => SerializationOption.java} | 2 +- .../io/serialization/SerializerFactory.java | 4 +- .../impl/exception/ParsingErrorException.java | 3 + .../UnsupportedFileFormatException.java | 3 + .../next/impl/io/parser/ParserFactory.java | 18 +++++ .../impl/io/parser/jsonld/JSONLDParser.java | 6 ++ .../io/parser/turtle/ANTLRTurtleParser.java | 5 ++ .../DefaultSerializerFactory.java | 17 ++--- .../jsonld/JSONLDSerializer.java | 11 ++- ...itaniumRDFDatasetSerializationAdapter.java | 75 +++++++++++++++++-- .../option/AbstractSerializerOption.java | 4 +- .../DefaultSerializerFactoryTest.java | 7 +- .../jsonld/JSONLDSerializerTest.java | 9 +++ 22 files changed, 172 insertions(+), 31 deletions(-) rename src/main/java/fr/inria/corese/core/next/api/io/serialization/{SerializationConfig.java => SerializationOption.java} (92%) 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 index a97c242ce..e8a820c58 100644 --- 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 @@ -2,6 +2,9 @@ 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> { 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 index 0ed5dd3e7..d5016e189 100644 --- 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 @@ -11,6 +11,9 @@ 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; 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 index adc0e2702..babc77fa8 100644 --- 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 @@ -6,11 +6,21 @@ 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/io/parser/RDFParser.java b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java index 34c851c57..fab2aaebf 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/parser/RDFParser.java @@ -6,6 +6,12 @@ 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 { /** 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 index 58e85cae6..e593843fb 100644 --- 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 @@ -2,6 +2,9 @@ import fr.inria.corese.core.next.api.io.IOOptions; +/** + * Options for RDF parsers that support a base IRI. + */ public interface RDFParserBaseIRIOptions extends RDFParserOptions, IOOptions { /** 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 index 5c5d7596e..c82293bb4 100644 --- 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 @@ -4,6 +4,9 @@ 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 { 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 index cc65d5d44..428c59c66 100644 --- 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 @@ -2,5 +2,8 @@ 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/io/serialization/RDFSerializer.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java index bc08a5592..6eb592a0e 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/RDFSerializer.java @@ -1,6 +1,7 @@ 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; @@ -9,8 +10,8 @@ * 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. 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 index cb9ffff92..fe8f8257f 100644 --- 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 @@ -1,5 +1,8 @@ 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 { /** diff --git a/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationConfig.java b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java similarity index 92% rename from src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationConfig.java rename to src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java index 982bf8e41..692dc6237 100644 --- a/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationConfig.java +++ b/src/main/java/fr/inria/corese/core/next/api/io/serialization/SerializationOption.java @@ -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 index b049c6419..594c4f87d 100644 --- 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 @@ -8,7 +8,7 @@ * 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}. + * {@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. @@ -16,5 +16,5 @@ public interface SerializerFactory { - RDFSerializer createSerializer(RDFFormat format, Model model, SerializationConfig config); + RDFSerializer createSerializer(RDFFormat format, Model model, SerializationOption config); } 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 8eded6714..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 @@ -3,6 +3,9 @@ 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/UnsupportedFileFormatException.java b/src/main/java/fr/inria/corese/core/next/impl/exception/UnsupportedFileFormatException.java index 2521fa74c..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 @@ -2,6 +2,9 @@ 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/parser/ParserFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/parser/ParserFactory.java index 25507e24c..081cb1296 100644 --- 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 @@ -9,12 +9,23 @@ 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) { @@ -25,6 +36,13 @@ public RDFParser createRDFParser(RDFFormat format, Model model, ValueFactory fac 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) { 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 index 245c0de7d..6a066e801 100644 --- 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 @@ -20,6 +20,12 @@ 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); 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 dca347f8a..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 @@ -20,6 +20,11 @@ import java.io.InputStreamReader; import java.io.Reader; +/** + * 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) { diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java index b07fa390e..ed7e35d65 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactory.java @@ -3,13 +3,12 @@ import fr.inria.corese.core.next.api.Model; 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.SerializationConfig; +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.option.*; 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; @@ -32,7 +31,7 @@ * 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.

*/ @@ -40,17 +39,17 @@ 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 + * 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 TurtleOption specificConfig) { @@ -110,19 +109,19 @@ public DefaultSerializerFactory() { * * @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. + * @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(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()); 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 index f9e67bec7..c654e00f4 100644 --- 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 @@ -15,7 +15,8 @@ import java.util.Objects; /** - * Serializer for JSON-LD format. + * Serializer for JSON-LD format. This serializer uses the Titanium library. + * @see Titanium JSON-LD */ public class JSONLDSerializer implements RDFSerializer { @@ -24,14 +25,18 @@ public class JSONLDSerializer implements RDFSerializer { /** * Constructor. - * @param model - * @param config + * @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()); } 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 index 794e1ca53..80dcffdb1 100644 --- 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 @@ -25,6 +25,7 @@ /** * 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 { @@ -107,6 +108,11 @@ 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 @@ -131,28 +137,35 @@ public RdfValue 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() { - logger.debug("getSubject: {}", statement.getSubject().stringValue()); return toRdfResource(statement.getSubject()); } @Override public RdfResource getPredicate() { - logger.debug("getPredicate: {}", statement.getPredicate().stringValue()); return toRdfResource(statement.getPredicate()); } @Override public RdfValue getObject() { - logger.debug("getObject: {}", statement.getObject().stringValue()); 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"); @@ -177,21 +190,28 @@ public String getValue() { }; } + /** + * 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()) { - logger.debug("toRdfValue: {} -> IRI", value.stringValue()); return toRdfIRI((IRI) value); } else if (value.isBNode()) { - logger.debug("toRdfValue: {} -> BNode", value.stringValue()); return toRdfBlankNode((BNode) value); } else if (value.isLiteral()) { - logger.debug("toRdfValue: {} -> Literal", value.stringValue()); 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 @@ -205,6 +225,11 @@ public String getValue() { }; } + /** + * 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 @@ -218,8 +243,12 @@ public String getValue() { }; } + /** + * Converts a Corese Literal to a titanium RDF Literal + * @param literal the Literal to convert + * @return the converted Literal + */ private RdfLiteral toRdfLiteral(Literal literal) { - logger.debug("toRdfLiteral: {} {} {}", literal.stringValue(), literal.getDatatype().stringValue(), literal.getLanguage()); return new RdfLiteral() { @Override public boolean isLiteral() { @@ -254,6 +283,11 @@ public Optional 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); @@ -266,6 +300,11 @@ private Value toValue(RdfValue value) { } } + /** + * 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); @@ -276,6 +315,11 @@ private Resource toResource(RdfResource resource) { } } + /** + * 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()); @@ -283,6 +327,11 @@ private IRI toIRI(RdfResource resource) { 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() { @@ -300,8 +349,12 @@ public String getID() { return null; } + /** + * Convert a Titanium RdfLiteral to a Corese Literal + * @param literal the Titanium RdfLiteral + * @return the Corese Literal + */ private Literal toLiteral(RdfLiteral literal) { - logger.debug("Converting literal: {}", literal); return new Literal() { @Override public String stringValue() { @@ -394,6 +447,12 @@ public CoreDatatype getCoreDatatype() { }; } + /** + * 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"); diff --git a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java index 1c8aa8d6a..e1a51ef5b 100644 --- a/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java +++ b/src/main/java/fr/inria/corese/core/next/impl/io/serialization/option/AbstractSerializerOption.java @@ -1,6 +1,6 @@ package fr.inria.corese.core.next.impl.io.serialization.option; -import fr.inria.corese.core.next.api.io.serialization.SerializationConfig; +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 AbstractSerializerOption implements SerializationConfig { +public abstract class AbstractSerializerOption implements SerializationOption { /** * The policy for how literal datatypes are printed. diff --git a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java index 5b3eaa15e..cbc605952 100644 --- a/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java +++ b/src/test/java/fr/inria/corese/core/next/impl/io/serialization/DefaultSerializerFactoryTest.java @@ -3,8 +3,7 @@ import fr.inria.corese.core.next.api.Model; 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.SerializationConfig; -import fr.inria.corese.core.next.impl.io.serialization.*; +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; @@ -29,14 +28,14 @@ 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 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 index 3c33b08e9..b8a97059d 100644 --- 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 @@ -36,6 +36,9 @@ 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 @@ -87,6 +90,9 @@ public void smallModelTest() { 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 @@ -138,6 +144,9 @@ public void modelWithBlankNodesTest() { 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 From 9cd6442649b7569feea40352c2f06f10cd8dc6e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20C=C3=A9r=C3=A8s?= Date: Mon, 21 Jul 2025 11:19:13 +0200 Subject: [PATCH 31/31] Refactor build.gradle.kts to enhance JavaCC and Antlr source generation configuration --- build.gradle.kts | 56 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0e925e654..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") } @@ -338,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") +}