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,211 +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: Document namespace etc.
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Reconciliation Service API.
|
|
10
|
-
*
|
|
11
|
-
* This class provides access to the [Reconciliation Service API](https://reconciliation-api.github.io/specs/).
|
|
12
|
-
*
|
|
13
|
-
* To use it in a registry, specify `provider` as "ReconciliationApi", provide the API base URL as `api`, and the compatible scheme or schemes in `schemes`:
|
|
14
|
-
* ```json
|
|
15
|
-
* {
|
|
16
|
-
* "uri": "http://coli-conc.gbv.de/registry/wikidata-reconciliation",
|
|
17
|
-
* "provider": "ReconciliationApi",
|
|
18
|
-
* "api": "https://tools.wmflabs.org/openrefine-wikidata/{language}/api",
|
|
19
|
-
* "schemes": [
|
|
20
|
-
* {
|
|
21
|
-
* "uri": "http://bartoc.org/en/node/1940"
|
|
22
|
-
* }
|
|
23
|
-
* ],
|
|
24
|
-
* }
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* The string `{language}` in `api` will be replaced with the queried language for the reconciliation request.
|
|
28
|
-
*
|
|
29
|
-
* Additionally, the following JSKOS properties can be provided: `prefLabel`, `notation`, `definition`
|
|
30
|
-
*
|
|
31
|
-
* @extends BaseProvider
|
|
32
|
-
* @category Providers
|
|
33
|
-
*/
|
|
34
|
-
class ReconciliationApiProvider extends BaseProvider {
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @private
|
|
38
|
-
*/
|
|
39
|
-
_setup() {
|
|
40
|
-
this.has.mappings = true
|
|
41
|
-
this._cache = []
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Returns a list of mappings suggestions.
|
|
46
|
-
*
|
|
47
|
-
* @param {Object} config
|
|
48
|
-
* @param {Object} config.from JSKOS concept on from side
|
|
49
|
-
* @param {Object} config.to JSKOS concept on to side
|
|
50
|
-
* @param {Object} config.mode mappings mode
|
|
51
|
-
* @returns {Object[]} array of JSKOS mapping objects
|
|
52
|
-
*/
|
|
53
|
-
async getMappings({ from, to, mode, ...config }) {
|
|
54
|
-
let schemes = []
|
|
55
|
-
if (_.isArray(this.schemes)) {
|
|
56
|
-
schemes = this.schemes
|
|
57
|
-
}
|
|
58
|
-
let swap
|
|
59
|
-
let concept
|
|
60
|
-
let fromConceptScheme = _.get(from, "inScheme[0]")
|
|
61
|
-
let toConceptScheme = _.get(to, "inScheme[0]")
|
|
62
|
-
let fromScheme
|
|
63
|
-
let toScheme
|
|
64
|
-
if (!from || jskos.isContainedIn(fromConceptScheme, schemes)) {
|
|
65
|
-
swap = true
|
|
66
|
-
concept = to
|
|
67
|
-
fromScheme = toConceptScheme
|
|
68
|
-
toScheme = schemes.find(scheme => jskos.compare(scheme, fromConceptScheme)) || schemes[0]
|
|
69
|
-
} else {
|
|
70
|
-
swap = false
|
|
71
|
-
concept = from
|
|
72
|
-
fromScheme = fromConceptScheme
|
|
73
|
-
toScheme = schemes.find(scheme => jskos.compare(scheme, toConceptScheme)) || schemes[0]
|
|
74
|
-
}
|
|
75
|
-
// Temporary to filter out GND mapping requests...
|
|
76
|
-
// TODO: Remove?!?
|
|
77
|
-
if (mode != "or") {
|
|
78
|
-
return []
|
|
79
|
-
}
|
|
80
|
-
if (!this._api.api) {
|
|
81
|
-
throw new errors.MissingApiUrlError()
|
|
82
|
-
}
|
|
83
|
-
if (!concept) {
|
|
84
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: swap ? "to" : "from" })
|
|
85
|
-
}
|
|
86
|
-
// Prepare labels
|
|
87
|
-
let language = jskos.languagePreference.selectLanguage(concept.prefLabel)
|
|
88
|
-
if (!language) {
|
|
89
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: swap ? "to" : "from", message: "Missing language" })
|
|
90
|
-
}
|
|
91
|
-
let altLabels = _.get(concept, `altLabel.${language}`, [])
|
|
92
|
-
if (_.isString(altLabels)) {
|
|
93
|
-
altLabels = [altLabels]
|
|
94
|
-
}
|
|
95
|
-
let prefLabel = _.get(concept, `prefLabel.${language}`)
|
|
96
|
-
let labels = altLabels.concat([prefLabel])
|
|
97
|
-
labels = [prefLabel]
|
|
98
|
-
// Get results from API or cache
|
|
99
|
-
let { url, data: results } = await this._getReconciliationResults({ ...config, labels, language })
|
|
100
|
-
results = [].concat(...Object.values(results).map(value => value.result)).filter(r => r)
|
|
101
|
-
// Sort results, first by score descending, then by match, then by length of notation
|
|
102
|
-
results = results.sort((a, b) => {
|
|
103
|
-
if (a.score != b.score) {
|
|
104
|
-
return b.score - a.score
|
|
105
|
-
}
|
|
106
|
-
if (a.match != b.match) {
|
|
107
|
-
if (a.match) {
|
|
108
|
-
return -1
|
|
109
|
-
} else {
|
|
110
|
-
return 1
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return a.id.length - b.id.length
|
|
114
|
-
})
|
|
115
|
-
// Prepare namespace
|
|
116
|
-
let namespace = _.get(toScheme, "namespace", "")
|
|
117
|
-
// Map results to actual mappings
|
|
118
|
-
let mappings = results.map(result => ({
|
|
119
|
-
fromScheme,
|
|
120
|
-
from: { memberSet: [concept] },
|
|
121
|
-
toScheme,
|
|
122
|
-
to: { memberSet: [
|
|
123
|
-
{
|
|
124
|
-
uri: namespace + result.id,
|
|
125
|
-
},
|
|
126
|
-
] },
|
|
127
|
-
type: [
|
|
128
|
-
result.match ?
|
|
129
|
-
"http://www.w3.org/2004/02/skos/core#exactMatch" :
|
|
130
|
-
(
|
|
131
|
-
result.score >= 80 ?
|
|
132
|
-
"http://www.w3.org/2004/02/skos/core#closeMatch" :
|
|
133
|
-
"http://www.w3.org/2004/02/skos/core#mappingRelation"
|
|
134
|
-
),
|
|
135
|
-
],
|
|
136
|
-
}))
|
|
137
|
-
if (swap) {
|
|
138
|
-
// Swap mapping sides if only `to` was set
|
|
139
|
-
mappings = mappings.map(mapping => Object.assign(mapping, {
|
|
140
|
-
fromScheme: mapping.toScheme,
|
|
141
|
-
from: mapping.to,
|
|
142
|
-
toScheme: mapping.fromScheme,
|
|
143
|
-
to: mapping.from,
|
|
144
|
-
}))
|
|
145
|
-
}
|
|
146
|
-
mappings._url = url
|
|
147
|
-
return mappings
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Internal function that either makes an API request or uses a local cache.
|
|
152
|
-
*
|
|
153
|
-
* @private
|
|
154
|
-
*
|
|
155
|
-
* @param {Object} config passthrough of config object for axios request
|
|
156
|
-
* @param {string[]} labels list of labels to get results for
|
|
157
|
-
* @param {string} language language of labels
|
|
158
|
-
*/
|
|
159
|
-
async _getReconciliationResults({ labels, language, ...config }) {
|
|
160
|
-
labels = labels.sort()
|
|
161
|
-
// Use local cache.
|
|
162
|
-
let resultsFromCache = this._cache.find(item => {
|
|
163
|
-
return _.isEqual(item.labels, labels) && item.language == language
|
|
164
|
-
})
|
|
165
|
-
if (resultsFromCache) {
|
|
166
|
-
return resultsFromCache
|
|
167
|
-
}
|
|
168
|
-
// Prepare queries
|
|
169
|
-
let queries = {}
|
|
170
|
-
let index = 0
|
|
171
|
-
for (let label of labels) {
|
|
172
|
-
queries[`q${index}`] = {
|
|
173
|
-
query: label,
|
|
174
|
-
}
|
|
175
|
-
index += 1
|
|
176
|
-
}
|
|
177
|
-
let url = this._api.api
|
|
178
|
-
if (language) {
|
|
179
|
-
url = url.replace("{language}", language)
|
|
180
|
-
}
|
|
181
|
-
// Encode data
|
|
182
|
-
const encodedData = `queries=${encodeURIComponent(JSON.stringify(queries))}`
|
|
183
|
-
// Set appropriate header
|
|
184
|
-
_.set(config, ["headers", "Content-Type"], "application/x-www-form-urlencoded")
|
|
185
|
-
let data = await this.axios({
|
|
186
|
-
...config,
|
|
187
|
-
method: "post",
|
|
188
|
-
url,
|
|
189
|
-
data: encodedData,
|
|
190
|
-
})
|
|
191
|
-
data = data || {}
|
|
192
|
-
let newCacheEntry = {
|
|
193
|
-
labels,
|
|
194
|
-
language,
|
|
195
|
-
data,
|
|
196
|
-
url: `${url}${url.includes("?") ? "&" : "?"}${encodedData}`,
|
|
197
|
-
}
|
|
198
|
-
this._cache.push(newCacheEntry)
|
|
199
|
-
// Make sure there are a maximum of 20 entries in cache
|
|
200
|
-
if (this._cache.length > 20) {
|
|
201
|
-
this._cache = this._cache.slice(this._cache.length - 20)
|
|
202
|
-
}
|
|
203
|
-
return newCacheEntry
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
ReconciliationApiProvider.providerName = "ReconciliationApi"
|
|
209
|
-
ReconciliationApiProvider.stored = false
|
|
210
|
-
|
|
211
|
-
module.exports = ReconciliationApiProvider
|
|
@@ -1,441 +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
|
-
/**
|
|
7
|
-
* Skosmos API.
|
|
8
|
-
*
|
|
9
|
-
* [Skosmos](http://skosmos.org/) is a web application to publish SKOS-based vocabularies.
|
|
10
|
-
* This class provides access to a Skosmos instance via its REST API.
|
|
11
|
-
*
|
|
12
|
-
* To use it in a registry, specify `provider` as "SkosmosApi" and provide the API base URL as `api`:
|
|
13
|
-
* ```json
|
|
14
|
-
* {
|
|
15
|
-
* "uri": "http://coli-conc.gbv.de/registry/skosmos-zbw",
|
|
16
|
-
* "provider": "SkosmosApi",
|
|
17
|
-
* "api": "https://zbw.eu/beta/skosmos/rest/v1/",
|
|
18
|
-
* "schemes": [
|
|
19
|
-
* {
|
|
20
|
-
* "uri": "http://bartoc.org/en/node/313",
|
|
21
|
-
* "VOCID": "stw"
|
|
22
|
-
* }
|
|
23
|
-
* ]
|
|
24
|
-
* }
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* Currently, it is not possible to query a list of concept schemes from the API, so you need to provide this list including a `VOCID` for every scheme.
|
|
28
|
-
*
|
|
29
|
-
* Additionally, the following JSKOS properties can be provided: `prefLabel`, `notation`, `definition`
|
|
30
|
-
*
|
|
31
|
-
* @extends BaseProvider
|
|
32
|
-
* @category Providers
|
|
33
|
-
*/
|
|
34
|
-
class SkosmosApiProvider extends BaseProvider {
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @private
|
|
38
|
-
*/
|
|
39
|
-
_setup() {
|
|
40
|
-
this.has.schemes = true
|
|
41
|
-
this.has.top = false
|
|
42
|
-
this.has.data = true
|
|
43
|
-
this.has.concepts = true
|
|
44
|
-
this.has.narrower = true
|
|
45
|
-
this.has.ancestors = true
|
|
46
|
-
this.has.types = true // ?
|
|
47
|
-
this.has.suggest = true
|
|
48
|
-
this.has.search = true
|
|
49
|
-
// Set concepts and topConcepts for schemes
|
|
50
|
-
for (let scheme of this.schemes) {
|
|
51
|
-
scheme.concepts = [null]
|
|
52
|
-
scheme.topConcepts = []
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* @private
|
|
58
|
-
*/
|
|
59
|
-
_getApiUrl(scheme, endpoint, params) {
|
|
60
|
-
if (!scheme || !scheme.VOCID) {
|
|
61
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "scheme", message: "Missing scheme or VOCID property on scheme" })
|
|
62
|
-
}
|
|
63
|
-
endpoint = endpoint || ""
|
|
64
|
-
params = params || {}
|
|
65
|
-
if (!params.lang) {
|
|
66
|
-
params.lang = this.languages[0] || "en"
|
|
67
|
-
}
|
|
68
|
-
const paramString = Object.keys(params).map(k => `${k}=${encodeURIComponent(params[k])}`).join("&")
|
|
69
|
-
return `${this._api.api}${scheme.VOCID}${endpoint}${paramString ? "?" + paramString : ""}`
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @private
|
|
74
|
-
*/
|
|
75
|
-
_getDataUrl(concept, { addFormatParameter = true } = {}) {
|
|
76
|
-
const scheme = _.get(concept, "inScheme[0]")
|
|
77
|
-
if (!concept || !concept.uri) {
|
|
78
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concept", message: "Missing concept URI" })
|
|
79
|
-
}
|
|
80
|
-
return this._getApiUrl(scheme, "/data", addFormatParameter ? { format: "application/json" } : {})
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @private
|
|
85
|
-
*/
|
|
86
|
-
_toJskosConcept(skosmosConcept, { concept, scheme, result, language } = {}) {
|
|
87
|
-
if (!skosmosConcept) {
|
|
88
|
-
return null
|
|
89
|
-
}
|
|
90
|
-
concept = jskos.deepCopy(concept || {})
|
|
91
|
-
language = language || skosmosConcept.lang || "en"
|
|
92
|
-
|
|
93
|
-
concept.uri = skosmosConcept.uri
|
|
94
|
-
|
|
95
|
-
// Set inScheme
|
|
96
|
-
if (scheme) {
|
|
97
|
-
concept.inScheme = [scheme]
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Set prefLabel
|
|
101
|
-
let prefLabel = skosmosConcept.matchedPrefLabel || skosmosConcept.prefLabel || skosmosConcept.label
|
|
102
|
-
if (_.isString(prefLabel)) {
|
|
103
|
-
_.set(concept, `prefLabel.${language}`, prefLabel)
|
|
104
|
-
} else {
|
|
105
|
-
if (prefLabel && !_.isArray(prefLabel)) {
|
|
106
|
-
prefLabel = [prefLabel]
|
|
107
|
-
}
|
|
108
|
-
for (let label of prefLabel || []) {
|
|
109
|
-
_.set(concept, `prefLabel.${label.lang}`, label.value)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Set altLabel
|
|
114
|
-
let altLabel = skosmosConcept.altLabel
|
|
115
|
-
if (_.isString(altLabel)) {
|
|
116
|
-
_.set(concept, `altLabel.${language}`, [altLabel])
|
|
117
|
-
} else {
|
|
118
|
-
if (altLabel && !_.isArray(altLabel)) {
|
|
119
|
-
altLabel = [altLabel]
|
|
120
|
-
}
|
|
121
|
-
for (let label of altLabel || []) {
|
|
122
|
-
if (_.get(concept, `altLabel.${label.lang}`)) {
|
|
123
|
-
concept.altLabel[label.lang].push(label.value)
|
|
124
|
-
concept.altLabel[label.lang] = _.uniq(concept.altLabel[label.lang])
|
|
125
|
-
} else {
|
|
126
|
-
_.set(concept, `altLabel.${label.lang}`, [label.value])
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Set notation
|
|
132
|
-
const notation = skosmosConcept.notation || skosmosConcept["skos:notation"] || jskos.notation(concept)
|
|
133
|
-
if (notation) {
|
|
134
|
-
// notation can be string or object, so we're trying notation.value first
|
|
135
|
-
concept.notation = [notation.value || notation]
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Set broader
|
|
139
|
-
if (skosmosConcept.broader) {
|
|
140
|
-
if (!_.isArray(skosmosConcept.broader)) {
|
|
141
|
-
skosmosConcept.broader = [skosmosConcept.broader]
|
|
142
|
-
}
|
|
143
|
-
concept.broader = skosmosConcept.broader.map(concept => _.isString(concept) ? { uri: concept } : concept)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Set narrower
|
|
147
|
-
if (skosmosConcept.hasChildren === true) {
|
|
148
|
-
concept.narrower = [null]
|
|
149
|
-
} else if (skosmosConcept.hasChildren === false) {
|
|
150
|
-
concept.narrower = []
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Set type
|
|
154
|
-
if (skosmosConcept.type && !_.isArray(skosmosConcept.type)) {
|
|
155
|
-
skosmosConcept.type = [skosmosConcept.type]
|
|
156
|
-
}
|
|
157
|
-
concept.type = concept.type || []
|
|
158
|
-
for (let type of skosmosConcept.type || []) {
|
|
159
|
-
if (!jskos.isValidUri(type)) {
|
|
160
|
-
continue
|
|
161
|
-
}
|
|
162
|
-
const uriScheme = type.slice(0, type.indexOf(":"))
|
|
163
|
-
// Try to find uriScheme in @context
|
|
164
|
-
if (result && result["@context"] && result["@context"][uriScheme]) {
|
|
165
|
-
type = type.replace(uriScheme + ":", result["@context"][uriScheme])
|
|
166
|
-
}
|
|
167
|
-
concept.type.push(type)
|
|
168
|
-
}
|
|
169
|
-
concept.type = _.uniq(concept.type)
|
|
170
|
-
if (!concept.type.length) {
|
|
171
|
-
concept.type = ["http://www.w3.org/2004/02/skos/core#Concept"]
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return concept
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Returns all concept schemes.
|
|
179
|
-
*
|
|
180
|
-
* @param {Object} config
|
|
181
|
-
* @returns {Object[]} array of JSKOS concept scheme objects
|
|
182
|
-
*/
|
|
183
|
-
async getSchemes({ ...config }) {
|
|
184
|
-
// TODO: Re-evaluate!
|
|
185
|
-
if (!this._jskos.loadSchemeInfo) {
|
|
186
|
-
const result = this.schemes.map(s => jskos.deepCopy(s))
|
|
187
|
-
return result
|
|
188
|
-
}
|
|
189
|
-
const schemes = []
|
|
190
|
-
// TODO
|
|
191
|
-
const language = this.languages[0] || "en"
|
|
192
|
-
for (let scheme of this.schemes || []) {
|
|
193
|
-
const url = this._getApiUrl(scheme, "/", { lang: language })
|
|
194
|
-
const data = await this.axios({
|
|
195
|
-
...config,
|
|
196
|
-
method: "get",
|
|
197
|
-
url,
|
|
198
|
-
})
|
|
199
|
-
const resultScheme = data.conceptschemes.find(s => jskos.compare(s, scheme))
|
|
200
|
-
const label = resultScheme && (resultScheme.prefLabel || resultScheme.label || resultScheme.title)
|
|
201
|
-
if (label) {
|
|
202
|
-
_.set(scheme, `prefLabel.${language}`, label)
|
|
203
|
-
}
|
|
204
|
-
// TODO: If there is no label, redo the request with one of the available languages.
|
|
205
|
-
schemes.push(scheme)
|
|
206
|
-
}
|
|
207
|
-
return schemes
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Returns top concepts.
|
|
212
|
-
*
|
|
213
|
-
* @param {Object} config
|
|
214
|
-
* @param {Object} config.scheme concept scheme
|
|
215
|
-
* @returns {Object[]} array of JSKOS concept scheme objects
|
|
216
|
-
*/
|
|
217
|
-
async getTop({ scheme, ...config }) {
|
|
218
|
-
const url = this._getApiUrl(scheme, "/topConcepts")
|
|
219
|
-
const language = this.languages[0] || "en"
|
|
220
|
-
_.set(config, "params.lang", language)
|
|
221
|
-
_.set(config, "params.scheme", scheme.uri)
|
|
222
|
-
const response = await this.axios({
|
|
223
|
-
...config,
|
|
224
|
-
method: "get",
|
|
225
|
-
url,
|
|
226
|
-
})
|
|
227
|
-
const concepts = []
|
|
228
|
-
for (let concept of response.topconcepts || []) {
|
|
229
|
-
const newConcept = this._toJskosConcept(concept, {
|
|
230
|
-
scheme,
|
|
231
|
-
language,
|
|
232
|
-
})
|
|
233
|
-
newConcept.topConceptOf = [scheme]
|
|
234
|
-
concepts.push(newConcept)
|
|
235
|
-
}
|
|
236
|
-
return concepts
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Returns details for a list of concepts.
|
|
241
|
-
*
|
|
242
|
-
* @param {Object} config
|
|
243
|
-
* @param {Object[]} config.concepts list of concept objects to load
|
|
244
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
245
|
-
*/
|
|
246
|
-
async getConcepts({ concepts, ...config }) {
|
|
247
|
-
if (!_.isArray(concepts)) {
|
|
248
|
-
concepts = [concepts]
|
|
249
|
-
}
|
|
250
|
-
concepts = concepts.map(c => ({ uri: c.uri, inScheme: c.inScheme }))
|
|
251
|
-
const newConcepts = []
|
|
252
|
-
for (let concept of concepts) {
|
|
253
|
-
const url = this._getDataUrl(concept, { addFormatParameter: false })
|
|
254
|
-
if (!url) {
|
|
255
|
-
continue
|
|
256
|
-
}
|
|
257
|
-
const result = await this.axios({
|
|
258
|
-
...config,
|
|
259
|
-
method: "get",
|
|
260
|
-
url,
|
|
261
|
-
params: {
|
|
262
|
-
uri: concept.uri,
|
|
263
|
-
format: "application/json",
|
|
264
|
-
},
|
|
265
|
-
})
|
|
266
|
-
const resultConcept = result && result.graph && result.graph.find(c => jskos.compare(c, concept))
|
|
267
|
-
if (resultConcept) {
|
|
268
|
-
const newConcept = this._toJskosConcept(resultConcept, { concept, result })
|
|
269
|
-
// Set broader/narrower
|
|
270
|
-
for (let type of ["broader", "narrower"]) {
|
|
271
|
-
let relatives = resultConcept[type] || newConcept[type]
|
|
272
|
-
if (relatives && !_.isArray(relatives)) {
|
|
273
|
-
relatives = [relatives]
|
|
274
|
-
}
|
|
275
|
-
if (!relatives) {
|
|
276
|
-
relatives = []
|
|
277
|
-
}
|
|
278
|
-
newConcept[type] = relatives.map(r => this._toJskosConcept(result.graph.find(c => jskos.compare(c, r)), { scheme: concept.inScheme[0], result }))
|
|
279
|
-
// if (relatives.length) {
|
|
280
|
-
// newConcept[type] = [null]
|
|
281
|
-
// } else {
|
|
282
|
-
// newConcept[type] = []
|
|
283
|
-
// }
|
|
284
|
-
}
|
|
285
|
-
// Set ancestors to empty array
|
|
286
|
-
// ?
|
|
287
|
-
newConcept.ancestors = []
|
|
288
|
-
// Push to array
|
|
289
|
-
newConcepts.push(newConcept)
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return newConcepts
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Returns narrower concepts for a concept.
|
|
297
|
-
*
|
|
298
|
-
* @param {Object} config
|
|
299
|
-
* @param {Object} config.concept concept object
|
|
300
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
301
|
-
*/
|
|
302
|
-
async getNarrower({ concept, ...config }) {
|
|
303
|
-
if (!concept || !concept.uri) {
|
|
304
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concept" })
|
|
305
|
-
}
|
|
306
|
-
const scheme = concept.inScheme[0]
|
|
307
|
-
const url = this._getApiUrl(scheme, "/children")
|
|
308
|
-
_.set(config, "params.uri", concept.uri)
|
|
309
|
-
const response = await this.axios({
|
|
310
|
-
...config,
|
|
311
|
-
method: "get",
|
|
312
|
-
url,
|
|
313
|
-
})
|
|
314
|
-
const concepts = (response.narrower || []).map(c => this._toJskosConcept(c, { scheme }))
|
|
315
|
-
return concepts
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Returns ancestor concepts for a concept.
|
|
320
|
-
*
|
|
321
|
-
* @param {Object} config
|
|
322
|
-
* @param {Object} config.concept concept object
|
|
323
|
-
* @returns {Object[]} array of JSKOS concept objects
|
|
324
|
-
*/
|
|
325
|
-
async getAncestors({ concept, ...config }) {
|
|
326
|
-
if (!concept || !concept.uri) {
|
|
327
|
-
throw new errors.InvalidOrMissingParameterError({ parameter: "concept" })
|
|
328
|
-
}
|
|
329
|
-
const scheme = concept.inScheme[0]
|
|
330
|
-
const url = this._getApiUrl(scheme, "/broaderTransitive")
|
|
331
|
-
_.set(config, "params.uri", concept.uri)
|
|
332
|
-
const response = await this.axios({
|
|
333
|
-
...config,
|
|
334
|
-
method: "get",
|
|
335
|
-
url,
|
|
336
|
-
})
|
|
337
|
-
let ancestors = []
|
|
338
|
-
let uri = concept.uri
|
|
339
|
-
while (uri) {
|
|
340
|
-
if (uri != concept.uri) {
|
|
341
|
-
const ancestor = _.get(response, `broaderTransitive["${uri}"]`)
|
|
342
|
-
ancestors = [ancestor].concat(ancestors)
|
|
343
|
-
}
|
|
344
|
-
uri = _.get(response, `broaderTransitive["${uri}"].broader[0]`)
|
|
345
|
-
}
|
|
346
|
-
const concepts = ancestors.map(c => this._toJskosConcept(c, { scheme })).filter(c => c.uri != concept.uri)
|
|
347
|
-
return concepts
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Returns suggestion result in OpenSearch Suggest Format.
|
|
352
|
-
*
|
|
353
|
-
* @param {Object} config
|
|
354
|
-
* @param {string} config.search search string
|
|
355
|
-
* @param {Object} [config.scheme] concept scheme to search in
|
|
356
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
357
|
-
* @param {string[]} [config.types=[]] list of type URIs
|
|
358
|
-
* @returns {Array} result in OpenSearch Suggest Format
|
|
359
|
-
*/
|
|
360
|
-
async suggest(config) {
|
|
361
|
-
config._raw = true
|
|
362
|
-
const concepts = await this.search(config)
|
|
363
|
-
const result = [config.search, [], [], []]
|
|
364
|
-
for (let concept of concepts) {
|
|
365
|
-
const notation = jskos.notation(concept)
|
|
366
|
-
const label = jskos.prefLabel(concept)
|
|
367
|
-
result[1].push((notation ? notation + " " : "") + label)
|
|
368
|
-
result[2].push("")
|
|
369
|
-
result[3].push(concept.uri)
|
|
370
|
-
}
|
|
371
|
-
if (concepts._totalCount != undefined) {
|
|
372
|
-
result._totalCount = concepts._totalCount
|
|
373
|
-
} else {
|
|
374
|
-
result._totalCount = concepts.length
|
|
375
|
-
}
|
|
376
|
-
return result
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Returns concept search results.
|
|
381
|
-
*
|
|
382
|
-
* @param {Object} config
|
|
383
|
-
* @param {string} config.search search string
|
|
384
|
-
* @param {Object} [config.scheme] concept scheme to search in
|
|
385
|
-
* @param {number} [config.limit=100] maximum number of search results (default might be overridden by registry)
|
|
386
|
-
* @param {string[]} [config.types=[]] list of type URIs
|
|
387
|
-
* @returns {Array} array of JSKOS concept objects
|
|
388
|
-
*/
|
|
389
|
-
async search({ search, scheme, limit, types = [], ...config }) {
|
|
390
|
-
const url = this._getApiUrl(scheme, "/search")
|
|
391
|
-
_.set(config, "params.query", `${search}*`)
|
|
392
|
-
_.set(config, "params.unique", 1)
|
|
393
|
-
_.set(config, "params.maxhits", limit || 100)
|
|
394
|
-
_.set(config, "params.type", types.join(" "))
|
|
395
|
-
const response = await this.axios({
|
|
396
|
-
...config,
|
|
397
|
-
method: "get",
|
|
398
|
-
url,
|
|
399
|
-
})
|
|
400
|
-
const concepts = (response.results || []).map(c => this._toJskosConcept(c, { scheme }))
|
|
401
|
-
return concepts
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Returns a list of types.
|
|
406
|
-
*
|
|
407
|
-
* @param {Object} config
|
|
408
|
-
* @param {Object} [config.scheme] concept scheme to load types for
|
|
409
|
-
* @returns {Object[]} array of JSKOS type objects
|
|
410
|
-
*/
|
|
411
|
-
async getTypes({ scheme, ...config }) {
|
|
412
|
-
const url = this._getApiUrl(scheme, "/types")
|
|
413
|
-
const types = []
|
|
414
|
-
const response = await this.axios({
|
|
415
|
-
...config,
|
|
416
|
-
method: "get",
|
|
417
|
-
url,
|
|
418
|
-
})
|
|
419
|
-
for (let type of (response && response.types) || []) {
|
|
420
|
-
// Skip SKOS type Concept
|
|
421
|
-
if (type.uri == "http://www.w3.org/2004/02/skos/core#Concept") {
|
|
422
|
-
continue
|
|
423
|
-
}
|
|
424
|
-
// Set prefLabel if available
|
|
425
|
-
if (type.label) {
|
|
426
|
-
type.prefLabel = {
|
|
427
|
-
[response["@context"]["@language"]]: type.label,
|
|
428
|
-
}
|
|
429
|
-
delete type.label
|
|
430
|
-
}
|
|
431
|
-
types.push(type)
|
|
432
|
-
}
|
|
433
|
-
types._url = url
|
|
434
|
-
return types
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
SkosmosApiProvider.providerName = "SkosmosApi"
|
|
440
|
-
|
|
441
|
-
module.exports = SkosmosApiProvider
|
package/utils/lodash.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Exports a subset of lodash methods
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
get: require("lodash/get"),
|
|
5
|
-
set: require("lodash/set"),
|
|
6
|
-
uniq: require("lodash/uniq"),
|
|
7
|
-
intersection: require("lodash/intersection"),
|
|
8
|
-
union: require("lodash/union"),
|
|
9
|
-
forOwn: require("lodash/forOwn"),
|
|
10
|
-
// TOOD: Use Array.isArray instead
|
|
11
|
-
isArray: require("lodash/isArray"),
|
|
12
|
-
isObject: require("lodash/isObject"),
|
|
13
|
-
isString: require("lodash/isString"),
|
|
14
|
-
isEmpty: require("lodash/isEmpty"),
|
|
15
|
-
isEqual: require("lodash/isEqual"),
|
|
16
|
-
merge: require("lodash/merge"),
|
|
17
|
-
last: require("lodash/last"),
|
|
18
|
-
omit: require("lodash/omit"),
|
|
19
|
-
// TODO: Use native concat instead
|
|
20
|
-
concat: require("lodash/concat"),
|
|
21
|
-
}
|