jskos-server 2.4.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.
Files changed (112) hide show
  1. package/.dockerignore +20 -0
  2. package/.editorconfig +9 -0
  3. package/.github/workflows/docker.yml +59 -0
  4. package/.github/workflows/gh-pages.yml +23 -0
  5. package/.github/workflows/gh-release.yml +19 -0
  6. package/.github/workflows/test.yml +39 -0
  7. package/.husky/pre-commit +1 -0
  8. package/CHANGELOG.md +18 -0
  9. package/LICENSE +21 -0
  10. package/README.md +2710 -0
  11. package/bin/extra.js +81 -0
  12. package/bin/import.js +438 -0
  13. package/bin/mongodb.js +21 -0
  14. package/bin/reset.js +257 -0
  15. package/bin/upgrade.js +34 -0
  16. package/config/config.default.json +88 -0
  17. package/config/config.schema.json +877 -0
  18. package/config/config.test.json +107 -0
  19. package/config/index.js +77 -0
  20. package/config/setup.js +212 -0
  21. package/depdendencies.png +0 -0
  22. package/docker/.env +1 -0
  23. package/docker/Dockerfile +20 -0
  24. package/docker/README.md +175 -0
  25. package/docker/docker-compose.yml +29 -0
  26. package/docker/docker-entrypoint.sh +8 -0
  27. package/docker/mongo-initdb.d/mongo_setup.sh +22 -0
  28. package/ecosystem.example.json +7 -0
  29. package/errors/index.js +94 -0
  30. package/eslint.config.js +17 -0
  31. package/index.js +10 -0
  32. package/models/annotations.js +13 -0
  33. package/models/concepts.js +12 -0
  34. package/models/concordances.js +12 -0
  35. package/models/index.js +33 -0
  36. package/models/mappings.js +20 -0
  37. package/models/meta.js +21 -0
  38. package/models/registries.js +12 -0
  39. package/models/schemes.js +12 -0
  40. package/package.json +91 -0
  41. package/routes/annotations.js +83 -0
  42. package/routes/common.js +86 -0
  43. package/routes/concepts.js +64 -0
  44. package/routes/concordances.js +86 -0
  45. package/routes/data.js +19 -0
  46. package/routes/mappings.js +108 -0
  47. package/routes/registries.js +24 -0
  48. package/routes/schemes.js +72 -0
  49. package/routes/validate.js +37 -0
  50. package/server.js +190 -0
  51. package/services/abstract.js +328 -0
  52. package/services/annotations.js +237 -0
  53. package/services/concepts.js +459 -0
  54. package/services/concordances.js +264 -0
  55. package/services/data.js +30 -0
  56. package/services/index.js +34 -0
  57. package/services/mappings.js +978 -0
  58. package/services/registries.js +319 -0
  59. package/services/schemes.js +318 -0
  60. package/services/validate.js +39 -0
  61. package/status.schema.json +145 -0
  62. package/test/abstract-service.js +36 -0
  63. package/test/annotations/annotation.json +13 -0
  64. package/test/api.js +2481 -0
  65. package/test/chai.js +14 -0
  66. package/test/changes.js +179 -0
  67. package/test/concepts/conceptNoFileEnding +4 -0
  68. package/test/concepts/concepts-ddc-6-60-61-62.json +123 -0
  69. package/test/concordances/concordances.ndjson +2 -0
  70. package/test/config.js +26 -0
  71. package/test/configs/complex-config.json +90 -0
  72. package/test/configs/empty-object.json +1 -0
  73. package/test/configs/fail-array.json +1 -0
  74. package/test/configs/fail-empty.json +0 -0
  75. package/test/configs/fail-mapping-only-props1.json +5 -0
  76. package/test/configs/fail-mapping-only-props2.json +5 -0
  77. package/test/configs/fail-mapping-only-props3.json +5 -0
  78. package/test/configs/fail-mapping-only-props4.json +5 -0
  79. package/test/configs/fail-nonexisting-prop.json +3 -0
  80. package/test/configs/fail-port-string.json +3 -0
  81. package/test/configs/fail-registry-types.json +16 -0
  82. package/test/configs/registry-types.json +16 -0
  83. package/test/data-write.js +784 -0
  84. package/test/eslint.js +22 -0
  85. package/test/import-reset.js +287 -0
  86. package/test/infer-mappings.js +340 -0
  87. package/test/ipcheck.js +287 -0
  88. package/test/mappings/README.md +1 -0
  89. package/test/mappings/ddc-gnd-1.mapping.json +33 -0
  90. package/test/mappings/ddc-gnd-2.mapping.json +67 -0
  91. package/test/mappings/mapping-ddc-gnd-noScheme.json +145 -0
  92. package/test/mappings/mapping-ddc-gnd.json +175 -0
  93. package/test/mappings/mappings-ddc.json +214 -0
  94. package/test/registries/registries.ndjson +2 -0
  95. package/test/services.js +557 -0
  96. package/test/terminologies/terminologies.json +94 -0
  97. package/test/test-utils.js +182 -0
  98. package/test/utils.js +425 -0
  99. package/test/validate.js +226 -0
  100. package/utils/adjust.js +206 -0
  101. package/utils/auth.js +154 -0
  102. package/utils/changes.js +88 -0
  103. package/utils/db.js +106 -0
  104. package/utils/ipcheck.js +76 -0
  105. package/utils/middleware.js +636 -0
  106. package/utils/searchHelper.js +153 -0
  107. package/utils/status.js +77 -0
  108. package/utils/users.js +7 -0
  109. package/utils/utils.js +114 -0
  110. package/utils/uuid.js +6 -0
  111. package/utils/version.js +324 -0
  112. package/views/base.ejs +172 -0
