Skip to content

Commit a28e7a0

Browse files
authored
Merge pull request #258 from Ostrzyciel/add-jelly
Add the Jelly output format
2 parents a6e67cd + a635bd1 commit a28e7a0

File tree

13 files changed

+141
-58
lines changed

13 files changed

+141
-58
lines changed

.gitattributes

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
docs/apidocs/* binary
2+
3+
# Mark Jelly files as binary
4+
*.jelly binary

README.md

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ and see [Usage](#cli) on how to use the commandline interface!
5656
- For examples on how to use functions within RML mapping documents, you can have a look at the [RML+FnO test cases](https://github.com/RMLio/rml-fno-test-cases)
5757
- configuration file
5858
- metadata generation
59-
- output formats: nquads (default), turtle, trig, trix, jsonld, hdt
59+
- output formats: nquads (default), turtle, trig, trix, jsonld, hdt, [jelly](https://w3id.org/jelly)
6060
- join conditions
6161
- targets:
6262
- local file
@@ -104,7 +104,7 @@ The following options are most common.
104104

105105
- `-m, --mapping <arg>`: one or more mapping file paths and/or strings (multiple values are concatenated).
106106
- `-o, --output <arg>`: path to output file
107-
- `-s,--serialization <arg>`: serialization format (nquads (default), trig, trix, jsonld, hdt)
107+
- `-s,--serialization <arg>`: serialization format (nquads (default), trig, trix, jsonld, hdt, [jelly](https://w3id.org/jelly))
108108

109109
All options can be found when executing `java -jar rmlmapper.jar --help`,
110110
that output is found below.
@@ -148,7 +148,7 @@ options:
148148
passwords, certificates, etc.
149149
-s,--serialization <arg> serialization format (nquads
150150
(default), turtle, trig, trix,
151-
jsonld, hdt)
151+
jsonld, hdt, jelly)
152152
--strict Enable strict mode. In strict mode,
153153
the mapper will fail on invalid IRIs
154154
instead of skipping them.
@@ -307,31 +307,34 @@ The tests will fail otherwise, as Testcontainers can't spin up the container.
307307

308308
## Dependencies
309309

310-
| Dependency | License |
311-
|:----------------------------------------------:|--------------------------------------------------------------------|
312-
| ch.qos.logback logback-classic | Eclipse Public License 1.0 & GNU Lesser General Public License 2.1 |
313-
| com.github.fnoio function-agent-java | MIT |
314-
| com.github.fnoio grel-functions-java | MIT |
315-
| com.github.fnoio idlab-functions-java | MIT |
316-
| com.github.rdfhdt hdt-java | GNU Lesser General Public License v3.0 |
317-
| com.github.tomakehurst:wiremock-jre8 | Apache License 2.0 |
318-
| com.microsoft.sqlserver mssql-jdbc | MIT |
319-
| com.mysql mysql-connector-java | GNU General Public License v2.0 |
320-
| com.oracle.database.jdbc:ojdbc11 | Oracle Free Use Terms and Conditions |
321-
| net.minidev json-smart | Apache License 2.0 |
322-
| org.apache.jena fuseki-main | Apache License 2.0 |
323-
| org.eclipse.rdf4j rdf4j-client | Eclipse Distribution License v1.0 |
324-
| org.junit.jupiter junit-jupiter-api | Eclipse Public License v2.0 |
325-
| org.junit.jupiter junit-jupiter-engine | Eclipse Public License v2.0 |
326-
| org.junit.jupiter junit-jupiter-params | Eclipse Public License v2.0 |
327-
| org.junit.vintage junit-vintage-engine | Eclipse Public License v2.0 |
328-
| org.postgresql postgresql | BSD |
329-
| org.testcontainers jdbc | MIT |
330-
| org.testcontainers junit-jupiter | MIT |
331-
| org.testcontainers mssqlserver | MIT |
332-
| org.testcontainers mysql | MIT |
333-
| org.testcontainers oracle-xe | MIT |
334-
| org.testcontainers postgresql | MIT |
310+
| Dependency | License |
311+
|:--------------------------------------:|--------------------------------------------------------------------|
312+
| ch.qos.logback logback-classic | Eclipse Public License 1.0 & GNU Lesser General Public License 2.1 |
313+
| com.github.fnoio function-agent-java | MIT |
314+
| com.github.fnoio grel-functions-java | MIT |
315+
| com.github.fnoio idlab-functions-java | MIT |
316+
| com.github.rdfhdt hdt-java | GNU Lesser General Public License v3.0 |
317+
| com.github.tomakehurst:wiremock-jre8 | Apache License 2.0 |
318+
| com.google.protobuf protobuf-java | BSD 3-clause |
319+
| com.microsoft.sqlserver mssql-jdbc | MIT |
320+
| com.mysql mysql-connector-java | GNU General Public License v2.0 |
321+
| com.oracle.database.jdbc:ojdbc11 | Oracle Free Use Terms and Conditions |
322+
| eu.neverblink.jelly jelly-core | Apache License 2.0 |
323+
| eu.neverblink.jelly jelly-rdf4j | Apache License 2.0 |
324+
| net.minidev json-smart | Apache License 2.0 |
325+
| org.apache.jena fuseki-main | Apache License 2.0 |
326+
| org.eclipse.rdf4j rdf4j-client | Eclipse Distribution License v1.0 |
327+
| org.junit.jupiter junit-jupiter-api | Eclipse Public License v2.0 |
328+
| org.junit.jupiter junit-jupiter-engine | Eclipse Public License v2.0 |
329+
| org.junit.jupiter junit-jupiter-params | Eclipse Public License v2.0 |
330+
| org.junit.vintage junit-vintage-engine | Eclipse Public License v2.0 |
331+
| org.postgresql postgresql | BSD |
332+
| org.testcontainers jdbc | MIT |
333+
| org.testcontainers junit-jupiter | MIT |
334+
| org.testcontainers mssqlserver | MIT |
335+
| org.testcontainers mysql | MIT |
336+
| org.testcontainers oracle-xe | MIT |
337+
| org.testcontainers postgresql | MIT |
335338

336339
## Commercial Support
337340

buildNumber.properties

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
#maven.buildNumber.plugin properties file
2-
#Tue Aug 13 08:29:04 GMT 2024
3-
buildNumber0=373
4-
2+
#Sun Jun 08 18:28:21 CEST 2025
3+
buildNumber0=378

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
<maven.compiler.source>17</maven.compiler.source>
4040
<maven.compiler.target>17</maven.compiler.target>
4141
<jena.version>5.0.0</jena.version>
42+
<jelly.version>3.2.0</jelly.version>
4243
<testcontainers.version>1.18.3</testcontainers.version>
4344
</properties>
4445

@@ -263,6 +264,17 @@
263264
</exclusion>
264265
</exclusions>
265266
</dependency>
267+
<dependency>
268+
<groupId>eu.neverblink.jelly</groupId>
269+
<artifactId>jelly-rdf4j</artifactId>
270+
<version>${jelly.version}</version>
271+
<exclusions> <!-- Exclude RDF4J, use the version from the rdf4j-client dependency -->
272+
<exclusion>
273+
<groupId>org.eclipse.rdf4j</groupId>
274+
<artifactId>*</artifactId>
275+
</exclusion>
276+
</exclusions>
277+
</dependency>
266278
<dependency>
267279
<groupId>be.ugent.idlab.knows</groupId>
268280
<artifactId>function-agent-java</artifactId>

src/main/java/be/ugent/rml/cli/Main.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public static void run(String[] args, String basePath) throws Exception {
127127
.build();
128128
Option serializationFormatOption = Option.builder("s")
129129
.longOpt("serialization")
130-
.desc("serialization format (nquads (default), turtle, trig, trix, jsonld, hdt)")
130+
.desc("serialization format (nquads (default), turtle, trig, trix, jsonld, hdt, jelly)")
131131
.hasArg()
132132
.build();
133133
Option jdbcDSNOption = Option.builder("dsn")
@@ -545,12 +545,7 @@ private static void writeOutputTargets(Map<Term, QuadStore> targets, QuadStore r
545545
String serializationFormat = target.getSerializationFormat();
546546
OutputStream output = target.getOutputStream();
547547
store.addQuads(target.getMetadata());
548-
549-
// Set character encoding
550-
try (Writer out = new BufferedWriter(new OutputStreamWriter(output, Charset.defaultCharset()))) {
551-
// Write store to target
552-
store.write(out, serializationFormat);
553-
}
548+
store.write(output, serializationFormat);
554549
// Close OS resources
555550
target.close();
556551
logger.debug("Exporting to Target: {}", target);
@@ -637,7 +632,7 @@ private static File writeOutputUncompressed(QuadStore store, String outputFile,
637632
logger.info("{} quad was generated for default Target", store.size());
638633
}
639634

640-
Writer out = null;
635+
OutputStream out = null;
641636
try {
642637

643638
String doneMessage = null;
@@ -653,11 +648,11 @@ private static File writeOutputUncompressed(QuadStore store, String outputFile,
653648

654649
doneMessage = "Writing to " + targetFile.getPath() + " is done.";
655650

656-
out = Files.newBufferedWriter(targetFile.toPath(), StandardCharsets.UTF_8);
651+
out = Files.newOutputStream(targetFile.toPath());
657652

658653
} else {
659654
isSystemOut = true;
660-
out = new BufferedWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8));
655+
out = System.out;
661656
}
662657

663658
store.write(out, format);

src/main/java/be/ugent/rml/store/QuadStore.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,29 +127,31 @@ public abstract class QuadStore {
127127
public abstract void read(InputStream is, String base, RDFFormat format) throws Exception;
128128

129129
/**
130-
* Write out the QuadStore in given format
131-
* TODO use class or enum for output format
130+
* Write out the QuadStore in given format.
131+
* Deprecated, use write(OutputStream out, String format) instead.
132+
* TODO remove this method in future versions, use write(OutputStream out, String format) instead.
132133
*
133134
* @param out Writer output location
134135
* @param format QuadStore format (.TTL)
135136
* @throws Exception
136137
*/
138+
@Deprecated
137139
public abstract void write(Writer out, String format) throws Exception;
138140

