diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..51f4592 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,19 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +### Issue type: :bug: Bug + +### Description +_A clear and concise description of what the bug is._ + +### Steps +_Add the necessary steps to replicate the bug._ + +### Environment +_Add the version of Java and OS that is used._ diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..2c54c43 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +### Issue type: :unicorn: Feature + +### Description +_Add a clear and concise description of what the feature is_ + +### Why it is useful +_Add why the feature is useful._ + +### Existing features it breaks +_List all existing features that this new feature will break._ diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3ce47..42c2a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +## [1.0.2] - 2020-01-17 + +### Added +- Test for subject with two references in template +- Issue templates (see [issue 43](https://github.com/RMLio/yarrrml-parser/issues/43)) + +### Fixed +- Join condition with two references in child/parent is incorrectly parsed (see [issue 44](https://github.com/RMLio/yarrrml-parser/issues/44)) + ## [1.0.1] - 2020-01-10 ### Fixed @@ -134,6 +143,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - fix failing test - support for recursive functions +[1.0.2]: https://github.com/RMLio/yarrrml-parser/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/RMLio/yarrrml-parser/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/RMLio/yarrrml-parser/compare/v0.3.11...v1.0.0 [0.3.11]: https://github.com/RMLio/yarrrml-parser/compare/v0.3.10...v0.3.11 diff --git a/lib/rml-generator.js b/lib/rml-generator.js index a0778bb..6a2c1c4 100644 --- a/lib/rml-generator.js +++ b/lib/rml-generator.js @@ -4,7 +4,7 @@ */ const namespaces = require('prefix-ns').asMap(); -const YARRRML2Anything = require('./abstract-generator.js'); +const AbstractGenerator = require('./abstract-generator.js'); const formulations = require('./formulations.json'); const { DataFactory } = require('n3'); const {namedNode, literal, quad} = DataFactory; @@ -13,7 +13,7 @@ const jdbcDrivers = require('./jdbc-drivers'); namespaces.ql = 'http://semweb.mmlab.be/ns/ql#'; namespaces['idlab-fn'] = 'http://example.com/idlab/function/'; -class RMLGenerator extends YARRRML2Anything { +class RMLGenerator extends AbstractGenerator { constructor() { super(); @@ -200,7 +200,9 @@ class RMLGenerator extends YARRRML2Anything { generateCondition(condition, omSubject) { if (condition.function === 'equal' && !this._parametersContainsFunction(condition.parameters) - && !this._parametersContainsConstantValues(condition.parameters)) { + && !this._parametersContainsConstantValues(condition.parameters) + && !this._parametersContainsTemplates(condition.parameters) + ) { super.generateCondition(condition, omSubject); } else { if (condition.function === 'equal') { @@ -249,7 +251,28 @@ class RMLGenerator extends YARRRML2Anything { let i = 0; while (i < parameters.length && - (typeof parameters[i].value !== 'string' || (typeof parameters[i].value === 'string' && this.getAppropriatePredicateAndObjectForValue(parameters[i].value).predicate.value !== namespaces.rr + 'constant'))) { + (typeof parameters[i].value !== 'string' || + (typeof parameters[i].value === 'string' + && this.getAppropriatePredicateAndObjectForValue(parameters[i].value).predicate.value !== namespaces.rr + 'constant'))) { + i ++ + } + + return i < parameters.length; + } + + /** + * This method returns true if there is at least one parameter that is a template. + * @param parameters The list of parameters to check. + * @returns {boolean} True if at least one parameter is found that is a template, else false. + * @private + */ + _parametersContainsTemplates(parameters) { + let i = 0; + + while (i < parameters.length && + (typeof parameters[i].value !== 'string' || + (typeof parameters[i].value === 'string' + && this.getAppropriatePredicateAndObjectForValue(parameters[i].value).predicate.value !== namespaces.rr + 'template'))) { i ++ } diff --git a/lib/rml-generator.test.js b/lib/rml-generator.test.js index 72c1cdc..dc66290 100644 --- a/lib/rml-generator.test.js +++ b/lib/rml-generator.test.js @@ -144,6 +144,18 @@ describe('YARRRML to RML', function () { it('condition on mapping with constant', function (done) { work('condition-on-mapping-constant/mapping.yarrrml', 'condition-on-mapping-constant/mapping.rml.ttl', done); }); + + it('template with two references', function (done) { + work('template-2-references/mapping.yarrrml', 'template-2-references/mapping.rml.ttl', done); + }); + + it('join condition with one reference and text', function (done) { + work('joincondition-template-1-reference-text/mapping.yarrrml', 'joincondition-template-1-reference-text/mapping.rml.ttl', done); + }); + + it('join condition with two references', function (done) { + work('joincondition-template-2-references/mapping.yarrrml', 'joincondition-template-2-references/mapping.rml.ttl', done); + }); }); function work(path1, path2, cb) { diff --git a/package.json b/package.json index e381a21..6e7920e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rmlio/yarrrml-parser", - "version": "1.0.1", + "version": "1.0.2", "description": "Parse YARRRML descriptions into RML RDF statements", "main": "lib/yarrrml2rml.js", "scripts": { diff --git a/test/joincondition-template-1-reference-text/mapping.rml.ttl b/test/joincondition-template-1-reference-text/mapping.rml.ttl new file mode 100644 index 0000000..367407e --- /dev/null +++ b/test/joincondition-template-1-reference-text/mapping.rml.ttl @@ -0,0 +1,72 @@ +@prefix rr: . +@prefix rdf: . +@prefix rdfs: . +@prefix fnml: . +@prefix fno: . +@prefix d2rq: . +@prefix rml: . +@prefix ql: . +@prefix : . + +:map_person_0 rml:logicalSource :source_0. +:source_0 a rml:LogicalSource; + rml:source "test.csv"; + rml:referenceFormulation ql:CSV. +:map_person_0 a rr:TriplesMap; + rdfs:label "person". +:s_0 a rr:SubjectMap. +:map_person_0 rr:subjectMap :s_0. +:s_0 rr:template "http://example.com/person/{id}". +:pom_0 a rr:PredicateObjectMap. +:map_person_0 rr:predicateObjectMap :pom_0. +:pm_0 a rr:PredicateMap. +:pom_0 rr:predicateMap :pm_0. +:pm_0 rr:constant . +:pom_0 rr:objectMap :om_0. +:map_project_0 rml:logicalSource :source_1. +:source_1 a rml:LogicalSource; + rml:source "test.csv"; + rml:referenceFormulation ql:CSV. +:map_project_0 a rr:TriplesMap; + rdfs:label "project". +:s_1 a rr:SubjectMap. +:map_project_0 rr:subjectMap :s_1. +:s_1 rr:template "http://example.com/project/{id}". +:pom_1 a rr:PredicateObjectMap. +:map_project_0 rr:predicateObjectMap :pom_1. +:pm_1 a rr:PredicateMap. +:pom_1 rr:predicateMap :pm_1. +:pm_1 rr:constant rdf:type. +:pom_1 rr:objectMap :om_1. +:om_1 a rr:ObjectMap; + rr:constant "http://schema.org/Project"; + rr:termType rr:IRI. +:om_0 a rr:ObjectMap; + rr:parentTriplesMap :map_project_0; + rml:joinCondition :jc_0. +:jc_0 a fnml:FunctionTermMap; + fnml:functionValue :fn_0. +:fn_0 rr:predicateObjectMap :pomexec_0. +:pomexec_0 rr:predicateMap :pmexec_0. +:pmexec_0 rr:constant fno:executes. +:pomexec_0 rr:objectMap :omexec_0. +:omexec_0 rr:constant "http://example.com/idlab/function/equal"; + rr:termType rr:IRI. +:fn_0 rr:predicateObjectMap :pom_2. +:pom_2 a rr:PredicateObjectMap; + rr:predicateMap :pm_2. +:pm_2 a rr:PredicateMap; + rr:constant . +:pom_2 rr:objectMap :om_2. +:om_2 a rr:ObjectMap; + rr:template "{id}_"; + rr:termType rr:Literal. +:fn_0 rr:predicateObjectMap :pom_3. +:pom_3 a rr:PredicateObjectMap; + rr:predicateMap :pm_3. +:pm_3 a rr:PredicateMap; + rr:constant . +:pom_3 rr:objectMap :om_3. +:om_3 a rr:ObjectMap; + rml:parentTermMap :ptm_0. +:ptm_0 rml:reference "id". diff --git a/test/joincondition-template-1-reference-text/mapping.yarrrml b/test/joincondition-template-1-reference-text/mapping.yarrrml new file mode 100644 index 0000000..c503785 --- /dev/null +++ b/test/joincondition-template-1-reference-text/mapping.yarrrml @@ -0,0 +1,20 @@ +mappings: + person: + sources: + - [test.csv~csv] + s: http://example.com/person/$(id) + po: + - p: schema:creator + o: + mapping: project + condition: + function: equal + parameters: + - [str1, $(id)_, s] + - [str2, $(id), o] + project: + sources: + - [test.csv~csv] + s: http://example.com/project/$(id) + po: + - [a, schema:Project] diff --git a/test/joincondition-template-2-references/mapping.rml.ttl b/test/joincondition-template-2-references/mapping.rml.ttl new file mode 100644 index 0000000..ff3373f --- /dev/null +++ b/test/joincondition-template-2-references/mapping.rml.ttl @@ -0,0 +1,72 @@ +@prefix rr: . +@prefix rdf: . +@prefix rdfs: . +@prefix fnml: . +@prefix fno: . +@prefix d2rq: . +@prefix rml: . +@prefix ql: . +@prefix : . + +:map_person_0 rml:logicalSource :source_0. +:source_0 a rml:LogicalSource; + rml:source "test.csv"; + rml:referenceFormulation ql:CSV. +:map_person_0 a rr:TriplesMap; + rdfs:label "person". +:s_0 a rr:SubjectMap. +:map_person_0 rr:subjectMap :s_0. +:s_0 rr:template "http://example.com/person/{id}". +:pom_0 a rr:PredicateObjectMap. +:map_person_0 rr:predicateObjectMap :pom_0. +:pm_0 a rr:PredicateMap. +:pom_0 rr:predicateMap :pm_0. +:pm_0 rr:constant . +:pom_0 rr:objectMap :om_0. +:map_project_0 rml:logicalSource :source_1. +:source_1 a rml:LogicalSource; + rml:source "test.csv"; + rml:referenceFormulation ql:CSV. +:map_project_0 a rr:TriplesMap; + rdfs:label "project". +:s_1 a rr:SubjectMap. +:map_project_0 rr:subjectMap :s_1. +:s_1 rr:template "http://example.com/project/{id}". +:pom_1 a rr:PredicateObjectMap. +:map_project_0 rr:predicateObjectMap :pom_1. +:pm_1 a rr:PredicateMap. +:pom_1 rr:predicateMap :pm_1. +:pm_1 rr:constant rdf:type. +:pom_1 rr:objectMap :om_1. +:om_1 a rr:ObjectMap; + rr:constant "http://schema.org/Project"; + rr:termType rr:IRI. +:om_0 a rr:ObjectMap; + rr:parentTriplesMap :map_project_0; + rml:joinCondition :jc_0. +:jc_0 a fnml:FunctionTermMap; + fnml:functionValue :fn_0. +:fn_0 rr:predicateObjectMap :pomexec_0. +:pomexec_0 rr:predicateMap :pmexec_0. +:pmexec_0 rr:constant fno:executes. +:pomexec_0 rr:objectMap :omexec_0. +:omexec_0 rr:constant "http://example.com/idlab/function/equal"; + rr:termType rr:IRI. +:fn_0 rr:predicateObjectMap :pom_2. +:pom_2 a rr:PredicateObjectMap; + rr:predicateMap :pm_2. +:pm_2 a rr:PredicateMap; + rr:constant . +:pom_2 rr:objectMap :om_2. +:om_2 a rr:ObjectMap; + rr:template "{id}_{name}"; + rr:termType rr:Literal. +:fn_0 rr:predicateObjectMap :pom_3. +:pom_3 a rr:PredicateObjectMap; + rr:predicateMap :pm_3. +:pm_3 a rr:PredicateMap; + rr:constant . +:pom_3 rr:objectMap :om_3. +:om_3 a rr:ObjectMap; + rml:parentTermMap :ptm_0. +:ptm_0 rr:template "{id}_{name}". diff --git a/test/joincondition-template-2-references/mapping.yarrrml b/test/joincondition-template-2-references/mapping.yarrrml new file mode 100644 index 0000000..edf3fc3 --- /dev/null +++ b/test/joincondition-template-2-references/mapping.yarrrml @@ -0,0 +1,20 @@ +mappings: + person: + sources: + - [test.csv~csv] + s: http://example.com/person/$(id) + po: + - p: schema:creator + o: + mapping: project + condition: + function: equal + parameters: + - [str1, $(id)_$(name), s] + - [str2, $(id)_$(name), o] + project: + sources: + - [test.csv~csv] + s: http://example.com/project/$(id) + po: + - [a, schema:Project] diff --git a/test/template-2-references/mapping.rml.ttl b/test/template-2-references/mapping.rml.ttl new file mode 100644 index 0000000..d301e15 --- /dev/null +++ b/test/template-2-references/mapping.rml.ttl @@ -0,0 +1,28 @@ +@prefix rr: . +@prefix rdf: . +@prefix rdfs: . +@prefix fnml: . +@prefix fno: . +@prefix d2rq: . +@prefix rml: . +@prefix ql: . +@prefix : . + +:map_person_0 rml:logicalSource :source_0. +:source_0 a rml:LogicalSource; + rml:source "test.csv"; + rml:referenceFormulation ql:CSV. +:map_person_0 a rr:TriplesMap; + rdfs:label "person". +:s_0 a rr:SubjectMap. +:map_person_0 rr:subjectMap :s_0. +:s_0 rr:template "http://example.com/{id}_{name}". +:pom_0 a rr:PredicateObjectMap. +:map_person_0 rr:predicateObjectMap :pom_0. +:pm_0 a rr:PredicateMap. +:pom_0 rr:predicateMap :pm_0. +:pm_0 rr:constant rdf:type. +:pom_0 rr:objectMap :om_0. +:om_0 a rr:ObjectMap; + rr:constant "http://schema.org/Person"; + rr:termType rr:IRI. diff --git a/test/template-2-references/mapping.yarrrml b/test/template-2-references/mapping.yarrrml new file mode 100644 index 0000000..8e2d6aa --- /dev/null +++ b/test/template-2-references/mapping.yarrrml @@ -0,0 +1,7 @@ +mappings: + person: + sources: + - [test.csv~csv] + s: http://example.com/$(id)_$(name) + po: + - [a, schema:Person]