diff --git a/bin/jskos-convert b/bin/jskos-convert index a803d86..aa1cf0e 100755 --- a/bin/jskos-convert +++ b/bin/jskos-convert @@ -18,6 +18,7 @@ program .option("-m, --marktop", "explicitly mark concepts without broader as top concepts") .option("--creator ", "add creator to mappings") .option("--created ", "add creation timestamp to mappings") + .option("-i, --identifier", "add mapping sameness identifier") .option("--delimiter ", "CSV delimiter (default: ,)") .example("mappings -t csv mappings.ndjson") .example("concepts -r registry.json -s example http://example.org/jskos.csv") diff --git a/lib/jskos-convert.js b/lib/jskos-convert.js index 9cee87d..897464e 100644 --- a/lib/jskos-convert.js +++ b/lib/jskos-convert.js @@ -11,7 +11,7 @@ import mappingsFromRows from "./csv-to-mapping.js" import conceptsFromRows from "./csv-to-concept.js" import rowsFromConcepts from "./concept-to-csv.js" -import { ConceptScheme } from "jskos-tools" +import { ConceptScheme, addMappingIdentifiers } from "jskos-tools" import rdfSerializer from "./rdf-serializer.js" import { formats } from "./rdf-serializer.js" @@ -86,6 +86,18 @@ function convert (opts) { } else if (from === "csv" && to === "ndjson") { steps.push(mappingsFromRows({ language, fromScheme: scheme, toScheme: destination, partOf: partof, creator, created })) } + if (opts.identifier) { + steps.push(new stream.Transform({ + objectMode: true, + async transform(mapping, encoding, callback) { + try { + callback(null, await addMappingIdentifiers(mapping)) + } catch(e) { + callback(e) + } + }, + })) + } if (opts.validate) { steps.push(validator(opts)) } diff --git a/package-lock.json b/package-lock.json index 24c8a51..01ba817 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "cocoda-sdk": "^3.4.13", "commander": "^12.1.0", "csv": "^6.4.1", - "jskos-tools": "^1.0.43", + "jskos-tools": "^1.2.0", "jskos-validate": "^1.2.0", "json-anystream": "^2.0.1", "jsonld": "^9.0.0", @@ -2024,9 +2024,9 @@ } }, "node_modules/jskos-tools": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jskos-tools/-/jskos-tools-1.1.0.tgz", - "integrity": "sha512-Cg5Qd8cgb/s1voSEwbOzpcsXuq5ioy0FnM/00Hqngj6hV3Uq6oiwrwPBWHMU7x8kzlUpNnsS4LHoarO0TGRNoQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jskos-tools/-/jskos-tools-1.2.0.tgz", + "integrity": "sha512-udxIM1287F9ICdYR8V0WZYwRgekBPrsUPsPJGfLBtTagE880ECTc6OcYVZ7l3cxjhzyzJKE1EfF5daNX0JePqQ==", "hasInstallScript": true, "license": "MIT" }, diff --git a/package.json b/package.json index 9aa3726..6c6b0ae 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "cocoda-sdk": "^3.4.13", "commander": "^12.1.0", "csv": "^6.4.1", - "jskos-tools": "^1.0.43", + "jskos-tools": "^1.2.0", "jskos-validate": "^1.2.0", "json-anystream": "^2.0.1", "jsonld": "^9.0.0", diff --git a/test/convert-mappings.js b/test/convert-mappings.js index 38d9d2d..a0f415a 100644 --- a/test/convert-mappings.js +++ b/test/convert-mappings.js @@ -1,5 +1,5 @@ import assert from "assert" -import { ConceptScheme } from "jskos-tools" +import { ConceptScheme, addMappingIdentifiers } from "jskos-tools" import mappingsFromRows from "../lib/csv-to-mapping.js" // { fromNotation: "612.111", toNotation: "4070945-0", type: "exact" } @@ -81,4 +81,34 @@ describe("convert-mappings", () => { done() }) + + it("adds mapping sameness identifier", async () => { + const mapping = { + from: { memberSet: [{ uri: "http://example.org/voc/A1", notation: ["A1"] }] }, + fromScheme: { uri: "http://example.org/voc" }, + to: { memberSet: [{ uri: "http://example.com/voc/x", notation: ["x"] }] }, + toScheme: { uri: "http://example.com/voc" }, + type: ["http://www.w3.org/2004/02/skos/core#exactMatch"], + } + const result = await addMappingIdentifiers(mapping) + assert.ok(Array.isArray(result.identifier)) + assert.ok(result.identifier.some(id => id.startsWith("mapping:"))) + assert.ok(result.identifier.some(id => id.startsWith("urn:jskos:mapping:members:"))) + assert.ok(result.identifier.some(id => id.startsWith("urn:jskos:mapping:content:"))) + }) + + it("replaces existing mapping sameness identifier", async () => { + const mapping = { + from: { memberSet: [{ uri: "http://example.org/voc/A1", notation: ["A1"] }] }, + fromScheme: { uri: "http://example.org/voc" }, + to: { memberSet: [{ uri: "http://example.com/voc/x", notation: ["x"] }] }, + toScheme: { uri: "http://example.com/voc" }, + type: ["http://www.w3.org/2004/02/skos/core#exactMatch"], + identifier: ["mapping:oldid"], + } + const result = await addMappingIdentifiers(mapping) + const samenessIds = result.identifier.filter(id => id.startsWith("mapping:")) + assert.strictEqual(samenessIds.length, 1) + assert.ok(!samenessIds[0].includes("oldid")) + }) })