139-
// END OF ABSTRACT METHODS
140-
141-
// following final methods use the abstract methods to provide additional functionality or helper functions
142141
/**
143-
* Helper function
142+
* Write out the QuadStore in given format, using a binary output stream.
143+
* Override this method if you want to support binary formats like Jelly.
144+
* TODO use class or enum for output format
144145
*
145-
* @param out
146-
* @param format
146+
* @param out OutputStream to write to
147+
* @param format QuadStore format (.TTL)
147148
* @throws Exception
148149
*/
149-
public final void write(ByteArrayOutputStream out, String format) throws Exception {
150-
write(new BufferedWriter(new OutputStreamWriter(out)), format);
151-
}
150+
public abstract void write(OutputStream out, String format) throws Exception;
152151

152+
// END OF ABSTRACT METHODS
153+
154+
// following final methods use the abstract methods to provide additional functionality or helper functions
153155
/**
154156
* Helper function
155157
*

src/main/java/be/ugent/rml/store/RDF4JStore.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import be.ugent.rml.term.Literal;
55
import be.ugent.rml.term.NamedNode;
66
import be.ugent.rml.term.Term;
7+
import eu.neverblink.jelly.convert.rdf4j.rio.JellyFormat;
8+
import eu.neverblink.jelly.convert.rdf4j.rio.JellyWriterSettings;
9+
import eu.neverblink.jelly.core.JellyOptions;
710
import org.eclipse.rdf4j.model.*;
811
import org.eclipse.rdf4j.model.impl.*;
912
import org.eclipse.rdf4j.model.util.Models;
@@ -15,8 +18,7 @@
1518
import org.slf4j.Logger;
1619
import org.slf4j.LoggerFactory;
1720

18-
import java.io.InputStream;
19-
import java.io.Writer;
21+
import java.io.*;
2022
import java.util.ArrayList;
2123
import java.util.List;
2224
import java.util.Optional;
@@ -172,11 +174,29 @@ public void write(Writer out, String format) throws Exception {
172174
case "ntriples":
173175
Rio.write(model, out, RDFFormat.NTRIPLES);
174176
break;
177+
case "jelly":
178+
throw new UnsupportedOperationException(
179+
"Writing Jelly format to a Writer is not supported. Use OutputStream instead."
180+
);
175181
default:
176182
throw new Exception("Serialization " + format + " not supported");
177183
}
178184
}
179185

186+
@Override
187+
public void write(OutputStream out, String format) throws Exception {
188+
// Jelly is the only format that requires a binary output stream
189+
if (format.equals("jelly")) {
190+
var settings = JellyWriterSettings.empty();
191+
// Mark RDF-star as not used
192+
settings.setJellyOptions(JellyOptions.BIG_STRICT);
193+
Rio.write(model, out, JellyFormat.JELLY, settings);
194+
} else {
195+
// For all other formats, fall back to using the Writer
196+
write(new BufferedWriter(new OutputStreamWriter(out)), format);
197+
}
198+
}
199+
180200
public String getBase() {
181201
Optional<Namespace> base = model.getNamespace("");
182202
if (base.isPresent()) {

src/main/java/be/ugent/rml/store/SimpleQuadStore.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public void write(Writer out, String format) throws IOException {
118118
}
119119
}
120120

121+
@Override
122+
public void write(OutputStream out, String format) throws IOException {
123+
write(new BufferedWriter(new OutputStreamWriter(out)), format);
124+
}
125+
121126
@Override
122127
public boolean equals(Object o) {
123128
throw new UnsupportedOperationException("Method not implemented.");

src/test/java/be/ugent/rml/ArgumentsTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,28 @@ public void outputHDT() throws Exception {
378378
}
379379
}
380380

381+
@Test
382+
public void outputJelly() throws Exception {
383+
String cwd = Utils.getFile("argument").getAbsolutePath();
384+
String mappingFilePath = (new File(cwd, "mapping.ttl")).getAbsolutePath();
385+
String actualJellyPath = (new File("./generated_output.jelly")).getAbsolutePath();
386+
String expectedJellyPath = Utils.getFile( "argument/output-jelly/target_output.jelly").getAbsolutePath();
387+
388+
Main.run(new String[]{"-m" , mappingFilePath , "-o" , actualJellyPath , "-s", "jelly"}, cwd);
389+
compareFiles(
390+
expectedJellyPath,
391+
actualJellyPath,
392+
false
393+
);
394+
395+
try {
396+
File outputFile = Utils.getFile(actualJellyPath);
397+
assertTrue(outputFile.delete());
398+
} catch (Exception e) {
399+
e.printStackTrace();
400+
}
401+
}
402+
381403

382404
@Test
383405
public void quoteInLiteral() throws Exception {

src/test/java/be/ugent/rml/TestCore.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import be.ugent.rml.target.TargetFactory;
1313
import be.ugent.rml.term.NamedNode;
1414
import be.ugent.rml.term.Term;
15+
import eu.neverblink.jelly.convert.rdf4j.rio.JellyFormat;
1516
import org.eclipse.rdf4j.rio.RDFFormat;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
@@ -351,6 +352,8 @@ protected QuadStore filePathToStore(String path) throws Exception {
351352
store = QuadStoreFactory.read(outputFile, RDFFormat.JSONLD);
352353
} else if (path.endsWith(".trig")) {
353354
store = QuadStoreFactory.read(outputFile, RDFFormat.TRIG);
355+
} else if (path.endsWith(".jelly")) {
356+
store = QuadStoreFactory.read(outputFile, JellyFormat.JELLY);
354357
} else {
355358
store = QuadStoreFactory.read(outputFile);
356359
}

0 commit comments

Comments
 (0)