diff --git a/README.md b/README.md index 6f1bde4..b418c9f 100644 --- a/README.md +++ b/README.md @@ -1126,6 +1126,8 @@ Inferred mappings don't have fields such as `uri`, `identifier`, `creator`, `cre `strict=[boolean]` values `1` or `true` disallow mapping type "closeMatch" for inferred mappings (default `false`) + `depth=[number]` a non-negative number of the depth used to infer mappings (not set by default); `0` means no inference, `1` means only the next ancestor concept (= broader) is used for inference, etc. + * **Success Response** JSON array of [JSKOS Concept Mappings] diff --git a/services/mappings.js b/services/mappings.js index 2a68e29..5c7ac56 100644 --- a/services/mappings.js +++ b/services/mappings.js @@ -374,7 +374,7 @@ class MappingService { /** * Infer mappings based on the source concept's ancestors. (see https://github.com/gbv/jskos-server/issues/177) */ - async inferMappings({ strict, ...query }) { + async inferMappings({ strict, depth, ...query }) { if (query.to) { // `to` parameter not supported throw new MalformedRequestError("Query parameter \"to\" is not supported in /mappings/infer.") @@ -402,6 +402,12 @@ class MappingService { } strict = ["true", "1"].includes(strict) ? true : false + depth = parseInt(depth) + depth = (isNaN(depth) || depth < 0) ? null : depth + + if (depth === 0) { + return [] + } fromScheme = await this.schemeService.getScheme(fromScheme) try { @@ -436,7 +442,10 @@ class MappingService { } // Retrieve ancestors from API - const ancestors = await registry.getAncestors({ concept: { uri: from } }) + let ancestors = await registry.getAncestors({ concept: { uri: from } }) + if (depth !== null) { + ancestors = ancestors.slice(0, depth) + } for (const uri of ancestors.map(a => a && a.uri).filter(Boolean)) { mappings = await this.getMappings(Object.assign({}, query, { from: uri, type: types.join("|") })) if (mappings.length) { diff --git a/test/infer-mappings.js b/test/infer-mappings.js index 5efe880..5ccaaa3 100644 --- a/test/infer-mappings.js +++ b/test/infer-mappings.js @@ -147,6 +147,23 @@ describe("/mappings/infer", () => { }) }) + it("should return nothing for previous request if depth is set to 1", done => { + chai.request(server.app) + .get("/mappings/infer") + .query({ + from: _.last(concepts).uri, + fromScheme: scheme.uri, + toScheme: targetScheme.uri, + depth: 1, + }) + .end((error, res) => { + res.should.have.status(200) + res.body.should.be.an("array") + assert.equal(res.body.length, 0) + done() + }) + }) + it("should add a mapping for a deeper ancestor concept and return it instead as inferred mapping; also adjust mapping type", done => { const mapping = { from: { memberSet: [concepts[1]] }, @@ -182,6 +199,23 @@ describe("/mappings/infer", () => { }) }) + it("should return nothing for previous request if depth is set to 0", done => { + chai.request(server.app) + .get("/mappings/infer") + .query({ + from: _.last(concepts).uri, + fromScheme: scheme.uri, + toScheme: targetScheme.uri, + depth: 0, + }) + .end((error, res) => { + res.should.have.status(200) + res.body.should.be.an("array") + assert.equal(res.body.length, 0) + done() + }) + }) + it("should not use mapping of type `closeMatch` for inference if parameter `strict` is set", done => { chai.request(server.app) .get("/mappings/infer") @@ -222,6 +256,7 @@ describe("/mappings/infer", () => { from: _.last(concepts).uri, fromScheme: scheme.uri, toScheme: targetScheme.uri, + depth: 0, }) .end((error, res) => { res.should.have.status(200)