-
Notifications
You must be signed in to change notification settings - Fork 2
Helper methods for RML to MTL conversion #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
69e1b1f
896741c
2561cb9
1b1d49c
5385156
e0da20f
f4d6dd8
f2d82b6
60d2634
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |||||||||||||||||||
|
|
||||||||||||||||||||
| package com.cefriel.template.utils; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import com.cefriel.template.TemplateExecutor; | ||||||||||||||||||||
| import com.cefriel.template.TemplateMap; | ||||||||||||||||||||
| import com.cefriel.template.io.Formatter; | ||||||||||||||||||||
| import com.cefriel.template.io.Reader; | ||||||||||||||||||||
|
|
@@ -30,9 +31,11 @@ | |||||||||||||||||||
| import org.apache.velocity.VelocityContext; | ||||||||||||||||||||
| import org.apache.velocity.app.VelocityEngine; | ||||||||||||||||||||
| import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; | ||||||||||||||||||||
| import org.apache.velocity.runtime.resource.loader.FileResourceLoader; | ||||||||||||||||||||
| import org.apache.velocity.tools.generic.*; | ||||||||||||||||||||
| import org.eclipse.rdf4j.common.exception.ValidationException; | ||||||||||||||||||||
| import org.eclipse.rdf4j.model.Model; | ||||||||||||||||||||
| import org.eclipse.rdf4j.model.base.CoreDatatype; | ||||||||||||||||||||
| import org.eclipse.rdf4j.model.vocabulary.RDF4J; | ||||||||||||||||||||
| import org.eclipse.rdf4j.model.vocabulary.SHACL; | ||||||||||||||||||||
| import org.eclipse.rdf4j.repository.RepositoryConnection; | ||||||||||||||||||||
|
|
@@ -45,6 +48,7 @@ | |||||||||||||||||||
| import org.slf4j.Logger; | ||||||||||||||||||||
| import org.slf4j.LoggerFactory; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| import java.io.ByteArrayInputStream; | ||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||
| import java.io.InputStream; | ||||||||||||||||||||
| import java.nio.charset.StandardCharsets; | ||||||||||||||||||||
|
|
@@ -195,11 +199,16 @@ public static VelocityEngine createVelocityEngine(boolean templateInResources, b | |||||||||||||||||||
| velocityEngine.setProperty("resource.loaders", "class"); | ||||||||||||||||||||
| velocityEngine.setProperty("resource.loader.class.class", | ||||||||||||||||||||
| ClasspathResourceLoader.class.getName()); | ||||||||||||||||||||
| } else{ | ||||||||||||||||||||
| velocityEngine.setProperty("resource.loaders", "file"); | ||||||||||||||||||||
| velocityEngine.setProperty("resource.loader.file.class", FileResourceLoader.class.getName()); | ||||||||||||||||||||
| velocityEngine.setProperty("resource.loader.file.path", ""); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| velocityEngine.init(); | ||||||||||||||||||||
| return velocityEngine; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| public static void validateRML(Path templatePath, boolean verbose) { | ||||||||||||||||||||
|
|
||||||||||||||||||||
| public static void validateRML(InputStream rmlMapping, boolean verbose) { | ||||||||||||||||||||
|
|
||||||||||||||||||||
| ShaclSail shaclSail = new ShaclSail(new MemoryStore()); | ||||||||||||||||||||
| SailRepository repository = new SailRepository(shaclSail); | ||||||||||||||||||||
|
|
@@ -208,33 +217,25 @@ public static void validateRML(Path templatePath, boolean verbose) { | |||||||||||||||||||
| try (RepositoryConnection connection = repository.getConnection()) { | ||||||||||||||||||||
| try (InputStream shapesStream = Util.class.getResourceAsStream("/rml/core.ttl")) { | ||||||||||||||||||||
| Model rules = Rio.parse(shapesStream, RDFFormat.TURTLE); | ||||||||||||||||||||
| // cf. https://github.com/eclipse-rdf4j/rdf4j/discussions/4287 | ||||||||||||||||||||
| rules.remove(null, SHACL.NAME, null); | ||||||||||||||||||||
| rules.remove(null, SHACL.DESCRIPTION, null); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| connection.begin(); | ||||||||||||||||||||
| connection.add(rules, RDF4J.SHACL_SHAPE_GRAPH); | ||||||||||||||||||||
| connection.commit(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Load RML | ||||||||||||||||||||
| try (InputStream dataStream = Files.newInputStream(templatePath)) { | ||||||||||||||||||||
| connection.begin(); | ||||||||||||||||||||
| connection.add(dataStream, "", org.eclipse.rdf4j.rio.RDFFormat.TURTLE); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| try { | ||||||||||||||||||||
| connection.commit(); | ||||||||||||||||||||
| log.info("RML validated correctly"); | ||||||||||||||||||||
| } catch (RepositoryException exception) { | ||||||||||||||||||||
| Throwable cause = exception.getCause(); | ||||||||||||||||||||
| log.error("RML not valid"); | ||||||||||||||||||||
| if (verbose) | ||||||||||||||||||||
| if (cause instanceof ValidationException) { | ||||||||||||||||||||
| Model validationReportModel = ((ValidationException) cause).validationReportAsModel(); | ||||||||||||||||||||
| Rio.write(validationReportModel, System.out, RDFFormat.TURTLE); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| throw exception; | ||||||||||||||||||||
| connection.begin(); | ||||||||||||||||||||
| connection.add(rmlMapping, "", RDFFormat.TURTLE); | ||||||||||||||||||||
| try { | ||||||||||||||||||||
| connection.commit(); | ||||||||||||||||||||
| log.info("RML validated correctly"); | ||||||||||||||||||||
| } catch (RepositoryException exception) { | ||||||||||||||||||||
| Throwable cause = exception.getCause(); | ||||||||||||||||||||
| log.error("RML not valid"); | ||||||||||||||||||||
| if (verbose && cause instanceof ValidationException) { | ||||||||||||||||||||
| Model validationReportModel = ((ValidationException) cause).validationReportAsModel(); | ||||||||||||||||||||
| Rio.write(validationReportModel, System.out, RDFFormat.TURTLE); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| throw exception; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } catch (Exception e) { | ||||||||||||||||||||
| throw new RuntimeException(e); | ||||||||||||||||||||
|
|
@@ -243,6 +244,7 @@ public static void validateRML(Path templatePath, boolean verbose) { | |||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
|
|
||||||||||||||||||||
| /** | ||||||||||||||||||||
| * Creates a new {@link VelocityContext} and populates it with the provided readers, template map, and template functions. | ||||||||||||||||||||
| * Additionally, it adds a set of common tools for mathematical operations, number formatting, date manipulation, | ||||||||||||||||||||
|
|
@@ -331,4 +333,46 @@ public static VelocityContext createVelocityContext(Reader reader, TemplateMap t | |||||||||||||||||||
| public static VelocityContext createVelocityContext(Map<String, Reader> readers, TemplateMap templateMap) { | ||||||||||||||||||||
| return createVelocityContext(readers, templateMap, new TemplateFunctions()); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| /** | ||||||||||||||||||||
| * Compiles an MTL mapping from the given RML file. | ||||||||||||||||||||
| * | ||||||||||||||||||||
| * @param mappingRML Path to the RML mapping file. | ||||||||||||||||||||
| * @param baseIri Base IRI to use if not found in the mapping. | ||||||||||||||||||||
| * @param basePath Base path for output files. | ||||||||||||||||||||
| * @param trimTemplate Whether to use the trimmed template. | ||||||||||||||||||||
| * @param verbose Enable verbose validation output. | ||||||||||||||||||||
| * @return Path to the compiled template. | ||||||||||||||||||||
| * @throws Exception if validation or compilation fails. | ||||||||||||||||||||
| */ | ||||||||||||||||||||
| public static Path compiledMTLMapping(InputStream mappingRML, String baseIri, Path basePath, boolean trimTemplate, boolean verbose) throws Exception { | ||||||||||||||||||||
|
Comment on lines
+346
to
+348
|
||||||||||||||||||||
| * @throws Exception if validation or compilation fails. | |
| */ | |
| public static Path compiledMTLMapping(InputStream mappingRML, String baseIri, Path basePath, boolean trimTemplate, boolean verbose) throws Exception { | |
| * @throws IOException if an I/O error occurs during reading or writing files. | |
| * @throws ValidationException if RML validation fails. | |
| * @throws RepositoryException if an RDF repository error occurs. | |
| */ | |
| public static Path compiledMTLMapping(InputStream mappingRML, String baseIri, Path basePath, boolean trimTemplate, boolean verbose) | |
| throws IOException, ValidationException, RepositoryException { |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |||||
| import org.eclipse.rdf4j.rio.helpers.StatementCollector; | ||||||
| import org.junit.jupiter.api.Test; | ||||||
|
|
||||||
| import java.io.InputStream; | ||||||
| import java.io.StringReader; | ||||||
| import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | ||||||
|
|
@@ -40,54 +41,48 @@ | |||||
|
|
||||||
| public class RMLTests { | ||||||
|
|
||||||
| final static String FOLDER = "src/test/resources/rml/"; | ||||||
| private String resolvePath(String folder, String file) { | ||||||
| return FOLDER + file; | ||||||
| } | ||||||
| final static Path FOLDER = Path.of("src/test/resources/rml/"); | ||||||
|
|
||||||
| @Test | ||||||
| public void invalidRMLTest() throws Exception { | ||||||
| String folder = "rml"; | ||||||
| Path rmlMappings = Paths.get(resolvePath(folder, "invalid-mapping.ttl")); | ||||||
| assertThrows(RuntimeException.class, () -> Util.validateRML(rmlMappings, false)); | ||||||
| Path rmlMappings = FOLDER.resolve(Path.of("invalid-mapping.ttl")); | ||||||
| try (InputStream rmlMapping = Files.newInputStream(rmlMappings)) { | ||||||
| assertThrows(RuntimeException.class, | ||||||
| () -> Util.validateRML(rmlMapping, false)); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| @Test | ||||||
| public void validRMLTest() throws Exception { | ||||||
| Path rmlMapping = FOLDER.resolve(Path.of("mapping.ttl")); | ||||||
| String expectedOutput = Files.readString(FOLDER.resolve("output.nq")); | ||||||
|
|
||||||
| String folder = "rml"; | ||||||
| String rmlMappings = resolvePath(folder, "mapping.ttl"); | ||||||
|
|
||||||
| String expectedOutput = Files.readString(Paths.get(resolvePath(folder, "output.nq"))); | ||||||
| try (InputStream rmlMappingStream = Files.newInputStream(rmlMapping)) { | ||||||
| Util.validateRML(rmlMappingStream, false); | ||||||
| } | ||||||
|
|
||||||
| Util.validateRML(Paths.get(rmlMappings), false); | ||||||
|
|
||||||
| Reader compilerReader = TemplateFunctions.getRDFReaderFromFile(rmlMappings); | ||||||
| Path rmlCompiler = Paths.get("rml/rml-compiler.vm"); | ||||||
| Path compiledTemplatePath = Paths.get(resolvePath(folder,"template.rml.vm")); | ||||||
| Reader compilerReader = TemplateFunctions.getRDFReaderFromFile(rmlMapping.toString()); | ||||||
|
|
||||||
| Map<String,String> rmlMap = new HashMap<>(); | ||||||
| rmlMap.put("basePath", FOLDER); | ||||||
| rmlMap.put("basePath", null); | ||||||
|
||||||
| rmlMap.put("basePath", null); | |
| rmlMap.put("basePath", ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import appears to be unused. Consider removing it to keep the imports clean.