cocoda-sdk 1.0.13 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +74 -28
- package/dist/cjs/index.cjs +2673 -0
- package/dist/cocoda-sdk.js +33 -17423
- package/dist/cocoda-sdk.js.LICENSES.txt +105 -86
- package/dist/cocoda-sdk.js.map +7 -0
- package/dist/esm/errors/index.js +46 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/lib/CocodaSDK.js +269 -0
- package/dist/esm/providers/base-provider.js +368 -0
- package/dist/esm/providers/concept-api-provider.js +278 -0
- package/dist/esm/providers/index.js +20 -0
- package/dist/esm/providers/label-search-suggestion-provider.js +101 -0
- package/dist/esm/providers/loc-api-provider.js +185 -0
- package/dist/esm/providers/local-mappings-provider.js +337 -0
- package/dist/esm/providers/mappings-api-provider.js +264 -0
- package/dist/esm/providers/occurrences-api-provider.js +163 -0
- package/dist/esm/providers/reconciliation-api-provider.js +140 -0
- package/dist/esm/providers/skosmos-api-provider.js +345 -0
- package/{utils → dist/esm/utils}/index.js +40 -53
- package/dist/esm/utils/lodash.js +34 -0
- package/package.json +16 -17
- package/errors/index.js +0 -119
- package/index.js +0 -5
- package/lib/CocodaSDK.js +0 -360
- package/providers/base-provider.js +0 -581
- package/providers/concept-api-provider.js +0 -377
- package/providers/index.js +0 -34
- package/providers/label-search-suggestion-provider.js +0 -219
- package/providers/loc-api-provider.js +0 -275
- package/providers/local-mappings-provider.js +0 -459
- package/providers/mappings-api-provider.js +0 -396
- package/providers/occurrences-api-provider.js +0 -234
- package/providers/reconciliation-api-provider.js +0 -211
- package/providers/skosmos-api-provider.js +0 -441
- package/utils/lodash.js +0 -21
|
@@ -1,377 +0,0 @@
|
|
|
1
|
-
const BaseProvider = require("./base-provider")
|
|
2
|
-
const _ = require("../utils/lodash")
|
|
3
|
-
const errors = require("../errors")
|
|
4
|
-
const utils = require("../utils")
|
|
5
|
-
const jskos = require("jskos-tools")
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* JSKOS Concept API.
|
|
9
|
-
*
|
|
10
|
-
* This class provides access to concept schemes and their concepts via JSKOS API in [JSKOS format](https://gbv.github.io/jskos/).
|
|
11
|
-
* See [jskos-server](https://github.com/gbv/jskos-server) for a JSKOS API reference implementation and [DANTE](https://api.dante.gbv.de/) for another API endpoint.
|
|
12
|
-
*
|
|
13
|
-
* To use it in a registry, specify `provider` as "ConceptApi" and provide the API base URL as `api`:
|
|
14
|
-
* ```json
|
|
15
|
-
* {
|
|
16
|
-
* "uri": "http://coli-conc.gbv.de/registry/coli-conc-concepts",
|
|
17
|
-
* "provider": "ConceptApi",
|
|
18
|
-
* "api": "https://coli-conc.gbv.de/api/"
|
|
19
|
-
* }
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* If the `/status` endpoint can be queried, the remaining API methods will be taken from that. As a fallback, the default endpoints will be appended to `api`.
|
|
23
|
-
*
|
|
24
|
-
* Alternatively, you can provide the endpoints separately: `status`, `schemes`, `top`, `concepts`, `data`, `narrower`, `ancestors`, `types`, `suggest`, `search`
|
|
25
|
-
* Note that `schemes`, `top`, and `types` can also be provided as arrays.
|
|
26
|
-
*
|
|
27
|
-
* Additionally, the following JSKOS properties can be provided: `prefLabel`, `notation`, `definition`
|
|
28
|
-
*
|
|
29
|
-
* @extends BaseProvider
|
|
30
|
-
* @category Providers
|
|
31
|
-
*/
|
|
32
|
-
class ConceptApiProvider extends BaseProvider {
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @private
|
|
36
|
-
*/
|
|
37
|
-
_prepare() {
|
|
38
|
-
// Set status endpoint only
|
|
39
|
-
if (this._api.api && this._api.status === undefined) {
|
|
40
|
-
this._api.status = utils.concatUrl(this._api.api, "/status")
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* @private
|
|
46
|
-
*/
|
|
47
|
-
_setup() {
|
|
48
|
-
// Implicitly fill `this._api` if necessary
|
|
49
|
-
if (this._api.api) {
|
|
50
|
-
const endpoints = {
|
|
51
|
-
schemes: "/voc",
|
|
52
|
-
top: "/voc/top",
|
|
53
|
-
concepts: "/voc/concepts",
|
|
54
|
-
data: "/data",
|
|
55
|
-
narrower: "/narrower",
|
|
56
|
-
ancestors: "/ancestors",
|
|
57
|
-
types: "/types",
|
|
58
|
-
suggest: "/suggest",
|
|
59
|
-
search: "/search",
|
|
60
|
-
}
|
|
61
|
-
for (let key of Object.keys(endpoints)) {
|
|
62
|
-
// Only override if undefined
|
|
63
|
-
if (this._api[key] === undefined) {
|
|
64
|
-
this._api[key] = utils.concatUrl(this._api.api, endpoints[key])
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
this.has.schemes = !!this._api.schemes
|
|
69
|
-
this.has.top = !!this._api.top
|
|
70
|
-
this.has.data = !!this._api.data
|
|
71
|
-
this.has.concepts = !!this._api.concepts || this.has.data
|
|
72
|
-
this.has.narrower = !!this._api.narrower
|
|
73
|
-
this.has.ancestors = !!this._api.ancestors
|
|
74
|
-
this.has.types = !!this._api.types
|
|
75
|
-
this.has.suggest = !!this._api.suggest
|
|
76
|
-
this.has.search = !!this._api.search
|
|
77
|
-
this.has.auth = _.get(this._config, "auth.key") != null
|
|
78
|
-
this._defaultParams = {
|
|
79
|
-
properties: "uri,prefLabel,notation,inScheme",
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Returns all concept schemes.
|
|
85
|
-
*
|
|
86
|
-
* @param {Object} config
|
|
87
|
-
* @returns {Object[]} array of JSKOS concept scheme objects
|
|
88
|
-
*/
|
|
89
|
-
async getSchemes(config) {
|
|
90
|
-
if (!this._api.schemes) {
|
|
91
|
-
throw new errors.MissingApiUrlError()
|
|
92
|
-
}
|
|
93
|
-
if (Array.isArray(this._api.schemes)) {
|
|
94
|
-
return this._api.schemes
|
|
95
|
-
}
|
|
96
|
-
const schemes = await this.axios({
|
|
97
|
-
...config,
|
|
98
|
-
method: "get",
|
|
99
|
-
url: this._api.schemes,
|
|
100
|
-
params: {
|
|
101
|
-
...this._defaultParams,
|
|
102
|
-
// ? What should the default limit be?
|
|
103
|
-
limit: 500,
|
|
104
|
-
...(config.params || {}),
|
|
105
|
-
},
|
|
106
|
-
})
|
|
107
|
-
// If schemes were given in registry object, only request those schemes from API
|
|
108
|
-
if (Array.isArray(this._jskos.schemes)) {
|
|
109
|
-
return utils.withCustomProps(schemes.filter(s => jskos.isContainedIn(s, this._jskos.schemes)), schemes)
|
|
110
|
-
} else {
|
|
111
|
-
return schemes
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Returns top concepts for a concept scheme.
|
|
117
|
-
*
|
|
118
|
-
* @param {Object} config
|
|
119
|
-
* @param {Object} config.scheme concept scheme object
|
|
120
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
121
|
-
*/
|
|
122
|
-
async getTop({ scheme, ...config }) {
|
|
123
|
-
if (!this._api.top) {
|
|
124
|
-
throw new errors.MissingApiUrlError()
|
|
125
|
-
}
|
|
126
|
-
if (!scheme) {
|
|
127
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "scheme" })
|
|
128
|
-
}
|
|
129
|
-
if (Array.isArray(this._api.top)) {
|
|
130
|
-
return this._api.top
|
|
131
|
-
}
|
|
132
|
-
return this.axios({
|
|
133
|
-
...config,
|
|
134
|
-
method: "get",
|
|
135
|
-
url: this._api.top,
|
|
136
|
-
params: {
|
|
137
|
-
...this._defaultParams,
|
|
138
|
-
// ? What should the default limit be?
|
|
139
|
-
limit: 10000,
|
|
140
|
-
...(config.params || {}),
|
|
141
|
-
uri: scheme.uri,
|
|
142
|
-
},
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Returns details for a list of concepts.
|
|
148
|
-
*
|
|
149
|
-
* @param {Object} config
|
|
150
|
-
* @param {Object[]} config.concepts list of concept objects to load
|
|
151
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
152
|
-
*/
|
|
153
|
-
async getConcepts({ concepts, ...config }) {
|
|
154
|
-
if (!this.has.data) {
|
|
155
|
-
throw new errors.MissingApiUrlError()
|
|
156
|
-
}
|
|
157
|
-
if (!concepts) {
|
|
158
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concepts" })
|
|
159
|
-
}
|
|
160
|
-
if (!Array.isArray(concepts)) {
|
|
161
|
-
concepts = [concepts]
|
|
162
|
-
}
|
|
163
|
-
let uris = concepts.map(concept => concept.uri).filter(uri => uri != null)
|
|
164
|
-
return this.axios({
|
|
165
|
-
...config,
|
|
166
|
-
method: "get",
|
|
167
|
-
url: this._api.data,
|
|
168
|
-
params: {
|
|
169
|
-
...this._defaultParams,
|
|
170
|
-
// ? What should the default limit be?
|
|
171
|
-
limit: 500,
|
|
172
|
-
...(config.params || {}),
|
|
173
|
-
uri: uris.join("|"),
|
|
174
|
-
},
|
|
175
|
-
})
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Returns narrower concepts for a concept.
|
|
180
|
-
*
|
|
181
|
-
* @param {Object} config
|
|
182
|
-
* @param {Object} config.concept concept object
|
|
183
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
184
|
-
*/
|
|
185
|
-
async getNarrower({ concept, ...config }) {
|
|
186
|
-
if (!this._api.narrower) {
|
|
187
|
-
throw new errors.MissingApiUrlError()
|
|
188
|
-
}
|
|
189
|
-
if (!concept || !concept.uri) {
|
|
190
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concept" })
|
|
191
|
-
}
|
|
192
|
-
return this.axios({
|
|
193
|
-
...config,
|
|
194
|
-
method: "get",
|
|
195
|
-
url: this._api.narrower,
|
|
196
|
-
params: {
|
|
197
|
-
...this._defaultParams,
|
|
198
|
-
// ? What should the default limit be?
|
|
199
|
-
limit: 10000,
|
|
200
|
-
...(config.params || {}),
|
|
201
|
-
uri: concept.uri,
|
|
202
|
-
},
|
|
203
|
-
})
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Returns ancestor concepts for a concept.
|
|
208
|
-
*
|
|
209
|
-
* @param {Object} config
|
|
210
|
-
* @param {Object} config.concept concept object
|
|
211
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
212
|
-
*/
|
|
213
|
-
async getAncestors({ concept, ...config }) {
|
|
214
|
-
if (!this._api.ancestors) {
|
|
215
|
-
throw new errors.MissingApiUrlError()
|
|
216
|
-
}
|
|
217
|
-
if (!concept || !concept.uri) {
|
|
218
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concept" })
|
|
219
|
-
}
|
|
220
|
-
return this.axios({
|
|
221
|
-
...config,
|
|
222
|
-
method: "get",
|
|
223
|
-
url: this._api.ancestors,
|
|
224
|
-
params: {
|
|
225
|
-
...this._defaultParams,
|
|
226
|
-
// ? What should the default limit be?
|
|
227
|
-
limit: 10000,
|
|
228
|
-
...(config.params || {}),
|
|
229
|
-
uri: concept.uri,
|
|
230
|
-
},
|
|
231
|
-
})
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Returns suggestion result in OpenSearch Suggest Format.
|
|
236
|
-
*
|
|
237
|
-
* @param {Object} config
|
|
238
|
-
* @param {string} config.search search string
|
|
239
|
-
* @param {Object} [config.scheme] concept scheme to search in
|
|
240
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
241
|
-
* @param {string} [config.use=notation,label] which fields to search ("notation", "label" or "notation,label")
|
|
242
|
-
* @param {string[]} [config.types=[]] list of type URIs
|
|
243
|
-
* @param {string} [config.sort=score] sorting parameter
|
|
244
|
-
* @returns {Array} result in OpenSearch Suggest Format
|
|
245
|
-
*/
|
|
246
|
-
async suggest({ scheme, use = "notation,label", types = [], sort = "score", ...config }) {
|
|
247
|
-
return this._search({
|
|
248
|
-
...config,
|
|
249
|
-
endpoint: "suggest",
|
|
250
|
-
params: {
|
|
251
|
-
...config.params,
|
|
252
|
-
voc: _.get(scheme, "uri", ""),
|
|
253
|
-
type: types.join("|"),
|
|
254
|
-
use,
|
|
255
|
-
sort,
|
|
256
|
-
},
|
|
257
|
-
})
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Returns search results in JSKOS Format.
|
|
262
|
-
*
|
|
263
|
-
* @param {Object} config
|
|
264
|
-
* @param {string} config.search search string
|
|
265
|
-
* @param {Object} [config.scheme] concept scheme to search in
|
|
266
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
267
|
-
* @param {number} [config.offset=0] offset
|
|
268
|
-
* @param {string[]} [config.types=[]] list of type URIs
|
|
269
|
-
* @returns {Array} result in JSKOS Format
|
|
270
|
-
*/
|
|
271
|
-
async search({ scheme, types = [], ...config }) {
|
|
272
|
-
return this._search({
|
|
273
|
-
...config,
|
|
274
|
-
endpoint: "search",
|
|
275
|
-
params: {
|
|
276
|
-
...config.params,
|
|
277
|
-
voc: _.get(scheme, "uri", ""),
|
|
278
|
-
type: types.join("|"),
|
|
279
|
-
},
|
|
280
|
-
})
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Returns concept scheme suggestion result in OpenSearch Suggest Format.
|
|
285
|
-
*
|
|
286
|
-
* @param {Object} config
|
|
287
|
-
* @param {string} config.search search string
|
|
288
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
289
|
-
* @param {string} [config.use=notation,label] which fields to search ("notation", "label" or "notation,label")
|
|
290
|
-
* @param {string} [config.sort=score] sorting parameter
|
|
291
|
-
* @returns {Array} result in OpenSearch Suggest Format
|
|
292
|
-
*/
|
|
293
|
-
async vocSuggest({ use = "notation,label", sort = "score", ...config }) {
|
|
294
|
-
return this._search({
|
|
295
|
-
...config,
|
|
296
|
-
endpoint: "voc-suggest",
|
|
297
|
-
params: {
|
|
298
|
-
...config.params,
|
|
299
|
-
use,
|
|
300
|
-
sort,
|
|
301
|
-
},
|
|
302
|
-
})
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Returns concept scheme search results in JSKOS Format.
|
|
307
|
-
*
|
|
308
|
-
* @param {Object} config
|
|
309
|
-
* @param {string} config.search search string
|
|
310
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
311
|
-
* @param {number} [config.offset=0] offset
|
|
312
|
-
* @returns {Array} result in JSKOS Format
|
|
313
|
-
*/
|
|
314
|
-
async vocSearch(config) {
|
|
315
|
-
return this._search({
|
|
316
|
-
...config,
|
|
317
|
-
endpoint: "voc-search",
|
|
318
|
-
})
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
async _search({ endpoint, search, limit, offset, params, ...config }) {
|
|
322
|
-
let url = this._api[endpoint]
|
|
323
|
-
if (!url) {
|
|
324
|
-
throw new errors.MissingApiUrlError()
|
|
325
|
-
}
|
|
326
|
-
if (!search) {
|
|
327
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "search" })
|
|
328
|
-
}
|
|
329
|
-
limit = limit || this._jskos.suggestResultLimit || 100
|
|
330
|
-
offset = offset || 0
|
|
331
|
-
// Some registries use URL templates with {searchTerms}
|
|
332
|
-
url = url.replace("{searchTerms}", search)
|
|
333
|
-
return this.axios({
|
|
334
|
-
...config,
|
|
335
|
-
params: {
|
|
336
|
-
...this._defaultParams,
|
|
337
|
-
...params,
|
|
338
|
-
limit: limit,
|
|
339
|
-
count: limit, // Some endpoints use count instead of limit
|
|
340
|
-
offset,
|
|
341
|
-
search,
|
|
342
|
-
query: search,
|
|
343
|
-
},
|
|
344
|
-
method: "get",
|
|
345
|
-
url,
|
|
346
|
-
})
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Returns a list of types.
|
|
351
|
-
*
|
|
352
|
-
* @param {Object} config
|
|
353
|
-
* @param {Object} [config.scheme] concept scheme to load types for
|
|
354
|
-
* @returns {Object[]} array of JSKOS type objects
|
|
355
|
-
*/
|
|
356
|
-
async getTypes({ scheme, ...config }) {
|
|
357
|
-
if (!this._api.types) {
|
|
358
|
-
throw new errors.MissingApiUrlError()
|
|
359
|
-
}
|
|
360
|
-
if (Array.isArray(this._api.types)) {
|
|
361
|
-
return this._api.types
|
|
362
|
-
}
|
|
363
|
-
if (scheme && scheme.uri) {
|
|
364
|
-
_.set(config, "params.uri", scheme.uri)
|
|
365
|
-
}
|
|
366
|
-
return this.axios({
|
|
367
|
-
...config,
|
|
368
|
-
method: "get",
|
|
369
|
-
url: this._api.types,
|
|
370
|
-
})
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
ConceptApiProvider.providerName = "ConceptApi"
|
|
376
|
-
|
|
377
|
-
module.exports = ConceptApiProvider
|
package/providers/index.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
const errors = require("../errors")
|
|
2
|
-
const BaseProvider = require("./base-provider")
|
|
3
|
-
|
|
4
|
-
let providers = {
|
|
5
|
-
[BaseProvider.providerName]: BaseProvider,
|
|
6
|
-
init(registry) {
|
|
7
|
-
if (this[registry.provider]) {
|
|
8
|
-
return new this[registry.provider](registry)
|
|
9
|
-
}
|
|
10
|
-
throw new errors.InvalidProviderError()
|
|
11
|
-
},
|
|
12
|
-
addProvider(provider) {
|
|
13
|
-
if (provider.prototype instanceof providers[BaseProvider.providerName]) {
|
|
14
|
-
this[provider.providerName] = provider
|
|
15
|
-
} else {
|
|
16
|
-
throw new errors.InvalidProviderError()
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
for (let provider of [
|
|
22
|
-
require("./local-mappings-provider"),
|
|
23
|
-
require("./mappings-api-provider"),
|
|
24
|
-
require("./occurrences-api-provider"),
|
|
25
|
-
require("./concept-api-provider"),
|
|
26
|
-
require("./reconciliation-api-provider"),
|
|
27
|
-
require("./label-search-suggestion-provider"),
|
|
28
|
-
require("./skosmos-api-provider"),
|
|
29
|
-
require("./loc-api-provider"),
|
|
30
|
-
]) {
|
|
31
|
-
providers.addProvider(provider)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = providers
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
const BaseProvider = require("./base-provider")
|
|
2
|
-
const jskos = require("jskos-tools")
|
|
3
|
-
const _ = require("../utils/lodash")
|
|
4
|
-
const errors = require("../errors")
|
|
5
|
-
|
|
6
|
-
// TODO: Only keep the last 20 results in cache.
|
|
7
|
-
// TODO: Try to remove dependencies on `selected`, `scheme._registry.registry.uri`, etc.
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Label search suggestion provider.
|
|
11
|
-
*
|
|
12
|
-
* This provider offers mapping recommendations based on label match via the `/search` endpoint of JSKOS APIs.
|
|
13
|
-
*
|
|
14
|
-
* The provider requires that a list of initialized registries with search endpoints is provided via `setRegistries`. Note that it has further dependencies on Cocoda and might be adjusted to reduce these dependencies.
|
|
15
|
-
*
|
|
16
|
-
* To use it in a registry, specify `provider` as "LabelSearchSuggestion":
|
|
17
|
-
* ```json
|
|
18
|
-
* {
|
|
19
|
-
* "uri": "http://coli-conc.gbv.de/registry/coli-conc-recommendations"
|
|
20
|
-
* "provider": "LabelSearchSuggestion"
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* You can provide a list of excluded schemes as JSKOS objects in `excludedSchemes`.
|
|
25
|
-
*
|
|
26
|
-
* Additionally, the following JSKOS properties can be provided: `prefLabel`, `notation`, `definition`
|
|
27
|
-
*
|
|
28
|
-
* @extends BaseProvider
|
|
29
|
-
* @category Providers
|
|
30
|
-
*/
|
|
31
|
-
class LabelSearchSuggestionProvider extends BaseProvider {
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* @private
|
|
35
|
-
*/
|
|
36
|
-
_setup() {
|
|
37
|
-
this._cache = []
|
|
38
|
-
this.has.mappings = true
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Sets a local list of registries where the search providers are taken from.
|
|
43
|
-
*
|
|
44
|
-
* @param {Object[]} registries list of registries
|
|
45
|
-
*/
|
|
46
|
-
setRegistries(registries) {
|
|
47
|
-
this._registries = registries
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* List of search provider URIs.
|
|
52
|
-
*
|
|
53
|
-
* @private
|
|
54
|
-
*/
|
|
55
|
-
get _searchUris() {
|
|
56
|
-
const _searchUris = {}
|
|
57
|
-
for (let registry of this._registries) {
|
|
58
|
-
const search = _.get(registry, "_api.search") || _.get(registry, "_jskos.search") || registry.search
|
|
59
|
-
if (search && _.isString(search)) {
|
|
60
|
-
_searchUris[registry.uri] = search
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return _searchUris
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Override `supportsScheme` to check whether a search URI is available for the scheme's registry.
|
|
68
|
-
*
|
|
69
|
-
* @param {Object} scheme - target scheme to check for support
|
|
70
|
-
* @returns {boolean}
|
|
71
|
-
*/
|
|
72
|
-
supportsScheme(scheme) {
|
|
73
|
-
let targetRegistry = _.get(scheme, "_registry.uri")
|
|
74
|
-
return super.supportsScheme(scheme) && targetRegistry != null && this._searchUris && this._searchUris[targetRegistry]
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Returns a list of mappings.
|
|
79
|
-
*
|
|
80
|
-
* @param {Object} config
|
|
81
|
-
* @param {Object} config.from JSKOS concept on from side
|
|
82
|
-
* @param {Object} config.to JSKOS concept on to side
|
|
83
|
-
* @param {Object} config.mode mappings mode
|
|
84
|
-
* @param {Object} config.selected selected mappings in Cocoda
|
|
85
|
-
* @returns {Object[]} array of JSKOS mapping objects
|
|
86
|
-
*/
|
|
87
|
-
async getMappings({ from, to, mode, selected, limit = 10, ...config }) {
|
|
88
|
-
// TODO: Why mode?
|
|
89
|
-
if (mode != "or") {
|
|
90
|
-
return []
|
|
91
|
-
}
|
|
92
|
-
if (!this._searchUris) {
|
|
93
|
-
throw new errors.MissingApiUrlError({ message: "No registries available to search" })
|
|
94
|
-
}
|
|
95
|
-
if (!selected) {
|
|
96
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "selected" })
|
|
97
|
-
}
|
|
98
|
-
let promises = []
|
|
99
|
-
if (from && this.supportsScheme(selected.scheme[false])) {
|
|
100
|
-
promises.push(this._getMappings({ ...config, concept: from, sourceScheme: selected.scheme[true], targetScheme: selected.scheme[false], limit }))
|
|
101
|
-
} else {
|
|
102
|
-
promises.push(Promise.resolve([]))
|
|
103
|
-
}
|
|
104
|
-
if (to && this.supportsScheme(selected.scheme[true])) {
|
|
105
|
-
promises.push(this._getMappings({ ...config, concept: to, sourceScheme: selected.scheme[false], targetScheme: selected.scheme[true], limit, swap: true }))
|
|
106
|
-
} else {
|
|
107
|
-
promises.push(Promise.resolve([]))
|
|
108
|
-
}
|
|
109
|
-
let [fromResult, toResult] = await Promise.all(promises)
|
|
110
|
-
// Filter all duplicates from toResult
|
|
111
|
-
toResult = toResult.filter(m => !fromResult.find(n => jskos.compareMappingMembers(m, n)))
|
|
112
|
-
// Reduce number of results until limit is reached
|
|
113
|
-
while (fromResult.length + toResult.length > limit) {
|
|
114
|
-
if (toResult.length >= fromResult.length) {
|
|
115
|
-
toResult = toResult.slice(0, -1)
|
|
116
|
-
} else {
|
|
117
|
-
fromResult = fromResult.slice(0, -1)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return _.union(fromResult, toResult)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Internal function to get mapping recommendations for a certain concept with sourceScheme and targetScheme.
|
|
125
|
-
*
|
|
126
|
-
* @private
|
|
127
|
-
*
|
|
128
|
-
* @param {Object} config
|
|
129
|
-
* @param {Object} config.concept
|
|
130
|
-
* @param {Object} config.sourceScheme
|
|
131
|
-
* @param {Pbject} config.targetScheme
|
|
132
|
-
* @param {boolean} config.swap - whether to reverse the direction of the mappings
|
|
133
|
-
*/
|
|
134
|
-
async _getMappings({ concept, sourceScheme, targetScheme, limit, swap = false, ...config }) {
|
|
135
|
-
if (!concept || !sourceScheme || !targetScheme) {
|
|
136
|
-
return []
|
|
137
|
-
}
|
|
138
|
-
// If source scheme is the same as target scheme, skip
|
|
139
|
-
if (jskos.compare(sourceScheme, targetScheme)) {
|
|
140
|
-
return []
|
|
141
|
-
}
|
|
142
|
-
// Prepare label
|
|
143
|
-
// TODO: Can we use a language prioritiy list like for requests?
|
|
144
|
-
let label = jskos.prefLabel(concept, {
|
|
145
|
-
fallbackToUri: false,
|
|
146
|
-
language: this.languages[0] || this._defaultLanguages[0],
|
|
147
|
-
})
|
|
148
|
-
if (!label) {
|
|
149
|
-
return []
|
|
150
|
-
}
|
|
151
|
-
// Get results from API or cache
|
|
152
|
-
const results = await this._getResults({ ...config, label, targetScheme, limit })
|
|
153
|
-
// Map results to actual mappings
|
|
154
|
-
let mappings = results.map(result => ({
|
|
155
|
-
fromScheme: sourceScheme,
|
|
156
|
-
from: { memberSet: [concept] },
|
|
157
|
-
toScheme: targetScheme,
|
|
158
|
-
to: { memberSet: [result] },
|
|
159
|
-
type: ["http://www.w3.org/2004/02/skos/core#mappingRelation"],
|
|
160
|
-
}))
|
|
161
|
-
if (swap) {
|
|
162
|
-
// Swap mapping sides if only `to` was set
|
|
163
|
-
mappings = mappings.map(mapping => Object.assign(mapping, {
|
|
164
|
-
fromScheme: mapping.toScheme,
|
|
165
|
-
from: mapping.to,
|
|
166
|
-
toScheme: mapping.fromScheme,
|
|
167
|
-
to: mapping.from,
|
|
168
|
-
}))
|
|
169
|
-
}
|
|
170
|
-
return mappings
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Internal function that either makes an API request or uses a local cache.
|
|
175
|
-
*
|
|
176
|
-
* @private
|
|
177
|
-
*
|
|
178
|
-
* @param {Object} config
|
|
179
|
-
* @param {string} config.label
|
|
180
|
-
* @param {Object} config.targetScheme
|
|
181
|
-
*/
|
|
182
|
-
async _getResults({ label, targetScheme, limit, ...config }) {
|
|
183
|
-
// Use local cache.
|
|
184
|
-
let resultsFromCache = (this._cache[targetScheme.uri] || {})[label]
|
|
185
|
-
if (resultsFromCache && resultsFromCache._limit >= limit) {
|
|
186
|
-
return resultsFromCache
|
|
187
|
-
}
|
|
188
|
-
// Determine search URI for target scheme's registry
|
|
189
|
-
const targetRegistry = _.get(targetScheme, "_registry.uri")
|
|
190
|
-
const url = targetRegistry != null && this._searchUris && this._searchUris[targetRegistry]
|
|
191
|
-
if (!url) {
|
|
192
|
-
return []
|
|
193
|
-
}
|
|
194
|
-
// API request
|
|
195
|
-
const data = await this.axios({
|
|
196
|
-
...config,
|
|
197
|
-
method: "get",
|
|
198
|
-
url,
|
|
199
|
-
params: {
|
|
200
|
-
query: label,
|
|
201
|
-
limit,
|
|
202
|
-
voc: targetScheme.uri,
|
|
203
|
-
},
|
|
204
|
-
})
|
|
205
|
-
// Save result in cache
|
|
206
|
-
if (!this._cache[targetScheme.uri]) {
|
|
207
|
-
this._cache[targetScheme.uri] = {}
|
|
208
|
-
}
|
|
209
|
-
this._cache[targetScheme.uri][label] = data
|
|
210
|
-
this._cache[targetScheme.uri][label]._limit = limit
|
|
211
|
-
return data
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
LabelSearchSuggestionProvider.providerName = "LabelSearchSuggestion"
|
|
217
|
-
LabelSearchSuggestionProvider.stored = false
|
|
218
|
-
|
|
219
|
-
module.exports = LabelSearchSuggestionProvider
|