fhirsmith 0.3.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/CHANGELOG.md +42 -0
- package/FHIRsmith.png +0 -0
- package/README.md +277 -0
- package/config-template.json +144 -0
- package/library/folder-setup.js +58 -0
- package/library/html-server.js +166 -0
- package/library/html.js +835 -0
- package/library/i18nsupport.js +259 -0
- package/library/languages.js +779 -0
- package/library/logger-telnet.js +205 -0
- package/library/logger.js +279 -0
- package/library/package-manager.js +876 -0
- package/library/utilities.js +196 -0
- package/library/version-utilities.js +1056 -0
- package/npmprojector/config-example.json +13 -0
- package/npmprojector/indexer.js +394 -0
- package/npmprojector/npmprojector.js +395 -0
- package/npmprojector/readme.md +174 -0
- package/npmprojector/watcher.js +335 -0
- package/package.json +119 -0
- package/packages/package-crawler.js +846 -0
- package/packages/packages-template.html +126 -0
- package/packages/packages.js +2838 -0
- package/passwords.ini +2 -0
- package/publisher/publisher-template.html +208 -0
- package/publisher/publisher.js +2167 -0
- package/publisher/task-draft.js +458 -0
- package/registry/api.js +735 -0
- package/registry/crawler.js +637 -0
- package/registry/model.js +513 -0
- package/registry/readme.md +243 -0
- package/registry/registry-data.json +121015 -0
- package/registry/registry-template.html +126 -0
- package/registry/registry.js +1395 -0
- package/registry/test-runner.js +237 -0
- package/root-template.html +124 -0
- package/server.js +524 -0
- package/shl/private-key.pem +5 -0
- package/shl/public-key.pem +18 -0
- package/shl/shl.js +1125 -0
- package/shl/vhl.js +69 -0
- package/static/FHIRsmith128.png +0 -0
- package/static/FHIRsmith16.png +0 -0
- package/static/FHIRsmith32.png +0 -0
- package/static/FHIRsmith64.png +0 -0
- package/static/assets/css/bootstrap-fhir.css +5302 -0
- package/static/assets/css/bootstrap-glyphicons.css +2 -0
- package/static/assets/css/bootstrap.css +4097 -0
- package/static/assets/css/jquery-ui.css +523 -0
- package/static/assets/css/jquery-ui.structure.css +863 -0
- package/static/assets/css/jquery-ui.structure.min.css +5 -0
- package/static/assets/css/jquery-ui.theme.css +439 -0
- package/static/assets/css/jquery-ui.theme.min.css +5 -0
- package/static/assets/css/jquery.ui.all.css +7 -0
- package/static/assets/css/modules.css +18 -0
- package/static/assets/css/project.css +367 -0
- package/static/assets/css/pygments-manni.css +66 -0
- package/static/assets/css/tags.css +74 -0
- package/static/assets/css/xml.css +2 -0
- package/static/assets/fonts/glyphiconshalflings-regular.eot +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.otf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.svg +175 -0
- package/static/assets/fonts/glyphiconshalflings-regular.ttf +0 -0
- package/static/assets/fonts/glyphiconshalflings-regular.woff +0 -0
- package/static/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
- package/static/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
- package/static/assets/ico/favicon.ico +0 -0
- package/static/assets/ico/favicon.png +0 -0
- package/static/assets/images/fhir-logo-www.png +0 -0
- package/static/assets/images/fhir-logo.png +0 -0
- package/static/assets/images/hl7-logo.png +0 -0
- package/static/assets/images/logo_ansinew.jpg +0 -0
- package/static/assets/images/search.png +0 -0
- package/static/assets/images/stripe.png +0 -0
- package/static/assets/images/target.png +0 -0
- package/static/assets/images/tx-registry-root.gif +0 -0
- package/static/assets/images/tx-registry.png +0 -0
- package/static/assets/images/tx-server.png +0 -0
- package/static/assets/images/tx-version.png +0 -0
- package/static/assets/js/bootstrap.min.js +6 -0
- package/static/assets/js/fhir-gw.js +259 -0
- package/static/assets/js/fhir.js +2 -0
- package/static/assets/js/html5shiv.js +8 -0
- package/static/assets/js/jcookie.js +96 -0
- package/static/assets/js/jquery-ui.min.js +6 -0
- package/static/assets/js/jquery.js +10716 -0
- package/static/assets/js/jquery.min.js +2 -0
- package/static/assets/js/jquery.ui.core.js +314 -0
- package/static/assets/js/jquery.ui.draggable.js +825 -0
- package/static/assets/js/jquery.ui.mouse.js +162 -0
- package/static/assets/js/jquery.ui.resizable.js +842 -0
- package/static/assets/js/jquery.ui.widget.js +268 -0
- package/static/assets/js/json2.js +487 -0
- package/static/assets/js/jtip.js +97 -0
- package/static/assets/js/respond.min.js +6 -0
- package/static/assets/js/statuspage.js +70 -0
- package/static/assets/js/xml.js +2 -0
- package/static/dist/js/bootstrap.js +1964 -0
- package/static/favicon.png +0 -0
- package/static/fhir.css +626 -0
- package/static/icon-fhir-16.png +0 -0
- package/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- package/static/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- package/static/images/ui-bg_flat_10_000000_40x100.png +0 -0
- package/static/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- package/static/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- package/static/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- package/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- package/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- package/static/images/ui-icons_222222_256x240.png +0 -0
- package/static/images/ui-icons_228ef1_256x240.png +0 -0
- package/static/images/ui-icons_ef8c08_256x240.png +0 -0
- package/static/images/ui-icons_ffd27a_256x240.png +0 -0
- package/static/images/ui-icons_ffffff_256x240.png +0 -0
- package/static/js/jquery.effects.blind.js +49 -0
- package/static/js/jquery.effects.bounce.js +78 -0
- package/static/js/jquery.effects.clip.js +54 -0
- package/static/js/jquery.effects.core.js +763 -0
- package/static/js/jquery.effects.drop.js +50 -0
- package/static/js/jquery.effects.explode.js +79 -0
- package/static/js/jquery.effects.fade.js +32 -0
- package/static/js/jquery.effects.fold.js +56 -0
- package/static/js/jquery.effects.highlight.js +50 -0
- package/static/js/jquery.effects.pulsate.js +51 -0
- package/static/js/jquery.effects.scale.js +178 -0
- package/static/js/jquery.effects.shake.js +57 -0
- package/static/js/jquery.effects.slide.js +50 -0
- package/static/js/jquery.effects.transfer.js +45 -0
- package/static/js/jquery.ui.accordion.js +611 -0
- package/static/js/jquery.ui.autocomplete.js +612 -0
- package/static/js/jquery.ui.button.js +416 -0
- package/static/js/jquery.ui.datepicker.js +1823 -0
- package/static/js/jquery.ui.dialog.js +878 -0
- package/static/js/jquery.ui.droppable.js +296 -0
- package/static/js/jquery.ui.position.js +252 -0
- package/static/js/jquery.ui.progressbar.js +109 -0
- package/static/js/jquery.ui.selectable.js +266 -0
- package/static/js/jquery.ui.slider.js +666 -0
- package/static/js/jquery.ui.sortable.js +1077 -0
- package/static/js/jquery.ui.tabs.js +758 -0
- package/stats.js +80 -0
- package/test-cache/vsac/vsac-valuesets.db +0 -0
- package/token/nginx_passport_setup.md +383 -0
- package/token/security_guide.md +294 -0
- package/token/token-template.html +330 -0
- package/token/token.js +1300 -0
- package/translations/Messages.properties +1510 -0
- package/translations/Messages_ar.properties +1399 -0
- package/translations/Messages_de.properties +836 -0
- package/translations/Messages_es.properties +737 -0
- package/translations/Messages_fr.properties +1 -0
- package/translations/Messages_ja.properties +893 -0
- package/translations/Messages_nl.properties +1357 -0
- package/translations/Messages_pt.properties +1302 -0
- package/translations/Messages_ru.properties +1 -0
- package/translations/Messages_uz.properties +1 -0
- package/translations/Messages_zh.properties +1 -0
- package/translations/rendering-phrases.properties +1128 -0
- package/translations/rendering-phrases_ar.properties +1091 -0
- package/translations/rendering-phrases_de.properties +6 -0
- package/translations/rendering-phrases_es.properties +6 -0
- package/translations/rendering-phrases_fr.properties +624 -0
- package/translations/rendering-phrases_ja.properties +21 -0
- package/translations/rendering-phrases_nl.properties +970 -0
- package/translations/rendering-phrases_pt.properties +1020 -0
- package/translations/rendering-phrases_ru.properties +1094 -0
- package/translations/rendering-phrases_uz.properties +1 -0
- package/translations/rendering-phrases_zh.properties +1 -0
- package/tx/README.md +418 -0
- package/tx/cm/cm-api.js +110 -0
- package/tx/cm/cm-database.js +735 -0
- package/tx/cm/cm-package.js +325 -0
- package/tx/cs/cs-api.js +789 -0
- package/tx/cs/cs-areacode.js +615 -0
- package/tx/cs/cs-country.js +1110 -0
- package/tx/cs/cs-cpt.js +785 -0
- package/tx/cs/cs-cs.js +1579 -0
- package/tx/cs/cs-currency.js +539 -0
- package/tx/cs/cs-db.js +1321 -0
- package/tx/cs/cs-hgvs.js +329 -0
- package/tx/cs/cs-lang.js +465 -0
- package/tx/cs/cs-loinc.js +1485 -0
- package/tx/cs/cs-mimetypes.js +238 -0
- package/tx/cs/cs-ndc.js +704 -0
- package/tx/cs/cs-omop.js +1025 -0
- package/tx/cs/cs-provider-api.js +43 -0
- package/tx/cs/cs-provider-list.js +37 -0
- package/tx/cs/cs-rxnorm.js +808 -0
- package/tx/cs/cs-snomed.js +1102 -0
- package/tx/cs/cs-ucum.js +514 -0
- package/tx/cs/cs-unii.js +271 -0
- package/tx/cs/cs-uri.js +218 -0
- package/tx/cs/cs-usstates.js +305 -0
- package/tx/dev.fhir.org.yml +14 -0
- package/tx/fixtures/test-cases-setup.json +18 -0
- package/tx/fixtures/test-cases.yml +16 -0
- package/tx/html/codesystem-operations.liquid +25 -0
- package/tx/html/home-metrics.liquid +247 -0
- package/tx/html/operations-form.liquid +148 -0
- package/tx/html/search-form.liquid +62 -0
- package/tx/html/tx-template.html +133 -0
- package/tx/html/valueset-operations.liquid +54 -0
- package/tx/importers/atc-to-fhir.js +316 -0
- package/tx/importers/import-loinc.module.js +1536 -0
- package/tx/importers/import-ndc.module.js +1088 -0
- package/tx/importers/import-rxnorm.module.js +898 -0
- package/tx/importers/import-sct.module.js +2457 -0
- package/tx/importers/import-unii.module.js +601 -0
- package/tx/importers/readme.md +453 -0
- package/tx/importers/subset-loinc.module.js +1081 -0
- package/tx/importers/subset-rxnorm.module.js +938 -0
- package/tx/importers/tx-import-base.js +351 -0
- package/tx/importers/tx-import-settings.js +310 -0
- package/tx/importers/tx-import.js +357 -0
- package/tx/library/canonical-resource.js +88 -0
- package/tx/library/capabilitystatement.js +292 -0
- package/tx/library/codesystem.js +774 -0
- package/tx/library/conceptmap.js +568 -0
- package/tx/library/designations.js +932 -0
- package/tx/library/errors.js +77 -0
- package/tx/library/extensions.js +117 -0
- package/tx/library/namingsystem.js +322 -0
- package/tx/library/operation-outcome.js +127 -0
- package/tx/library/parameters.js +105 -0
- package/tx/library/renderer.js +1559 -0
- package/tx/library/terminologycapabilities.js +418 -0
- package/tx/library/ucum-parsers.js +1029 -0
- package/tx/library/ucum-service.js +370 -0
- package/tx/library/ucum-types.js +1099 -0
- package/tx/library/valueset.js +543 -0
- package/tx/library.js +676 -0
- package/tx/ocl/cm-ocl.js +106 -0
- package/tx/ocl/cs-ocl.js +39 -0
- package/tx/ocl/vs-ocl.js +105 -0
- package/tx/operation-context.js +568 -0
- package/tx/params.js +613 -0
- package/tx/provider.js +403 -0
- package/tx/sct/ecl.js +1560 -0
- package/tx/sct/expressions.js +2077 -0
- package/tx/sct/structures.js +1396 -0
- package/tx/tx-html.js +1063 -0
- package/tx/tx.fhir.org.yml +39 -0
- package/tx/tx.js +927 -0
- package/tx/vs/vs-api.js +112 -0
- package/tx/vs/vs-database.js +786 -0
- package/tx/vs/vs-package.js +358 -0
- package/tx/vs/vs-vsac.js +366 -0
- package/tx/workers/batch-validate.js +129 -0
- package/tx/workers/batch.js +361 -0
- package/tx/workers/closure.js +32 -0
- package/tx/workers/expand.js +1845 -0
- package/tx/workers/lookup.js +407 -0
- package/tx/workers/metadata.js +467 -0
- package/tx/workers/operations.js +34 -0
- package/tx/workers/read.js +164 -0
- package/tx/workers/search.js +384 -0
- package/tx/workers/subsumes.js +334 -0
- package/tx/workers/translate.js +492 -0
- package/tx/workers/validate.js +2504 -0
- package/tx/workers/worker.js +904 -0
- package/tx/xml/capabilitystatement-xml.js +63 -0
- package/tx/xml/codesystem-xml.js +62 -0
- package/tx/xml/conceptmap-xml.js +65 -0
- package/tx/xml/namingsystem-xml.js +65 -0
- package/tx/xml/operationoutcome-xml.js +127 -0
- package/tx/xml/parameters-xml.js +312 -0
- package/tx/xml/terminologycapabilities-xml.js +64 -0
- package/tx/xml/valueset-xml.js +64 -0
- package/tx/xml/xml-base.js +603 -0
- package/vcl/vcl-parser.js +1098 -0
- package/vcl/vcl.js +253 -0
- package/windows-install.js +19 -0
- package/xig/xig-template.html +124 -0
- package/xig/xig.js +3049 -0
package/tx/cs/cs-lang.js
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
const { CodeSystemProvider, FilterExecutionContext, CodeSystemFactoryProvider} = require('./cs-api');
|
|
2
|
+
const { Language } = require('../../library/languages');
|
|
3
|
+
const { CodeSystem } = require("../library/codesystem");
|
|
4
|
+
const assert = require('assert');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Language component types for filtering
|
|
8
|
+
*/
|
|
9
|
+
const LanguageComponent = {
|
|
10
|
+
LANG: 'language',
|
|
11
|
+
EXTLANG: 'ext-lang',
|
|
12
|
+
SCRIPT: 'script',
|
|
13
|
+
REGION: 'region',
|
|
14
|
+
VARIANT: 'variant',
|
|
15
|
+
EXTENSION: 'extension',
|
|
16
|
+
PRIVATE_USE: 'private-use'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const CODES_LanguageComponent = Object.values(LanguageComponent);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Filter context for language component filters
|
|
23
|
+
*/
|
|
24
|
+
class IETFLanguageCodeFilter {
|
|
25
|
+
constructor(component, status) {
|
|
26
|
+
this.component = component; // LanguageComponent
|
|
27
|
+
this.status = status; // boolean - true if component must exist, false if must not exist
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* IETF Language CodeSystem Provider
|
|
33
|
+
* Provides validation and lookup for BCP 47 language tags
|
|
34
|
+
*/
|
|
35
|
+
class IETFLanguageCodeProvider extends CodeSystemProvider {
|
|
36
|
+
constructor(opContext, supplements) {
|
|
37
|
+
super(opContext, supplements);
|
|
38
|
+
this.languageDefinitions = opContext.i18n.languageDefinitions;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ========== Metadata Methods ==========
|
|
42
|
+
|
|
43
|
+
system() {
|
|
44
|
+
return 'urn:ietf:bcp:47'; // BCP 47 URI
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
version() {
|
|
48
|
+
return null; // No specific version for BCP 47. Could be date?
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
description() {
|
|
52
|
+
return 'IETF language codes (BCP 47)';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
name() {
|
|
56
|
+
return 'IETF Lang (BCP 47)';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
totalCount() {
|
|
60
|
+
return -1; // Unbounded - grammar-based system
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
hasParents() {
|
|
64
|
+
return false; // No hierarchy in language codes
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
contentMode() {
|
|
68
|
+
return 'complete'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
listFeatures() {
|
|
72
|
+
// not sure about this?
|
|
73
|
+
|
|
74
|
+
// // Return supported filter features
|
|
75
|
+
// return CODES_LanguageComponent.map(component => ({
|
|
76
|
+
// feature: `rest.Codesystem:${this.system()}.filter`,
|
|
77
|
+
// value: `${component}:exists`
|
|
78
|
+
// }));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
hasAnyDisplays(languages) {
|
|
82
|
+
const langs = this._ensureLanguages(languages);
|
|
83
|
+
if (this._hasAnySupplementDisplays(langs)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return super.hasAnyDisplays(langs);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ========== Code Information Methods ==========
|
|
90
|
+
|
|
91
|
+
async code(code) {
|
|
92
|
+
|
|
93
|
+
const ctxt = await this.#ensureContext(code);
|
|
94
|
+
if (ctxt instanceof Language) {
|
|
95
|
+
return ctxt.code;
|
|
96
|
+
}
|
|
97
|
+
throw new Error('Invalid context type');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async display(code) {
|
|
101
|
+
|
|
102
|
+
const ctxt = await this.#ensureContext(code);
|
|
103
|
+
if (!ctxt) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
if (this.opContext.langs.isEnglishOrNothing()) {
|
|
107
|
+
return this.languageDefinitions.present(ctxt).trim();
|
|
108
|
+
}
|
|
109
|
+
let disp = this._displayFromSupplements(ctxt.code);
|
|
110
|
+
if (disp) {
|
|
111
|
+
return disp;
|
|
112
|
+
}
|
|
113
|
+
return this.languageDefinitions.present(ctxt).trim();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async definition(code) {
|
|
117
|
+
|
|
118
|
+
await this.#ensureContext(code);
|
|
119
|
+
return null; // No definitions for language codes
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async isAbstract(code) {
|
|
123
|
+
|
|
124
|
+
await this.#ensureContext(code);
|
|
125
|
+
return false; // Language codes are not abstract
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async isInactive(code) {
|
|
129
|
+
|
|
130
|
+
await this.#ensureContext(code);
|
|
131
|
+
return false; // We don't track inactive language codes
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async isDeprecated(code) {
|
|
135
|
+
|
|
136
|
+
await this.#ensureContext(code);
|
|
137
|
+
return false; // We don't track deprecated language codes
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async designations(code, displays) {
|
|
141
|
+
|
|
142
|
+
const ctxt = await this.#ensureContext(code);
|
|
143
|
+
const designations = [];
|
|
144
|
+
if (ctxt != null) {
|
|
145
|
+
const primaryDisplay = this.languageDefinitions.present(ctxt).trim();
|
|
146
|
+
displays.addDesignation(true, 'active', 'en', CodeSystem.makeUseForDisplay(), primaryDisplay);
|
|
147
|
+
if (ctxt.isLangRegion()) {
|
|
148
|
+
const langDisplay = this.languageDefinitions.getDisplayForLang(ctxt.language);
|
|
149
|
+
const regionDisplay = this.languageDefinitions.getDisplayForRegion(ctxt.region);
|
|
150
|
+
const regionVariant = `${langDisplay} (${regionDisplay})`;
|
|
151
|
+
const regionVariant2 = `${langDisplay} (Region=${regionDisplay})`;
|
|
152
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant);
|
|
153
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), regionVariant2);
|
|
154
|
+
}
|
|
155
|
+
// add alternative displays if available
|
|
156
|
+
const displayCount = this.languageDefinitions.displayCount(ctxt);
|
|
157
|
+
for (let i = 0; i < displayCount; i++) {
|
|
158
|
+
const altDisplay = this.languageDefinitions.present(ctxt, i).trim();
|
|
159
|
+
if (altDisplay && altDisplay !== primaryDisplay) {
|
|
160
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), altDisplay);
|
|
161
|
+
// Add region variants for alternatives too
|
|
162
|
+
if (ctxt.isLangRegion()) {
|
|
163
|
+
const langDisplay = this.languageDefinitions.getDisplayForLang(ctxt.language, i);
|
|
164
|
+
const regionDisplay = this.languageDefinitions.getDisplayForRegion(ctxt.region);
|
|
165
|
+
const altRegionVariant = `${langDisplay} (${regionDisplay})`;
|
|
166
|
+
displays.addDesignation(false, 'active', 'en', CodeSystem.makeUseForDisplay(), altRegionVariant);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
this._listSupplementDesignations(ctxt.code, displays);
|
|
171
|
+
}
|
|
172
|
+
return designations;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
async #ensureContext(code) {
|
|
177
|
+
if (code == null) {
|
|
178
|
+
return code;
|
|
179
|
+
}
|
|
180
|
+
if (typeof code === 'string') {
|
|
181
|
+
const ctxt = await this.locate(code);
|
|
182
|
+
if (!ctxt.context) {
|
|
183
|
+
throw new Error(ctxt.message ? ctxt.message : `Invalid language code: ${code}`);
|
|
184
|
+
} else {
|
|
185
|
+
return ctxt.context;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (code instanceof Language) {
|
|
189
|
+
return code;
|
|
190
|
+
}
|
|
191
|
+
throw new Error("Unknown Type at #ensureContext: "+ (typeof code));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ========== Lookup Methods ==========
|
|
195
|
+
|
|
196
|
+
async locate(code) {
|
|
197
|
+
|
|
198
|
+
assert(!code || typeof code === 'string', 'code must be string');
|
|
199
|
+
if (!code) return { context: null, message: 'Empty code' };
|
|
200
|
+
|
|
201
|
+
const language = this.languageDefinitions.parse(code);
|
|
202
|
+
if (!language) {
|
|
203
|
+
return { context: null, message: undefined };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { context: language, message: null };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// ========== Filter Methods ==========
|
|
210
|
+
|
|
211
|
+
async doesFilter(prop, op, value) {
|
|
212
|
+
|
|
213
|
+
assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
|
|
214
|
+
assert(op != null && typeof op === 'string', 'op must be a non-null string');
|
|
215
|
+
assert(value != null && typeof value === 'string', 'value must be a non-null string');
|
|
216
|
+
|
|
217
|
+
// Support exists filters for language components
|
|
218
|
+
if (op === 'exists' && (value === 'true' || value === 'false')) {
|
|
219
|
+
return CODES_LanguageComponent.includes(prop);
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async searchFilter(filterContext, filter, sort) {
|
|
225
|
+
|
|
226
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
227
|
+
assert(filter && typeof filter === 'string', 'filter must be a non-null string');
|
|
228
|
+
assert(typeof sort === 'boolean', 'sort must be a boolean');
|
|
229
|
+
|
|
230
|
+
throw new Error('Text search not supported');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
async filter(filterContext, prop, op, value) {
|
|
235
|
+
|
|
236
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
237
|
+
assert(prop != null && typeof prop === 'string', 'prop must be a non-null string');
|
|
238
|
+
assert(op != null && typeof op === 'string', 'op must be a non-null string');
|
|
239
|
+
assert(value != null && typeof value === 'string', 'value must be a non-null string');
|
|
240
|
+
|
|
241
|
+
if (op !== 'exists') {
|
|
242
|
+
throw new Error(`Unsupported filter operator: ${op}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (value !== 'true' && value !== 'false') {
|
|
246
|
+
throw new Error(`Invalid exists value: ${value}, must be 'true' or 'false'`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const componentIndex = CODES_LanguageComponent.indexOf(prop);
|
|
250
|
+
if (componentIndex < 0) {
|
|
251
|
+
throw new Error(`Unsupported filter property: ${prop}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const component = CODES_LanguageComponent[componentIndex];
|
|
255
|
+
const status = value === 'true';
|
|
256
|
+
|
|
257
|
+
filterContext.filters.push(new IETFLanguageCodeFilter(component, status));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async executeFilters(filterContext) {
|
|
261
|
+
|
|
262
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
263
|
+
return filterContext.filters;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async filterSize(filterContext, set) {
|
|
267
|
+
|
|
268
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
269
|
+
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
270
|
+
|
|
271
|
+
throw new Error('Language valuesets cannot be expanded as they are based on a grammar');
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async filtersNotClosed(filterContext) {
|
|
275
|
+
|
|
276
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
277
|
+
return true; // Grammar-based system is not closed
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async filterMore(filterContext, set) {
|
|
281
|
+
|
|
282
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
283
|
+
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
284
|
+
throw new Error('Language valuesets cannot be expanded as they are based on a grammar');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async filterConcept(filterContext, set) {
|
|
288
|
+
|
|
289
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
290
|
+
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
291
|
+
throw new Error('Language valuesets cannot be expanded as they are based on a grammar');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async filterLocate(filterContext, set, code) {
|
|
295
|
+
|
|
296
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
297
|
+
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
298
|
+
assert(typeof code === 'string', 'code must be non-null string');
|
|
299
|
+
|
|
300
|
+
const language = this.languageDefinitions.parse(code);
|
|
301
|
+
if (!language) {
|
|
302
|
+
return `Invalid language code: ${code}`;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const filter = set;
|
|
306
|
+
let hasComponent = false;
|
|
307
|
+
|
|
308
|
+
switch (filter.component) {
|
|
309
|
+
case LanguageComponent.LANG:
|
|
310
|
+
hasComponent = !!language.language;
|
|
311
|
+
break;
|
|
312
|
+
case LanguageComponent.EXTLANG:
|
|
313
|
+
hasComponent = !!language.extLang.length;
|
|
314
|
+
break;
|
|
315
|
+
case LanguageComponent.SCRIPT:
|
|
316
|
+
hasComponent = !!language.script;
|
|
317
|
+
break;
|
|
318
|
+
case LanguageComponent.REGION:
|
|
319
|
+
hasComponent = !!language.region;
|
|
320
|
+
break;
|
|
321
|
+
case LanguageComponent.VARIANT:
|
|
322
|
+
hasComponent = !!language.variant;
|
|
323
|
+
break;
|
|
324
|
+
case LanguageComponent.EXTENSION:
|
|
325
|
+
hasComponent = !!language.extension;
|
|
326
|
+
break;
|
|
327
|
+
case LanguageComponent.PRIVATE_USE:
|
|
328
|
+
hasComponent = language.privateUse.length > 0;
|
|
329
|
+
break;
|
|
330
|
+
default:
|
|
331
|
+
return `Unknown language component: ${filter.component}`;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (hasComponent === filter.status) {
|
|
335
|
+
return language;
|
|
336
|
+
} else {
|
|
337
|
+
const action = filter.status ? 'does not contain' : 'contains';
|
|
338
|
+
const requirement = filter.status ? 'required' : 'not allowed';
|
|
339
|
+
return `The language code ${code} ${action} a ${filter.component}, and it is ${requirement}`;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async filterCheck(filterContext, set, concept) {
|
|
344
|
+
|
|
345
|
+
assert(filterContext && filterContext instanceof FilterExecutionContext, 'filterContext must be a FilterExecutionContext');
|
|
346
|
+
assert(set && set instanceof IETFLanguageCodeFilter, 'set must be a IETFLanguageCodeFilter');
|
|
347
|
+
const ctxt = await this.#ensureContext(concept);
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
const filter = set;
|
|
351
|
+
let hasComponent = false;
|
|
352
|
+
|
|
353
|
+
switch (filter.component) {
|
|
354
|
+
case LanguageComponent.LANG:
|
|
355
|
+
hasComponent = !!ctxt.language;
|
|
356
|
+
break;
|
|
357
|
+
case LanguageComponent.EXTLANG:
|
|
358
|
+
hasComponent = ctxt.extLang.length > 0;
|
|
359
|
+
break;
|
|
360
|
+
case LanguageComponent.SCRIPT:
|
|
361
|
+
hasComponent = !!ctxt.script;
|
|
362
|
+
break;
|
|
363
|
+
case LanguageComponent.REGION:
|
|
364
|
+
hasComponent = !!ctxt.region;
|
|
365
|
+
break;
|
|
366
|
+
case LanguageComponent.VARIANT:
|
|
367
|
+
hasComponent = !!ctxt.variant;
|
|
368
|
+
break;
|
|
369
|
+
case LanguageComponent.EXTENSION:
|
|
370
|
+
hasComponent = !!ctxt.extension;
|
|
371
|
+
break;
|
|
372
|
+
case LanguageComponent.PRIVATE_USE:
|
|
373
|
+
hasComponent = ctxt.privateUse.length > 0;
|
|
374
|
+
break;
|
|
375
|
+
default:
|
|
376
|
+
return `Unknown language component: ${filter.component}`;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return hasComponent === filter.status;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
// ========== Iterator Methods ==========
|
|
384
|
+
// Cannot iterate language codes (grammar-based)
|
|
385
|
+
|
|
386
|
+
// ========== Additional Methods ==========
|
|
387
|
+
|
|
388
|
+
async sameConcept(a, b) {
|
|
389
|
+
|
|
390
|
+
const codeA = await this.code(a);
|
|
391
|
+
const codeB = await this.code(b);
|
|
392
|
+
return codeA === codeB;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async subsumesTest(codeA, codeB) {
|
|
396
|
+
await this.#ensureContext(codeA);
|
|
397
|
+
await this.#ensureContext(codeB);
|
|
398
|
+
return 'not-subsumed'; // No subsumption in language codes
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
versionAlgorithm() {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
isNotClosed() {
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Factory for creating IETF Language CodeSystem providers
|
|
412
|
+
*/
|
|
413
|
+
class IETFLanguageCodeFactory extends CodeSystemFactoryProvider {
|
|
414
|
+
constructor(i18n) {
|
|
415
|
+
super(i18n);
|
|
416
|
+
this.uses = 0;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
defaultVersion() {
|
|
420
|
+
return ''; // No versioning for BCP 47
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
system() {
|
|
424
|
+
return 'urn:ietf:bcp:47'; // BCP 47 URI
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
version() {
|
|
428
|
+
return null; // No specific version for BCP 47. Could be date?
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
build(opContext, supplements) {
|
|
432
|
+
this.recordUse();
|
|
433
|
+
return new IETFLanguageCodeProvider(opContext, supplements);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
useCount() {
|
|
437
|
+
return this.uses;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
recordUse() {
|
|
441
|
+
this.uses++;
|
|
442
|
+
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
name() {
|
|
446
|
+
return 'IETF Lang (BCP 47)';
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
// eslint-disable-next-line no-unused-vars
|
|
451
|
+
async buildKnownValueSet(url, version) {
|
|
452
|
+
return null;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
id() {
|
|
456
|
+
return "languages";
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
module.exports = {
|
|
461
|
+
IETFLanguageCodeProvider,
|
|
462
|
+
IETFLanguageCodeFactory,
|
|
463
|
+
IETFLanguageCodeFilter,
|
|
464
|
+
LanguageComponent
|
|
465
|
+
};
|