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
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { AbstractConceptMapProvider } = require('./cm-api');
|
|
3
|
+
const { PackageContentLoader } = require('../../library/package-manager');
|
|
4
|
+
const { ConceptMapDatabase } = require('./cm-database');
|
|
5
|
+
const { VersionUtilities } = require('../../library/version-utilities');
|
|
6
|
+
const {validateParameter} = require("../../library/utilities");
|
|
7
|
+
const {ConceptMap} = require("../library/conceptmap");
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Package-based ConceptMap provider using shared database layer
|
|
11
|
+
*/
|
|
12
|
+
class PackageConceptMapProvider extends AbstractConceptMapProvider {
|
|
13
|
+
USE_DATABASE_SEARCH = true;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {PackageContentLoader} packageLoader - Path to the extracted package folder
|
|
17
|
+
*/
|
|
18
|
+
constructor(packageLoader) {
|
|
19
|
+
super();
|
|
20
|
+
validateParameter(packageLoader, "packageLoader", PackageContentLoader);
|
|
21
|
+
this.packageLoader = packageLoader;
|
|
22
|
+
this.dbPath = path.join(packageLoader.packageFolder, '.conceptmaps.db');
|
|
23
|
+
this.database = new ConceptMapDatabase(this.dbPath);
|
|
24
|
+
this.conceptMapMap = new Map();
|
|
25
|
+
this.initialized = false;
|
|
26
|
+
this.count = 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the provider - check/create database and load concept maps into memory
|
|
31
|
+
* @returns {Promise<void>}
|
|
32
|
+
*/
|
|
33
|
+
async initialize() {
|
|
34
|
+
if (this.initialized) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const dbExists = await this.database.exists();
|
|
39
|
+
|
|
40
|
+
if (!dbExists) {
|
|
41
|
+
await this.database.create();
|
|
42
|
+
await this._populateDatabase();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.conceptMapMap = await this.database.loadAllConceptMaps();
|
|
46
|
+
this.initialized = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Populate the database with concept maps from the package
|
|
51
|
+
* @returns {Promise<void>}
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
async _populateDatabase() {
|
|
55
|
+
// Get all ConceptMap resources
|
|
56
|
+
const conceptMapEntries = await this.packageLoader.getResourcesByType('ConceptMap');
|
|
57
|
+
|
|
58
|
+
if (conceptMapEntries.length === 0) {
|
|
59
|
+
return; // No concept maps in this package
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const conceptMaps = [];
|
|
63
|
+
for (const entry of conceptMapEntries) {
|
|
64
|
+
const conceptMap = await this.packageLoader.loadFile(entry);
|
|
65
|
+
if (conceptMap.url) {
|
|
66
|
+
conceptMaps.push(new ConceptMap(conceptMap, this.packageLoader.fhirVersion())); // get in converted to R5 format
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (conceptMaps.length > 0) {
|
|
71
|
+
await this.database.batchUpsertConceptMaps(conceptMaps);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Fetches a concept map by URL and version
|
|
77
|
+
* @param {string} url - The canonical URL of the concept map
|
|
78
|
+
* @param {string} version - The version of the concept map
|
|
79
|
+
* @returns {Promise<Object>} The requested concept map
|
|
80
|
+
*/
|
|
81
|
+
async fetchConceptMap(url, version) {
|
|
82
|
+
await this.initialize();
|
|
83
|
+
this._validateFetchParams(url, version);
|
|
84
|
+
|
|
85
|
+
// Try exact match first: url|version
|
|
86
|
+
let key = `${url}|${version}`;
|
|
87
|
+
if (this.conceptMapMap.has(key)) {
|
|
88
|
+
return this.conceptMapMap.get(key);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// If version is semver, try url|major.minor
|
|
92
|
+
try {
|
|
93
|
+
if (VersionUtilities.isSemVer(version)) {
|
|
94
|
+
const majorMinor = VersionUtilities.getMajMin(version);
|
|
95
|
+
if (majorMinor) {
|
|
96
|
+
key = `${url}|${majorMinor}`;
|
|
97
|
+
if (this.conceptMapMap.has(key)) {
|
|
98
|
+
return this.conceptMapMap.get(key);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
// Ignore version parsing errors
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Finally try just the URL
|
|
107
|
+
if (this.conceptMapMap.has(url)) {
|
|
108
|
+
return this.conceptMapMap.get(url);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Searches for concept maps based on criteria
|
|
116
|
+
* @param {Array<{name: string, value: string}>} searchParams - Search criteria
|
|
117
|
+
* @returns {Promise<Array<Object>>} List of matching concept maps
|
|
118
|
+
*/
|
|
119
|
+
async searchConceptMaps(searchParams, elements = null) {
|
|
120
|
+
await this.initialize();
|
|
121
|
+
this._validateSearchParams(searchParams);
|
|
122
|
+
|
|
123
|
+
if (this.USE_DATABASE_SEARCH) {
|
|
124
|
+
return await this.database.search(this.spaceId, searchParams, elements);
|
|
125
|
+
} else {
|
|
126
|
+
const matches = [];
|
|
127
|
+
const seen = new Set(); // Track by URL to avoid duplicates from versioned keys
|
|
128
|
+
|
|
129
|
+
// Convert array format to object for easier access
|
|
130
|
+
const params = {};
|
|
131
|
+
for (const {name, value} of searchParams) {
|
|
132
|
+
params[name] = value.toLowerCase();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hasSearchParams = Object.keys(params).length > 0;
|
|
136
|
+
|
|
137
|
+
for (const vs of this.conceptMapMap.values()) {
|
|
138
|
+
const json = vs.jsonObj || vs;
|
|
139
|
+
|
|
140
|
+
// Only process each ConceptMap once (use URL to deduplicate)
|
|
141
|
+
const vsUrl = json.url;
|
|
142
|
+
if (seen.has(vsUrl)) {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!hasSearchParams) {
|
|
147
|
+
seen.add(vsUrl);
|
|
148
|
+
matches.push(vs);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Check each search parameter
|
|
153
|
+
let isMatch = true;
|
|
154
|
+
for (const [param, searchValue] of Object.entries(params)) {
|
|
155
|
+
// Ignore content-mode and supplements for ConceptMap search
|
|
156
|
+
if (param === 'content-mode' || param === 'supplements') {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (param === 'system') {
|
|
161
|
+
// Special handling: match against compose.include[].system
|
|
162
|
+
if (!this._matchSystem(json, searchValue)) {
|
|
163
|
+
isMatch = false;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
} else if (param === 'jurisdiction') {
|
|
167
|
+
// Special handling for jurisdiction - array of CodeableConcept
|
|
168
|
+
if (!this._matchJurisdiction(json.jurisdiction, searchValue)) {
|
|
169
|
+
isMatch = false;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
} else if (param === 'identifier') {
|
|
173
|
+
// Special handling for identifier
|
|
174
|
+
if (!this._matchIdentifier(json.identifier, searchValue)) {
|
|
175
|
+
isMatch = false;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
// Standard partial text match on property
|
|
180
|
+
const propValue = json[param];
|
|
181
|
+
if (!this._matchValue(propValue, searchValue)) {
|
|
182
|
+
isMatch = false;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (isMatch) {
|
|
189
|
+
seen.add(vsUrl);
|
|
190
|
+
// Return with prefixed id
|
|
191
|
+
const result = { ...json, id: `${this.spaceId}-${json.id}` };
|
|
192
|
+
matches.push(result);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return matches;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Check if a value matches the search term (partial, case-insensitive)
|
|
202
|
+
*/
|
|
203
|
+
_matchValue(propValue, searchValue) {
|
|
204
|
+
if (propValue === undefined || propValue === null) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
const strValue = String(propValue).toLowerCase();
|
|
208
|
+
return strValue.includes(searchValue);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Check if system matches any compose.include[].system
|
|
213
|
+
*/
|
|
214
|
+
_matchSystem(json, searchValue) {
|
|
215
|
+
if (!json.compose?.include || !Array.isArray(json.compose.include)) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
for (const include of json.compose.include) {
|
|
219
|
+
if (include.system && include.system.toLowerCase().includes(searchValue)) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Check if jurisdiction matches - jurisdiction is an array of CodeableConcept
|
|
228
|
+
*/
|
|
229
|
+
_matchJurisdiction(jurisdictions, searchValue) {
|
|
230
|
+
if (!jurisdictions || !Array.isArray(jurisdictions)) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
for (const cc of jurisdictions) {
|
|
234
|
+
if (cc.coding && Array.isArray(cc.coding)) {
|
|
235
|
+
for (const coding of cc.coding) {
|
|
236
|
+
if (coding.code && coding.code.toLowerCase().includes(searchValue)) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
if (coding.display && coding.display.toLowerCase().includes(searchValue)) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (cc.text && cc.text.toLowerCase().includes(searchValue)) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Check if identifier matches
|
|
253
|
+
*/
|
|
254
|
+
_matchIdentifier(identifiers, searchValue) {
|
|
255
|
+
if (!identifiers) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const idArray = Array.isArray(identifiers) ? identifiers : [identifiers];
|
|
259
|
+
for (const id of idArray) {
|
|
260
|
+
if (id.system && id.system.toLowerCase().includes(searchValue)) {
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
if (id.value && id.value.toLowerCase().includes(searchValue)) {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get statistics about the loaded concept maps
|
|
272
|
+
* @returns {Promise<Object>} Statistics object
|
|
273
|
+
*/
|
|
274
|
+
async getStatistics() {
|
|
275
|
+
await this.initialize();
|
|
276
|
+
return await this.database.getStatistics();
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Get the number of concept maps loaded into memory
|
|
281
|
+
* @returns {number} Number of unique concept maps in map
|
|
282
|
+
*/
|
|
283
|
+
getMapSize() {
|
|
284
|
+
const uniqueUrls = new Set();
|
|
285
|
+
for (const [key, conceptMap] of this.conceptMapMap.entries()) {
|
|
286
|
+
if (!key.includes('|')) { // Only count base URL keys
|
|
287
|
+
uniqueUrls.add(conceptMap.url);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return uniqueUrls.size;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async fetchConceptMapById(id) {
|
|
294
|
+
if (!this.spaceId) {
|
|
295
|
+
return this.conceptMapMap.get(id);
|
|
296
|
+
} else if (id.startsWith(this.spaceId+"-")) {
|
|
297
|
+
let key = id.substring(this.spaceId.length + 1);
|
|
298
|
+
return this.conceptMapMap.get(key);
|
|
299
|
+
} else {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// eslint-disable-next-line no-unused-vars
|
|
305
|
+
assignIds(ids) {
|
|
306
|
+
// nothing - we don't do any assigning.
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async findConceptMapForTranslation(opContext, conceptMaps, sourceSystem, sourceScope, targetScope, targetSystem) {
|
|
310
|
+
for (let cm of this.conceptMapMap.values()) {
|
|
311
|
+
if (cm.providesTranslation(sourceSystem, sourceScope, targetScope, targetSystem)) {
|
|
312
|
+
conceptMaps.push(cm);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
cmCount() {
|
|
318
|
+
return this.database.cmCount;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
module.exports = {
|
|
324
|
+
PackageConceptMapProvider
|
|
325
|
+
};
|