1616
1717package com .cefriel .template .utils ;
1818
19+ import com .cefriel .template .TemplateExecutor ;
1920import com .cefriel .template .TemplateMap ;
2021import com .cefriel .template .io .Formatter ;
2122import com .cefriel .template .io .Reader ;
3031import org .apache .velocity .VelocityContext ;
3132import org .apache .velocity .app .VelocityEngine ;
3233import org .apache .velocity .runtime .resource .loader .ClasspathResourceLoader ;
34+ import org .apache .velocity .runtime .resource .loader .FileResourceLoader ;
3335import org .apache .velocity .tools .generic .*;
3436import org .eclipse .rdf4j .common .exception .ValidationException ;
3537import org .eclipse .rdf4j .model .Model ;
38+ import org .eclipse .rdf4j .model .base .CoreDatatype ;
3639import org .eclipse .rdf4j .model .vocabulary .RDF4J ;
3740import org .eclipse .rdf4j .model .vocabulary .SHACL ;
3841import org .eclipse .rdf4j .repository .RepositoryConnection ;
4548import org .slf4j .Logger ;
4649import org .slf4j .LoggerFactory ;
4750
51+ import java .io .ByteArrayInputStream ;
4852import java .io .IOException ;
4953import java .io .InputStream ;
5054import java .nio .charset .StandardCharsets ;
@@ -195,11 +199,16 @@ public static VelocityEngine createVelocityEngine(boolean templateInResources, b
195199 velocityEngine .setProperty ("resource.loaders" , "class" );
196200 velocityEngine .setProperty ("resource.loader.class.class" ,
197201 ClasspathResourceLoader .class .getName ());
202+ } else {
203+ velocityEngine .setProperty ("resource.loaders" , "file" );
204+ velocityEngine .setProperty ("resource.loader.file.class" , FileResourceLoader .class .getName ());
205+ velocityEngine .setProperty ("resource.loader.file.path" , "" );
198206 }
199207 velocityEngine .init ();
200208 return velocityEngine ;
201209 }
202- public static void validateRML (Path templatePath , boolean verbose ) {
210+
211+ public static void validateRML (InputStream rmlMapping , boolean verbose ) {
203212
204213 ShaclSail shaclSail = new ShaclSail (new MemoryStore ());
205214 SailRepository repository = new SailRepository (shaclSail );
@@ -208,33 +217,25 @@ public static void validateRML(Path templatePath, boolean verbose) {
208217 try (RepositoryConnection connection = repository .getConnection ()) {
209218 try (InputStream shapesStream = Util .class .getResourceAsStream ("/rml/core.ttl" )) {
210219 Model rules = Rio .parse (shapesStream , RDFFormat .TURTLE );
211- // cf. https://github.com/eclipse-rdf4j/rdf4j/discussions/4287
212220 rules .remove (null , SHACL .NAME , null );
213221 rules .remove (null , SHACL .DESCRIPTION , null );
214-
215222 connection .begin ();
216223 connection .add (rules , RDF4J .SHACL_SHAPE_GRAPH );
217224 connection .commit ();
218225 }
219-
220- // Load RML
221- try (InputStream dataStream = Files .newInputStream (templatePath )) {
222- connection .begin ();
223- connection .add (dataStream , "" , org .eclipse .rdf4j .rio .RDFFormat .TURTLE );
224-
225- try {
226- connection .commit ();
227- log .info ("RML validated correctly" );
228- } catch (RepositoryException exception ) {
229- Throwable cause = exception .getCause ();
230- log .error ("RML not valid" );
231- if (verbose )
232- if (cause instanceof ValidationException ) {
233- Model validationReportModel = ((ValidationException ) cause ).validationReportAsModel ();
234- Rio .write (validationReportModel , System .out , RDFFormat .TURTLE );
235- }
236- throw exception ;
226+ connection .begin ();
227+ connection .add (rmlMapping , "" , RDFFormat .TURTLE );
228+ try {
229+ connection .commit ();
230+ log .info ("RML validated correctly" );
231+ } catch (RepositoryException exception ) {
232+ Throwable cause = exception .getCause ();
233+ log .error ("RML not valid" );
234+ if (verbose && cause instanceof ValidationException ) {
235+ Model validationReportModel = ((ValidationException ) cause ).validationReportAsModel ();
236+ Rio .write (validationReportModel , System .out , RDFFormat .TURTLE );
237237 }
238+ throw exception ;
238239 }
239240 } catch (Exception e ) {
240241 throw new RuntimeException (e );
@@ -243,6 +244,7 @@ public static void validateRML(Path templatePath, boolean verbose) {
243244 }
244245 }
245246
247+
246248 /**
247249 * Creates a new {@link VelocityContext} and populates it with the provided readers, template map, and template functions.
248250 * 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
331333 public static VelocityContext createVelocityContext (Map <String , Reader > readers , TemplateMap templateMap ) {
332334 return createVelocityContext (readers , templateMap , new TemplateFunctions ());
333335 }
336+
337+ /**
338+ * Compiles an MTL mapping from the given RML file.
339+ *
340+ * @param mappingRML Path to the RML mapping file.
341+ * @param baseIri Base IRI to use if not found in the mapping.
342+ * @param basePath Base path for output files.
343+ * @param trimTemplate Whether to use the trimmed template.
344+ * @param verbose Enable verbose validation output.
345+ * @return Path to the compiled template.
346+ * @throws Exception if validation or compilation fails.
347+ */
348+ public static Path compiledMTLMapping (InputStream mappingRML , String baseIri , Path basePath , boolean trimTemplate , boolean verbose ) throws Exception {
349+ String mappingRMLString = inputStreamToString (mappingRML );
350+ Util .validateRML (new ByteArrayInputStream (mappingRMLString .getBytes (StandardCharsets .UTF_8 )), verbose );
351+ Reader compilerReader = TemplateFunctions .getRDFReaderFromString (mappingRMLString , RDFFormat .TURTLE .toString ());
352+ Map <String , Reader > compilerReaderMap = new HashMap <>();
353+ compilerReaderMap .put ("reader" , compilerReader );
354+
355+ try (InputStream rmlCompiler = trimTemplate
356+ ? Util .class .getResourceAsStream ("/rml/rml-compiler.vm.tmp.vm" )
357+ : Util .class .getResourceAsStream ("/rml/rml-compiler.vm" )) {
358+
359+ RMLCompilerUtils rmlCompilerUtils = new RMLCompilerUtils ();
360+
361+ Map <String , String > rmlMap = new HashMap <>();
362+ String baseIriRML = rmlCompilerUtils .getBaseIRI (mappingRMLString );
363+ baseIriRML = baseIriRML != null ? baseIriRML : baseIri ;
364+ rmlMap .put ("baseIRI" , baseIriRML );
365+ rmlMap .put ("basePath" , basePath .toString () + "/" );
366+
367+ Path compiledTemplatePath = Paths .get (basePath .toString (), "template.rml.vm" );
368+ TemplateExecutor templateExecutor = new TemplateExecutor (false , false , true , null );
369+ return templateExecutor .executeMapping (
370+ compilerReaderMap ,
371+ rmlCompiler ,
372+ compiledTemplatePath ,
373+ rmlCompilerUtils ,
374+ new TemplateMap (rmlMap )
375+ );
376+ }
377+ }
334378}
0 commit comments