@@ -0,0 +1,287 @@
1
+ import esmock from "esmock"
2
+ import assert from "node:assert"
3
+ import { ForbiddenAccessError } from "../errors/index.js"
4
+
5
+ const baseConfig = {
6
+ log: () => {},
7
+ warn: () => {},
8
+ error: () => {},
9
+ }
10
+
11
+ async function getIpCheck(config) {
12
+ return (await esmock("../utils/ipcheck.js", {
13
+ "../config/index.js": Object.assign({}, baseConfig, config),
14
+ })).ipcheck
15
+ }
16
+
17
+ describe("IP Check Middleware", () => {
18
+
19
+ it("should allow all requests if no IPs are given", async () => {
20
+ const config = {
21
+ mappings: {
22
+ read: {},
23
+ },
24
+ }
25
+ const ipcheck = await getIpCheck(config)
26
+ const tests = [
27
+ {
28
+ req: {
29
+ method: "GET",
30
+ type: "mappings",
31
+ ip: null,
32
+ },
33
+ next: (error) => {
34
+ assert.equal(error, undefined)
35
+ },
36
+ },
37
+ {
38
+ req: {
39
+ method: "GET",
40
+ type: "mappings",
41
+ ip: "127.0.0.1",
42
+ },
43
+ next: (error) => {
44
+ assert.equal(error, undefined)
45
+ },
46
+ },
47
+ ]
48
+ for (let { req, next } of tests) {
49
+ ipcheck(req, null, next)
50
+ }
51
+ })
52
+
53
+ it("should allow a single IP address", async () => {
54
+ const config = {
55
+ mappings: {
56
+ read: {
57
+ ips: ["1.2.3.4"],
58
+ },
59
+ },
60
+ }
61
+ const ipcheck = await getIpCheck(config)
62
+ const tests = [
63
+ {
64
+ req: {
65
+ method: "GET",
66
+ type: "mappings",
67
+ ip: null,
68
+ },
69
+ next: (error) => {
70
+ assert(error instanceof ForbiddenAccessError)
71
+ },
72
+ },
73
+ {
74
+ req: {
75
+ method: "GET",
76
+ type: "mappings",
77
+ ip: "127.0.0.1",
78
+ },
79
+ next: (error) => {
80
+ assert(error instanceof ForbiddenAccessError)
81
+ },
82
+ },
83
+ {
84
+ req: {
85
+ method: "GET",
86
+ type: "mappings",
87
+ ip: "1.2.3.4",
88
+ },
89
+ next: (error) => {
90
+ assert.equal(error, undefined)
91
+ },
92
+ },
93
+ ]
94
+ for (let { req, next } of tests) {
95
+ ipcheck(req, null, next)
96
+ }
97
+ })
98
+
99
+ it("should correctly recognize IPv6 loopback address", async () => {
100
+ const config = {
101
+ mappings: {
102
+ read: {
103
+ ips: ["127.0.0.1"],
104
+ },
105
+ },
106
+ }
107
+ const ipcheck = await getIpCheck(config)
108
+ const tests = [
109
+ {
110
+ req: {
111
+ method: "GET",
112
+ type: "mappings",
113
+ ip: null,
114
+ },
115
+ next: (error) => {
116
+ assert(error instanceof ForbiddenAccessError)
117
+ },
118
+ },
119
+ {
120
+ req: {
121
+ method: "GET",
122
+ type: "mappings",
123
+ ip: "127.0.0.1",
124
+ },
125
+ next: (error) => {
126
+ assert.equal(error, undefined)
127
+ },
128
+ },
129
+ {
130
+ req: {
131
+ method: "GET",
132
+ type: "mappings",
133
+ ip: "::1",
134
+ },
135
+ next: (error) => {
136
+ assert.equal(error, undefined)
137
+ },
138
+ },
139
+ ]
140
+ for (let { req, next } of tests) {
141
+ ipcheck(req, null, next)
142
+ }
143
+ })
144
+
145
+ it("should correctly handle CIDR ranges", async () => {
146
+ const config = {
147
+ mappings: {
148
+ read: {
149
+ ips: ["192.168.0.1/24"],
150
+ },
151
+ },
152
+ }
153
+ const ipcheck = await getIpCheck(config)
154
+ const tests = [
155
+ {
156
+ req: {
157
+ method: "GET",
158
+ type: "mappings",
159
+ ip: null,
160
+ },
161
+ next: (error) => {
162
+ assert(error instanceof ForbiddenAccessError)
163
+ },
164
+ },
165
+ {
166
+ req: {
167
+ method: "GET",
168
+ type: "mappings",
169
+ ip: "127.0.0.1",
170
+ },
171
+ next: (error) => {
172
+ assert(error instanceof ForbiddenAccessError)
173
+ },
174
+ },
175
+ {
176
+ req: {
177
+ method: "GET",
178
+ type: "mappings",
179
+ ip: "192.168.0.5",
180
+ },
181
+ next: (error) => {
182
+ assert.equal(error, undefined)
183
+ },
184
+ },
185
+ {
186
+ req: {
187
+ method: "GET",
188
+ type: "mappings",
189
+ ip: "192.168.0.254",
190
+ },
191
+ next: (error) => {
192
+ assert.equal(error, undefined)
193
+ },
194
+ },
195
+ {
196
+ req: {
197
+ method: "GET",
198
+ type: "mappings",
199
+ ip: "192.168.1.1",
200
+ },
201
+ next: (error) => {
202
+ assert(error instanceof ForbiddenAccessError)
203
+ },
204
+ },
205
+ ]
206
+ for (let { req, next } of tests) {
207
+ ipcheck(req, null, next)
208
+ }
209
+ })
210
+
211
+ it("should correctly handle multiple ranges and addresses", async () => {
212
+ const config = {
213
+ mappings: {
214
+ read: {
215
+ ips: ["192.168.1.1/24", "127.0.0.1", "1.2.3.4"],
216
+ },
217
+ },
218
+ }
219
+ const ipcheck = await getIpCheck(config)
220
+ const tests = [
221
+ {
222
+ req: {
223
+ method: "GET",
224
+ type: "mappings",
225
+ ip: null,
226
+ },
227
+ next: (error) => {
228
+ assert(error instanceof ForbiddenAccessError)
229
+ },
230
+ },
231
+ {
232
+ req: {
233
+ method: "GET",
234
+ type: "mappings",
235
+ ip: "127.0.0.1",
236
+ },
237
+ next: (error) => {
238
+ assert.equal(error, undefined)
239
+ },
240
+ },
241
+ {
242
+ req: {
243
+ method: "GET",
244
+ type: "mappings",
245
+ ip: "1.2.3.4",
246
+ },
247
+ next: (error) => {
248
+ assert.equal(error, undefined)
249
+ },
250
+ },
251
+ {
252
+ req: {
253
+ method: "GET",
254
+ type: "mappings",
255
+ ip: "1.2.3.5",
256
+ },
257
+ next: (error) => {
258
+ assert(error instanceof ForbiddenAccessError)
259
+ },
260
+ },
261
+ {
262
+ req: {
263
+ method: "GET",
264
+ type: "mappings",
265
+ ip: "192.168.0.5",
266
+ },
267
+ next: (error) => {
268
+ assert(error instanceof ForbiddenAccessError)
269
+ },
270
+ },
271
+ {
272
+ req: {
273
+ method: "GET",
274
+ type: "mappings",
275
+ ip: "192.168.1.1",
276
+ },
277
+ next: (error) => {
278
+ assert.equal(error, undefined)
279
+ },
280
+ },
281
+ ]
282
+ for (let { req, next } of tests) {
283
+ ipcheck(req, null, next)
284
+ }
285
+ })
286
+
287
+ })
@@ -0,0 +1 @@
1
+ This directory contains JSKOS Concept Mappings [taken from the JSKOS specification](https://github.com/gbv/jskos/tree/master/examples).
@@ -0,0 +1,33 @@
1
+ [
2
+ {
3
+ "type": [
4
+ "http://www.w3.org/2004/02/skos/core#closeMatch"
5
+ ],
6
+ "fromScheme": {
7
+ "uri": "http://dewey.info/scheme/edition/e22/"
8
+ },
9
+ "toScheme": {
10
+ "uri": "http://d-nb.info/gnd/7749153-1"
11
+ },
12
+ "from": {
13
+ "memberSet": [
14
+ {
15
+ "uri": "http://dewey.info/class/612.112/e22/",
16
+ "notation": [
17
+ "612.112"
18
+ ]
19
+ }
20
+ ]
21
+ },
22
+ "to": {
23
+ "memberSet": [
24
+ {
25
+ "uri": "http://d-nb.info/gnd/4074195-3",
26
+ "preflabel": {
27
+ "de": "Leukozyt"
28
+ }
29
+ }
30
+ ]
31
+ }
32
+ }
33
+ ]
@@ -0,0 +1,67 @@
1
+ [
2
+ {
3
+ "fromScheme": {
4
+ "uri": "http://dewey.info/scheme/edition/e22/"
5
+ },
6
+ "from": {
7
+ "memberSet": [
8
+ {
9
+ "uri": "http://dewey.info/class/612.112/e22/",
10
+ "notation": [
11
+ "612.112"
12
+ ]
13
+ }
14
+ ]
15
+ },
16
+ "toScheme": {
17
+ "uri": "http://d-nb.info/gnd/7749153-1"
18
+ },
19
+ "to": {
20
+ "memberChoice": [
21
+ {
22
+ "uri": "http://d-nb.info/gnd/4074195-3",
23
+ "preflabel": {
24
+ "de": "Leukozyt"
25
+ }
26
+ },
27
+ {
28
+ "uri": "http://d-nb.info/gnd/4141893-1",
29
+ "preflabel": {
30
+ "de": "Alkalische Leukozytenphosphatase"
31
+ }
32
+ },
33
+ {
34
+ "uri": "http://d-nb.info/gnd/7606617-4",
35
+ "preflabel": {
36
+ "de": "Blutlymphozyt"
37
+ }
38
+ },
39
+ {
40
+ "uri": "http://d-nb.info/gnd/4158047-3",
41
+ "preflabel": {
42
+ "de": "Granulozyt"
43
+ }
44
+ },
45
+ {
46
+ "uri": "http://d-nb.info/gnd/4227943-4",
47
+ "preflabel": {
48
+ "de": "Leukozytenadhäsion"
49
+ }
50
+ },
51
+ {
52
+ "uri": "http://d-nb.info/gnd/4166696-3",
53
+ "preflabel": {
54
+ "de": "Leukozytenphosphatase"
55
+ }
56
+ },
57
+ {
58
+ "uri": "http://d-nb.info/gnd/4285013-7",
59
+ "prefLabel": {
60
+ "de": "Monozyt"
61
+ }
62
+ }
63
+ ]
64
+ },
65
+ "mappingRelevance": 0.5
66
+ }
67
+ ]
@@ -0,0 +1,145 @@
1
+ [
2
+ {
3
+ "mappingRelevance": 0.5,
4
+ "type": [
5
+ "http://www.w3.org/2004/02/skos/core#exactMatch"
6
+ ],
7
+ "from": {
8
+ "memberSet": [
9
+ {
10
+ "notation": [
11
+ "612.112"
12
+ ],
13
+ "prefLabel": {
14
+ "de": "Leukozyten (Weiße Blutkörperchen)"
15
+ }
16
+ }
17
+ ]
18
+ },
19
+ "to": {
20
+ "memberSet": [
21
+ {
22
+ "uri": "http://d-nb.info/gnd/4074195-3",
23
+ "prefLabel": {
24
+ "de": "Leukozyt"
25
+ },
26
+ "notation": [
27
+ "4074195-3"
28
+ ]
29
+ }
30
+ ]
31
+ }
32
+ },
33
+ {
34
+ "mappingRelevance": 0.4,
35
+ "from": {
36
+ "memberSet": [
37
+ {
38
+ "uri": "http://dewey.info/class/612.112/e22/",
39
+ "notation": [
40
+ "612.112"
41
+ ],
42
+ "prefLabel": {
43
+ "de": "Leukozyten (Weiße Blutkörperchen)"
44
+ }
45
+ }
46
+ ]
47
+ },
48
+ "to": {
49
+ "memberChoice": [
50
+ {
51
+ "uri": "http://d-nb.info/gnd/4074195-3",
52
+ "prefLabel": {
53
+ "de": "Leukozyt"
54
+ },
55
+ "notation": [
56
+ "4074195-3"
57
+ ]
58
+ },
59
+ {
60
+ "uri": "http://d-nb.info/gnd/4141893-1",
61
+ "prefLabel": {
62
+ "de": "Alkalische Leukozytenphosphatase"
63
+ },
64
+ "notation": [
65
+ "4141893-1"
66
+ ]
67
+ },
68
+ {
69
+ "uri": "http://d-nb.info/gnd/7606617-4",
70
+ "prefLabel": {
71
+ "de": "Blutlymphozyt"
72
+ },
73
+ "notation": [
74
+ "7606617-4"
75
+ ]
76
+ },
77
+ {
78
+ "uri": "http://d-nb.info/gnd/4158047-3",
79
+ "prefLabel": {
80
+ "de": "Granulozyt"
81
+ },
82
+ "notation": [
83
+ "4158047-3"
84
+ ]
85
+ },
86
+ {
87
+ "uri": "http://d-nb.info/gnd/4227943-4",
88
+ "prefLabel": {
89
+ "de": "Leukozytenadhäsion"
90
+ },
91
+ "notation": [
92
+ "4227943-4"
93
+ ]
94
+ },
95
+ {
96
+ "uri": "http://d-nb.info/gnd/4166696-3",
97
+ "prefLabel": {
98
+ "de": "Leukozytenphosphatase"
99
+ },
100
+ "notation": [
101
+ "4166696-3"
102
+ ]
103
+ },
104
+ {
105
+ "uri": "http://d-nb.info/gnd/4285013-7",
106
+ "prefLabel": {
107
+ "de": "Monozyt"
108
+ },
109
+ "notation": [
110
+ "4285013-7"
111
+ ]
112
+ }
113
+ ]
114
+ }
115
+ },
116
+ {
117
+ "mappingRelevance": 0.9,
118
+ "from": {
119
+ "memberChoice": [
120
+ {
121
+ "uri": "http://dewey.info/class/612.112/e22/",
122
+ "notation": [
123
+ "612.112"
124
+ ],
125
+ "prefLabel": {
126
+ "de": "Leukozyten (Weiße Blutkörperchen)"
127
+ }
128
+ }
129
+ ]
130
+ },
131
+ "to": {
132
+ "memberSet": [
133
+ {
134
+ "uri": "http://d-nb.info/gnd/4499720-6",
135
+ "prefLabel": {
136
+ "de": "Leukozytenintegrine"
137
+ },
138
+ "notation": [
139
+ "4499720-6"
140
+ ]
141
+ }
142
+ ]
143
+ }
144
+ }
145
+ ]
@@ -0,0 +1,175 @@
1
+ [
2
+ {
3
+ "mappingRelevance": 0.5,
4
+ "type": [
5
+ "http://www.w3.org/2004/02/skos/core#exactMatch"
6
+ ],
7
+ "fromScheme": {
8
+ "notation": [
9
+ "DDC"
10
+ ]
11
+ },
12
+ "from": {
13
+ "memberSet": [
14
+ {
15
+ "notation": [
16
+ "612.112"
17
+ ],
18
+ "prefLabel": {
19
+ "de": "Leukozyten (Weiße Blutkörperchen)"
20
+ }
21
+ }
22
+ ]
23
+ },
24
+ "toScheme": {
25
+ "notation": [
26
+ "GND"
27
+ ]
28
+ },
29
+ "to": {
30
+ "memberSet": [
31
+ {
32
+ "uri": "http://d-nb.info/gnd/4074195-3",
33
+ "prefLabel": {
34
+ "de": "Leukozyt"
35
+ },
36
+ "notation": [
37
+ "4074195-3"
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+ },
43
+ {
44
+ "mappingRelevance": 0.4,
45
+ "fromScheme": {
46
+ "notation": [
47
+ "DDC"
48
+ ]
49
+ },
50
+ "from": {
51
+ "memberSet": [
52
+ {
53
+ "uri": "http://dewey.info/class/612.112/e22/",
54
+ "notation": [
55
+ "612.112"
56
+ ],
57
+ "prefLabel": {
58
+ "de": "Leukozyten (Weiße Blutkörperchen)"
59
+ }
60
+ }
61
+ ]
62
+ },
63
+ "toScheme": {
64
+ "notation": [
65
+ "GND"
66
+ ]
67
+ },
68
+ "to": {
69
+ "memberChoice": [
70
+ {
71
+ "uri": "http://d-nb.info/gnd/4074195-3",
72
+ "prefLabel": {
73
+ "de": "Leukozyt"
74
+ },
75
+ "notation": [
76
+ "4074195-3"
77
+ ]
78
+ },
79
+ {
80
+ "uri": "http://d-nb.info/gnd/4141893-1",
81
+ "prefLabel": {
82
+ "de": "Alkalische Leukozytenphosphatase"
83
+ },
84
+ "notation": [
85
+ "4141893-1"
86
+ ]
87
+ },
88
+ {
89
+ "uri": "http://d-nb.info/gnd/7606617-4",
90
+ "prefLabel": {
91
+ "de": "Blutlymphozyt"
92
+ },
93
+ "notation": [
94
+ "7606617-4"
95
+ ]
96
+ },
97
+ {
98
+ "uri": "http://d-nb.info/gnd/4158047-3",
99
+ "prefLabel": {
100
+ "de": "Granulozyt"
101
+ },
102
+ "notation": [
103
+ "4158047-3"
104
+ ]
105
+ },
106
+ {
107
+ "uri": "http://d-nb.info/gnd/4227943-4",
108
+ "prefLabel": {
109
+ "de": "Leukozytenadhäsion"
110
+ },
111
+ "notation": [
112
+ "4227943-4"
113
+ ]
114
+ },
115
+ {
116
+ "uri": "http://d-nb.info/gnd/4166696-3",
117
+ "prefLabel": {
118
+ "de": "Leukozytenphosphatase"
119
+ },
120
+ "notation": [
121
+ "4166696-3"
122
+ ]
123
+ },
124
+ {
125
+ "uri": "http://d-nb.info/gnd/4285013-7",
126
+ "prefLabel": {
127
+ "de": "Monozyt"
128
+ },
129
+ "notation": [
130
+ "4285013-7"
131
+ ]
132
+ }
133
+ ]
134
+ }
135
+ },
136
+ {
137
+ "mappingRelevance": 0.9,
138
+ "fromScheme": {
139
+ "notation": [
140
+ "DDC"
141
+ ]
142
+ },
143
+ "from": {
144
+ "memberChoice": [
145
+ {
146
+ "uri": "http://dewey.info/class/612.112/e22/",
147
+ "notation": [
148
+ "612.112"
149
+ ],
150
+ "prefLabel": {
151
+ "de": "Leukozyten (Weiße Blutkörperchen)"
152
+ }
153
+ }
154
+ ]
155
+ },
156
+ "toScheme": {
157
+ "notation": [
158
+ "GND"
159
+ ]
160
+ },
161
+ "to": {
162
+ "memberSet": [
163
+ {
164
+ "uri": "http://d-nb.info/gnd/4499720-6",
165
+ "prefLabel": {
166
+ "de": "Leukozytenintegrine"
167
+ },
168
+ "notation": [
169
+ "4499720-6"
170
+ ]
171
+ }
172
+ ]
173
+ }
174
+ }
175
+ ]