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.
Files changed (277) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/FHIRsmith.png +0 -0
  3. package/README.md +277 -0
  4. package/config-template.json +144 -0
  5. package/library/folder-setup.js +58 -0
  6. package/library/html-server.js +166 -0
  7. package/library/html.js +835 -0
  8. package/library/i18nsupport.js +259 -0
  9. package/library/languages.js +779 -0
  10. package/library/logger-telnet.js +205 -0
  11. package/library/logger.js +279 -0
  12. package/library/package-manager.js +876 -0
  13. package/library/utilities.js +196 -0
  14. package/library/version-utilities.js +1056 -0
  15. package/npmprojector/config-example.json +13 -0
  16. package/npmprojector/indexer.js +394 -0
  17. package/npmprojector/npmprojector.js +395 -0
  18. package/npmprojector/readme.md +174 -0
  19. package/npmprojector/watcher.js +335 -0
  20. package/package.json +119 -0
  21. package/packages/package-crawler.js +846 -0
  22. package/packages/packages-template.html +126 -0
  23. package/packages/packages.js +2838 -0
  24. package/passwords.ini +2 -0
  25. package/publisher/publisher-template.html +208 -0
  26. package/publisher/publisher.js +2167 -0
  27. package/publisher/task-draft.js +458 -0
  28. package/registry/api.js +735 -0
  29. package/registry/crawler.js +637 -0
  30. package/registry/model.js +513 -0
  31. package/registry/readme.md +243 -0
  32. package/registry/registry-data.json +121015 -0
  33. package/registry/registry-template.html +126 -0
  34. package/registry/registry.js +1395 -0
  35. package/registry/test-runner.js +237 -0
  36. package/root-template.html +124 -0
  37. package/server.js +524 -0
  38. package/shl/private-key.pem +5 -0
  39. package/shl/public-key.pem +18 -0
  40. package/shl/shl.js +1125 -0
  41. package/shl/vhl.js +69 -0
  42. package/static/FHIRsmith128.png +0 -0
  43. package/static/FHIRsmith16.png +0 -0
  44. package/static/FHIRsmith32.png +0 -0
  45. package/static/FHIRsmith64.png +0 -0
  46. package/static/assets/css/bootstrap-fhir.css +5302 -0
  47. package/static/assets/css/bootstrap-glyphicons.css +2 -0
  48. package/static/assets/css/bootstrap.css +4097 -0
  49. package/static/assets/css/jquery-ui.css +523 -0
  50. package/static/assets/css/jquery-ui.structure.css +863 -0
  51. package/static/assets/css/jquery-ui.structure.min.css +5 -0
  52. package/static/assets/css/jquery-ui.theme.css +439 -0
  53. package/static/assets/css/jquery-ui.theme.min.css +5 -0
  54. package/static/assets/css/jquery.ui.all.css +7 -0
  55. package/static/assets/css/modules.css +18 -0
  56. package/static/assets/css/project.css +367 -0
  57. package/static/assets/css/pygments-manni.css +66 -0
  58. package/static/assets/css/tags.css +74 -0
  59. package/static/assets/css/xml.css +2 -0
  60. package/static/assets/fonts/glyphiconshalflings-regular.eot +0 -0
  61. package/static/assets/fonts/glyphiconshalflings-regular.otf +0 -0
  62. package/static/assets/fonts/glyphiconshalflings-regular.svg +175 -0
  63. package/static/assets/fonts/glyphiconshalflings-regular.ttf +0 -0
  64. package/static/assets/fonts/glyphiconshalflings-regular.woff +0 -0
  65. package/static/assets/ico/apple-touch-icon-114-precomposed.png +0 -0
  66. package/static/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  67. package/static/assets/ico/apple-touch-icon-57-precomposed.png +0 -0
  68. package/static/assets/ico/apple-touch-icon-72-precomposed.png +0 -0
  69. package/static/assets/ico/favicon.ico +0 -0
  70. package/static/assets/ico/favicon.png +0 -0
  71. package/static/assets/images/fhir-logo-www.png +0 -0
  72. package/static/assets/images/fhir-logo.png +0 -0
  73. package/static/assets/images/hl7-logo.png +0 -0
  74. package/static/assets/images/logo_ansinew.jpg +0 -0
  75. package/static/assets/images/search.png +0 -0
  76. package/static/assets/images/stripe.png +0 -0
  77. package/static/assets/images/target.png +0 -0
  78. package/static/assets/images/tx-registry-root.gif +0 -0
  79. package/static/assets/images/tx-registry.png +0 -0
  80. package/static/assets/images/tx-server.png +0 -0
  81. package/static/assets/images/tx-version.png +0 -0
  82. package/static/assets/js/bootstrap.min.js +6 -0
  83. package/static/assets/js/fhir-gw.js +259 -0
  84. package/static/assets/js/fhir.js +2 -0
  85. package/static/assets/js/html5shiv.js +8 -0
  86. package/static/assets/js/jcookie.js +96 -0
  87. package/static/assets/js/jquery-ui.min.js +6 -0
  88. package/static/assets/js/jquery.js +10716 -0
  89. package/static/assets/js/jquery.min.js +2 -0
  90. package/static/assets/js/jquery.ui.core.js +314 -0
  91. package/static/assets/js/jquery.ui.draggable.js +825 -0
  92. package/static/assets/js/jquery.ui.mouse.js +162 -0
  93. package/static/assets/js/jquery.ui.resizable.js +842 -0
  94. package/static/assets/js/jquery.ui.widget.js +268 -0
  95. package/static/assets/js/json2.js +487 -0
  96. package/static/assets/js/jtip.js +97 -0
  97. package/static/assets/js/respond.min.js +6 -0
  98. package/static/assets/js/statuspage.js +70 -0
  99. package/static/assets/js/xml.js +2 -0
  100. package/static/dist/js/bootstrap.js +1964 -0
  101. package/static/favicon.png +0 -0
  102. package/static/fhir.css +626 -0
  103. package/static/icon-fhir-16.png +0 -0
  104. package/static/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  105. package/static/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  106. package/static/images/ui-bg_flat_10_000000_40x100.png +0 -0
  107. package/static/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  108. package/static/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  109. package/static/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  110. package/static/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  111. package/static/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  112. package/static/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  113. package/static/images/ui-icons_222222_256x240.png +0 -0
  114. package/static/images/ui-icons_228ef1_256x240.png +0 -0
  115. package/static/images/ui-icons_ef8c08_256x240.png +0 -0
  116. package/static/images/ui-icons_ffd27a_256x240.png +0 -0
  117. package/static/images/ui-icons_ffffff_256x240.png +0 -0
  118. package/static/js/jquery.effects.blind.js +49 -0
  119. package/static/js/jquery.effects.bounce.js +78 -0
  120. package/static/js/jquery.effects.clip.js +54 -0
  121. package/static/js/jquery.effects.core.js +763 -0
  122. package/static/js/jquery.effects.drop.js +50 -0
  123. package/static/js/jquery.effects.explode.js +79 -0
  124. package/static/js/jquery.effects.fade.js +32 -0
  125. package/static/js/jquery.effects.fold.js +56 -0
  126. package/static/js/jquery.effects.highlight.js +50 -0
  127. package/static/js/jquery.effects.pulsate.js +51 -0
  128. package/static/js/jquery.effects.scale.js +178 -0
  129. package/static/js/jquery.effects.shake.js +57 -0
  130. package/static/js/jquery.effects.slide.js +50 -0
  131. package/static/js/jquery.effects.transfer.js +45 -0
  132. package/static/js/jquery.ui.accordion.js +611 -0
  133. package/static/js/jquery.ui.autocomplete.js +612 -0
  134. package/static/js/jquery.ui.button.js +416 -0
  135. package/static/js/jquery.ui.datepicker.js +1823 -0
  136. package/static/js/jquery.ui.dialog.js +878 -0
  137. package/static/js/jquery.ui.droppable.js +296 -0
  138. package/static/js/jquery.ui.position.js +252 -0
  139. package/static/js/jquery.ui.progressbar.js +109 -0
  140. package/static/js/jquery.ui.selectable.js +266 -0
  141. package/static/js/jquery.ui.slider.js +666 -0
  142. package/static/js/jquery.ui.sortable.js +1077 -0
  143. package/static/js/jquery.ui.tabs.js +758 -0
  144. package/stats.js +80 -0
  145. package/test-cache/vsac/vsac-valuesets.db +0 -0
  146. package/token/nginx_passport_setup.md +383 -0
  147. package/token/security_guide.md +294 -0
  148. package/token/token-template.html +330 -0
  149. package/token/token.js +1300 -0
  150. package/translations/Messages.properties +1510 -0
  151. package/translations/Messages_ar.properties +1399 -0
  152. package/translations/Messages_de.properties +836 -0
  153. package/translations/Messages_es.properties +737 -0
  154. package/translations/Messages_fr.properties +1 -0
  155. package/translations/Messages_ja.properties +893 -0
  156. package/translations/Messages_nl.properties +1357 -0
  157. package/translations/Messages_pt.properties +1302 -0
  158. package/translations/Messages_ru.properties +1 -0
  159. package/translations/Messages_uz.properties +1 -0
  160. package/translations/Messages_zh.properties +1 -0
  161. package/translations/rendering-phrases.properties +1128 -0
  162. package/translations/rendering-phrases_ar.properties +1091 -0
  163. package/translations/rendering-phrases_de.properties +6 -0
  164. package/translations/rendering-phrases_es.properties +6 -0
  165. package/translations/rendering-phrases_fr.properties +624 -0
  166. package/translations/rendering-phrases_ja.properties +21 -0
  167. package/translations/rendering-phrases_nl.properties +970 -0
  168. package/translations/rendering-phrases_pt.properties +1020 -0
  169. package/translations/rendering-phrases_ru.properties +1094 -0
  170. package/translations/rendering-phrases_uz.properties +1 -0
  171. package/translations/rendering-phrases_zh.properties +1 -0
  172. package/tx/README.md +418 -0
  173. package/tx/cm/cm-api.js +110 -0
  174. package/tx/cm/cm-database.js +735 -0
  175. package/tx/cm/cm-package.js +325 -0
  176. package/tx/cs/cs-api.js +789 -0
  177. package/tx/cs/cs-areacode.js +615 -0
  178. package/tx/cs/cs-country.js +1110 -0
  179. package/tx/cs/cs-cpt.js +785 -0
  180. package/tx/cs/cs-cs.js +1579 -0
  181. package/tx/cs/cs-currency.js +539 -0
  182. package/tx/cs/cs-db.js +1321 -0
  183. package/tx/cs/cs-hgvs.js +329 -0
  184. package/tx/cs/cs-lang.js +465 -0
  185. package/tx/cs/cs-loinc.js +1485 -0
  186. package/tx/cs/cs-mimetypes.js +238 -0
  187. package/tx/cs/cs-ndc.js +704 -0
  188. package/tx/cs/cs-omop.js +1025 -0
  189. package/tx/cs/cs-provider-api.js +43 -0
  190. package/tx/cs/cs-provider-list.js +37 -0
  191. package/tx/cs/cs-rxnorm.js +808 -0
  192. package/tx/cs/cs-snomed.js +1102 -0
  193. package/tx/cs/cs-ucum.js +514 -0
  194. package/tx/cs/cs-unii.js +271 -0
  195. package/tx/cs/cs-uri.js +218 -0
  196. package/tx/cs/cs-usstates.js +305 -0
  197. package/tx/dev.fhir.org.yml +14 -0
  198. package/tx/fixtures/test-cases-setup.json +18 -0
  199. package/tx/fixtures/test-cases.yml +16 -0
  200. package/tx/html/codesystem-operations.liquid +25 -0
  201. package/tx/html/home-metrics.liquid +247 -0
  202. package/tx/html/operations-form.liquid +148 -0
  203. package/tx/html/search-form.liquid +62 -0
  204. package/tx/html/tx-template.html +133 -0
  205. package/tx/html/valueset-operations.liquid +54 -0
  206. package/tx/importers/atc-to-fhir.js +316 -0
  207. package/tx/importers/import-loinc.module.js +1536 -0
  208. package/tx/importers/import-ndc.module.js +1088 -0
  209. package/tx/importers/import-rxnorm.module.js +898 -0
  210. package/tx/importers/import-sct.module.js +2457 -0
  211. package/tx/importers/import-unii.module.js +601 -0
  212. package/tx/importers/readme.md +453 -0
  213. package/tx/importers/subset-loinc.module.js +1081 -0
  214. package/tx/importers/subset-rxnorm.module.js +938 -0
  215. package/tx/importers/tx-import-base.js +351 -0
  216. package/tx/importers/tx-import-settings.js +310 -0
  217. package/tx/importers/tx-import.js +357 -0
  218. package/tx/library/canonical-resource.js +88 -0
  219. package/tx/library/capabilitystatement.js +292 -0
  220. package/tx/library/codesystem.js +774 -0
  221. package/tx/library/conceptmap.js +568 -0
  222. package/tx/library/designations.js +932 -0
  223. package/tx/library/errors.js +77 -0
  224. package/tx/library/extensions.js +117 -0
  225. package/tx/library/namingsystem.js +322 -0
  226. package/tx/library/operation-outcome.js +127 -0
  227. package/tx/library/parameters.js +105 -0
  228. package/tx/library/renderer.js +1559 -0
  229. package/tx/library/terminologycapabilities.js +418 -0
  230. package/tx/library/ucum-parsers.js +1029 -0
  231. package/tx/library/ucum-service.js +370 -0
  232. package/tx/library/ucum-types.js +1099 -0
  233. package/tx/library/valueset.js +543 -0
  234. package/tx/library.js +676 -0
  235. package/tx/ocl/cm-ocl.js +106 -0
  236. package/tx/ocl/cs-ocl.js +39 -0
  237. package/tx/ocl/vs-ocl.js +105 -0
  238. package/tx/operation-context.js +568 -0
  239. package/tx/params.js +613 -0
  240. package/tx/provider.js +403 -0
  241. package/tx/sct/ecl.js +1560 -0
  242. package/tx/sct/expressions.js +2077 -0
  243. package/tx/sct/structures.js +1396 -0
  244. package/tx/tx-html.js +1063 -0
  245. package/tx/tx.fhir.org.yml +39 -0
  246. package/tx/tx.js +927 -0
  247. package/tx/vs/vs-api.js +112 -0
  248. package/tx/vs/vs-database.js +786 -0
  249. package/tx/vs/vs-package.js +358 -0
  250. package/tx/vs/vs-vsac.js +366 -0
  251. package/tx/workers/batch-validate.js +129 -0
  252. package/tx/workers/batch.js +361 -0
  253. package/tx/workers/closure.js +32 -0
  254. package/tx/workers/expand.js +1845 -0
  255. package/tx/workers/lookup.js +407 -0
  256. package/tx/workers/metadata.js +467 -0
  257. package/tx/workers/operations.js +34 -0
  258. package/tx/workers/read.js +164 -0
  259. package/tx/workers/search.js +384 -0
  260. package/tx/workers/subsumes.js +334 -0
  261. package/tx/workers/translate.js +492 -0
  262. package/tx/workers/validate.js +2504 -0
  263. package/tx/workers/worker.js +904 -0
  264. package/tx/xml/capabilitystatement-xml.js +63 -0
  265. package/tx/xml/codesystem-xml.js +62 -0
  266. package/tx/xml/conceptmap-xml.js +65 -0
  267. package/tx/xml/namingsystem-xml.js +65 -0
  268. package/tx/xml/operationoutcome-xml.js +127 -0
  269. package/tx/xml/parameters-xml.js +312 -0
  270. package/tx/xml/terminologycapabilities-xml.js +64 -0
  271. package/tx/xml/valueset-xml.js +64 -0
  272. package/tx/xml/xml-base.js +603 -0
  273. package/vcl/vcl-parser.js +1098 -0
  274. package/vcl/vcl.js +253 -0
  275. package/windows-install.js +19 -0
  276. package/xig/xig-template.html +124 -0
  277. package/xig/xig.js +3049 -0
@@ -0,0 +1,2504 @@
1
+ //
2
+ // Validate Worker - Handles $validate-code operations
3
+ //
4
+ // GET /CodeSystem/$validate-code?{params}
5
+ // POST /CodeSystem/$validate-code
6
+ // GET /CodeSystem/{id}/$validate-code?{params}
7
+ // POST /CodeSystem/{id}/$validate-code
8
+ // GET /ValueSet/$validate-code?{params}
9
+ // POST /ValueSet/$validate-code
10
+ // GET /ValueSet/{id}/$validate-code?{params}
11
+ // POST /ValueSet/{id}/$validate-code
12
+ //
13
+
14
+ const { TerminologyWorker } = require('./worker');
15
+ const {Languages, Language} = require("../../library/languages");
16
+ const {Extensions} = require("../library/extensions");
17
+ const {validateParameter, isAbsoluteUrl, validateOptionalParameter, getValuePrimitive} = require("../../library/utilities");
18
+ const {TxParameters} = require("../params");
19
+ const {OperationOutcome, Issue} = require("../library/operation-outcome");
20
+ const {Parameters} = require("../library/parameters");
21
+ const {Designations, DisplayCheckingStyle, DisplayDifference, SearchFilterText} = require("../library/designations");
22
+ const ValueSet = require("../library/valueset");
23
+ const {ValueSetExpander} = require("./expand");
24
+ const {FhirCodeSystemProvider} = require("../cs/cs-cs");
25
+ const {CodeSystem} = require("../library/codesystem");
26
+
27
+ const DEV_IGNORE_VALUESET = false; // todo: what's going on with this (ported from pascal)
28
+
29
+ /**
30
+ * Validation check mode - affects how errors are reported
31
+ */
32
+ const ValidationCheckMode = {
33
+ Code: 'code', // Just code string, infer system
34
+ Coding: 'coding', // Single coding with system/code
35
+ CodeableConcept: 'codeableConcept' // Multiple codings, any match is success
36
+ };
37
+
38
+ /**
39
+ * Value Set Checker - performs validation against a ValueSet
40
+ * Port of TValueSetChecker from Pascal
41
+ */
42
+ class ValueSetChecker {
43
+ worker;
44
+ valueSet;
45
+ params;
46
+ requiredSupplements = [];
47
+ others = new Map();
48
+
49
+ constructor(worker, valueSet, params) {
50
+ validateParameter(worker, "worker", TerminologyWorker);
51
+ validateOptionalParameter(valueSet, "valueSet", ValueSet);
52
+ validateParameter(params, "params", TxParameters);
53
+ this.worker = worker;
54
+ this.valueSet = valueSet;
55
+ this.params = params;
56
+ }
57
+
58
+ checkCanonicalStatus(path, op, resource, source) {
59
+ if (resource.jsonObj) {
60
+ resource = resource.jsonObj;
61
+ }
62
+ this.checkCanonicalStatusFull(path, op, resource.resourceType, this.worker.makeVurl(resource), resource.SourcePackage, resource.status, Extensions.readString(resource, 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status'), resource.experimental, source);
63
+ }
64
+
65
+ async checkCanonicalStatusCS(path, op, cs, source) {
66
+ let status = await cs.status();
67
+ if (cs.version()) {
68
+ this.checkCanonicalStatusFull(path, op, 'CodeSystem', cs.system() + '|' + cs.version(), cs.sourcePackage(), status.status, status.standardsStatus, status.experimental, source);
69
+ } else {
70
+ this.checkCanonicalStatusFull(path, op, 'CodeSystem', cs.system(), cs.sourcePackage(), status.status, status.standardsStatus, status.experimental, source);
71
+ }
72
+ }
73
+
74
+ checkCanonicalStatusFull(path, op, rtype, vurl, pid, status, standardsStatus, experimental, source) {
75
+ if (op !== null) {
76
+ if (standardsStatus === 'deprecated') {
77
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_DEPRECATED', this.worker.i18n.translate('MSG_DEPRECATED', this.params.HTTPLanguages, [vurl, '', rtype]), 'status-check'), false);
78
+ } else if (standardsStatus === 'withdrawn') {
79
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_WITHDRAWN', this.worker.i18n.translate('MSG_WITHDRAWN', this.params.HTTPLanguages, [vurl, '', rtype]), 'status-check'), false);
80
+ } else if (status === 'retired') {
81
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_RETIRED', this.worker.i18n.translate('MSG_RETIRED', this.params.HTTPLanguages, [vurl, '', rtype]), 'status-check'), false);
82
+ } else if (source !== null) {
83
+ if (experimental && !source.experimental) {
84
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_EXPERIMENTAL', this.worker.i18n.translate('MSG_EXPERIMENTAL', this.params.HTTPLanguages, [vurl, '', rtype]), 'status-check'), false);
85
+ } else if ((status === 'draft' || standardsStatus === 'draft') &&
86
+ !((source.status === 'draft') || (Extensions.readString(source, 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status') === 'draft'))) {
87
+ if (pid) {
88
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_DRAFT', this.worker.i18n.translate('MSG_DRAFT_SRC', this.params.HTTPLanguages, [vurl, pid, rtype]), 'status-check'), false);
89
+ } else {
90
+ op.addIssue(new Issue('information', 'business-rule', '', 'MSG_DRAFT', this.worker.i18n.translate('MSG_DRAFT', this.params.HTTPLanguages, [vurl, '', rtype]), 'status-check'), false);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ dispWarning() {
98
+ if (this.params.displayWarning) {
99
+ return 'warning';
100
+ } else {
101
+ return 'error';
102
+ }
103
+ }
104
+
105
+ async determineSystemFromExpansion(code, systems) {
106
+ let result;
107
+ try {
108
+ let txpe = this.params.clone();
109
+ txpe.limit = 10000;
110
+ let exp = new ValueSetExpander(this.worker, txpe);
111
+ let vse = await exp.expand(this.valueSet, new SearchFilterText(''), true);
112
+ result = '';
113
+ for (let c of vse.expansion.contains || []) {
114
+ this.worker.deadCheck('determineSystemFromExpansion');
115
+ if (c.code === code) {
116
+ systems.add(c.system);
117
+ if (!result) {
118
+ result = c.system;
119
+ } else {
120
+ return '';
121
+ }
122
+ }
123
+ }
124
+ } catch (e) {
125
+ console.error(e);
126
+ throw new Error('Exception expanding value set in order to infer system: ' + e.message);
127
+ }
128
+ return result;
129
+ }
130
+
131
+ fixedSystemFromValueSet() {
132
+ if (this.valueSet === null) {
133
+ return '';
134
+ }
135
+
136
+ let result = '';
137
+ for (let c of this.valueSet.jsonObj.include) {
138
+ this.worker.deadCheck('fixedSystemFromValueSet');
139
+ if (c.hasValueSets || !c.system) {
140
+ return '';
141
+ }
142
+ if (!result) {
143
+ result = c.system;
144
+ } else if (result !== c.system) {
145
+ return '';
146
+ }
147
+ }
148
+ return result;
149
+ }
150
+
151
+ async determineSystem(opContext, code, systems, op) {
152
+ let result = '';
153
+ let needDoExpansion = false;
154
+
155
+ for (let vsi of this.valueSet.jsonObj.compose.exclude || []) {
156
+ if (vsi.valueSet || !vsi.system || vsi.filter) {
157
+ needDoExpansion = true;
158
+ }
159
+ }
160
+ for (let vsi of this.valueSet.jsonObj.compose.include || []) {
161
+ if (vsi.valueSet || !vsi.system || vsi.filter) {
162
+ needDoExpansion = true;
163
+ }
164
+ }
165
+
166
+ if (needDoExpansion) {
167
+ result = await this.determineSystemFromExpansion(code, systems);
168
+ } else {
169
+ for (let vsi of this.valueSet.jsonObj.compose.include) {
170
+ this.worker.deadCheck('determineSystem');
171
+ let cs = await this.worker.findCodeSystem(vsi.system, '', null, ['complete', 'fragment'], op,true);
172
+ if (cs === null) {
173
+ return '';
174
+ }
175
+ if (vsi.concept) {
176
+ for (let cc of vsi.concept) {
177
+ this.worker.deadCheck('determineSystem#2');
178
+ let match = cc.code === code;
179
+ if (match) {
180
+ systems.add(vsi.system);
181
+ if (!result) {
182
+ result = vsi.system;
183
+ } else if (result !== vsi.system) {
184
+ return '';
185
+ }
186
+ }
187
+ }
188
+ } else {
189
+ let loc = await cs.locate(code);
190
+ if (loc.context !== null) {
191
+ systems.add(vsi.system);
192
+ if (!result) {
193
+ result = vsi.system;
194
+ } else if (result !== vsi.system) {
195
+ return '';
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ return result;
202
+ }
203
+
204
+ async determineVersion(path, system, versionVS, versionCoding, op, unknownSystems, messages) {
205
+ validateParameter(path, "path", String);
206
+ validateParameter(system, "system", String);
207
+ validateOptionalParameter(versionVS, "versionVS", String);
208
+ validateOptionalParameter(versionCoding, "versionCoding", String);
209
+ validateParameter(op, "op", OperationOutcome);
210
+ validateParameter(unknownSystems, "unknownSystems", Set);
211
+ validateParameter(messages, "messages", Array);
212
+
213
+
214
+ let result;
215
+ let csa = await this.worker.findCodeSystem(system, '', this.params, "*", op,true, false, true);
216
+
217
+ result = this.worker.determineVersionBase(system, versionVS, this.params);
218
+
219
+ if (versionCoding) {
220
+ if (result) {
221
+ if (csa !== null) {
222
+ if (versionCoding != result && csa.versionIsMoreDetailed(result, versionCoding)) {
223
+ result = versionCoding;
224
+ }
225
+ }
226
+ }
227
+ if (!result) {
228
+ let vl = await this.worker.listVersions(system);
229
+ if (vl.find(v => v == versionCoding || (csa && csa.versionIsMoreDetailed(versionCoding, v)))) {
230
+ result = versionCoding;
231
+ }
232
+ }
233
+
234
+ let cs = await this.worker.findCodeSystem(system, result, this.params, ['complete', 'fragment'], op,true, false, false);
235
+ if (cs !== null && cs.version() !== versionCoding && !cs.versionIsMoreDetailed(versionCoding, cs.version())) {
236
+ let errLvl = 'error';
237
+ let msg, mid;
238
+ if (!result) {
239
+ if (!cs.versionNeeded()) {
240
+ errLvl = 'warning';
241
+ }
242
+ msg = this.worker.i18n.translate('VALUESET_VALUE_MISMATCH_DEFAULT', this.params.HTTPLanguages, [system, cs.version(), versionVS, versionCoding]);
243
+ mid = 'VALUESET_VALUE_MISMATCH_DEFAULT';
244
+ } else if (result !== versionVS) {
245
+ msg = this.worker.i18n.translate('VALUESET_VALUE_MISMATCH_CHANGED', this.params.HTTPLanguages, [system, result, versionVS ? versionVS : "", versionCoding]);
246
+ mid = 'VALUESET_VALUE_MISMATCH_CHANGED';
247
+ } else {
248
+ msg = this.worker.i18n.translate('VALUESET_VALUE_MISMATCH', this.params.HTTPLanguages, [system, versionVS, versionCoding]);
249
+ mid = 'VALUESET_VALUE_MISMATCH';
250
+ }
251
+ op.addIssue(new Issue(errLvl, 'invalid', addToPath(path, 'version'), mid, msg, 'vs-invalid'));
252
+ if (errLvl === 'error') {
253
+ messages.push(msg);
254
+ }
255
+ let cs2 = await this.worker.findCodeSystem(system, versionCoding, this.params, ['complete', 'fragment'], op, true, false, true);
256
+ if (cs2 !== null) {
257
+ cs2 = null;
258
+ } else {
259
+ let vl = await this.worker.listVersions(system);
260
+ unknownSystems.add(system + '|' + versionCoding);
261
+ msg = this.worker.i18n.translate('UNKNOWN_CODESYSTEM_VERSION', this.params.HTTPLanguages, [system, versionCoding, this.worker.presentVersionList(vl)]);
262
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), 'UNKNOWN_CODESYSTEM_VERSION', msg, 'not-found'));
263
+ messages.push(msg);
264
+ }
265
+ } else if (cs === null && result !== versionCoding) {
266
+ let msg = this.worker.i18n.translate('VALUESET_VALUE_MISMATCH', this.params.HTTPLanguages, [system, result, versionCoding]);
267
+ op.addIssue(new Issue('error', 'invalid', addToPath(path, 'version'), 'VALUESET_VALUE_MISMATCH', msg, 'vs-invalid'));
268
+ messages.push(msg);
269
+ }
270
+ }
271
+ return result;
272
+ }
273
+
274
+ seeValueSet() {
275
+ this.worker.opContext.seeContext(this.valueSet.vurl);
276
+ if (this.valueSet.jsonObj.compose && this.valueSet.jsonObj.compose.extension) {
277
+ for (let ext of this.valueSet.jsonObj.compose.extension) {
278
+ if (ext.url === 'http://hl7.org/fhir/StructureDefinition/valueset-expansion-parameter' || ext.url === 'http://hl7.org/fhir/tools/StructureDefinition/valueset-expansion-parameter') {
279
+ let n = Extensions.readString(ext, 'name');
280
+ let v = Extensions.readValue(ext, 'value');
281
+ this.params.seeParameter(n, v, false);
282
+ }
283
+ }
284
+ }
285
+ if (!this.params.HTTPLanguages && this.valueSet.jsonObj.language) {
286
+ this.params.HTTPLanguages = Languages.fromAcceptLanguage(this.valueSet.jsonObj.language, this.worker.languages, false);
287
+ }
288
+ }
289
+
290
+ async prepare() {
291
+ if (this.valueSet === null) {
292
+ throw new Issue('error', 'not-found', null, null, 'Error Error: vs = nil');
293
+ } else {
294
+ this.seeValueSet();
295
+ this.worker.opContext.addNote(this.valueSet, 'Analysing ' + this.valueSet.vurl + ' for validation purposes', this.indentCount);
296
+ if (this.indentCount === 0) {
297
+ this.worker.opContext.addNote(this.valueSet, 'Parameters: ' + this.params.summary, this.indentCount);
298
+ let vrs = this.params.verSummary;
299
+ if (vrs) {
300
+ this.worker.opContext.addNote(this.valueSet, 'Version Rules: ' + vrs, this.indentCount);
301
+ }
302
+ }
303
+ this.requiredSupplements = [];
304
+ for (let ext of Extensions.list(this.valueSet.jsonObj, 'http://hl7.org/fhir/StructureDefinition/valueset-supplement')) {
305
+ this.requiredSupplements.push(getValuePrimitive(ext));
306
+ }
307
+ if (this.requiredSupplements.length > 0) {
308
+ await this.checkSupplementsExist(this.valueSet);
309
+ }
310
+
311
+ Extensions.checkNoImplicitRules(this.valueSet, 'ValueSetChecker.prepare', 'ValueSet');
312
+ Extensions.checkNoModifiers(this.valueSet, 'ValueSetChecker.prepare', 'ValueSet');
313
+
314
+ this.allValueSet = this.valueSet.url === 'http://hl7.org/fhir/ValueSet/@all';
315
+
316
+ if (this.valueSet.jsonObj.compose) {
317
+ Extensions.checkNoModifiers(this.valueSet.jsonObj.compose, 'ValueSetChecker.prepare', 'ValueSet.compose');
318
+ let i = 0;
319
+ for (let cc of this.valueSet.jsonObj.compose.include || []) {
320
+ await this.prepareConceptSet('include['+i+']', cc);
321
+ i++;
322
+ }
323
+ i = 0;
324
+ for (let cc of this.valueSet.jsonObj.compose.exclude || []) {
325
+ await this.prepareConceptSet('exclude['+i+']', cc);
326
+ i++;
327
+ }
328
+ }
329
+ }
330
+ if (this.requiredSupplements.length > 0) {
331
+ throw new Issue('error', 'not-found', null, 'VALUESET_SUPPLEMENT_MISSING', this.worker.i18n.translatePlural(this.requiredSupplements.length, 'VALUESET_SUPPLEMENT_MISSING', this.params.HTTPLanguages, [this.requiredSupplements.join(',')])).handleAsOO(400);
332
+ }
333
+ }
334
+
335
+ async prepareConceptSet(desc, cc) {
336
+ this.worker.deadCheck('prepareConceptSet');
337
+ Extensions.checkNoModifiers(cc, 'ValueSetChecker.prepare', desc);
338
+ this.worker.opContext.addNote(this.valueSet, 'Prepare ' + desc + ': "' + this.worker.renderer.displayValueSetInclude(cc) + '"', this.indentCount);
339
+ if (cc.valueSet) {
340
+ for (let u of cc.valueSet) {
341
+ let s = this.worker.pinValueSet(u);
342
+ this.worker.deadCheck('prepareConceptSet');
343
+ if (!this.others.has(s)) {
344
+ let other = await this.worker.findValueSet(s, '');
345
+ if (other === null) {
346
+ throw new Issue('error', 'not-found', null, 'Unable_to_resolve_value_Set_', this.worker.i18n.translate('Unable_to_resolve_value_Set_', this.params.HTTPLanguages, [s]), 'not-found');
347
+ }
348
+ let checker = new ValueSetChecker(this.worker, other, this.params);
349
+ checker.indentCount = this.indentCount + 1;
350
+ await checker.prepare(other, this.params, null);
351
+ this.others.set(s, checker);
352
+ }
353
+ }
354
+ }
355
+ let v = this.worker.determineVersionBase(cc.system, cc.version, this.params);
356
+ let cs = await this.worker.findCodeSystem(cc.system, v, this.params, ['complete', 'fragment'], null, true, false, false);
357
+ if (cs !== null) {
358
+ this.worker.opContext.addNote(this.valueSet, 'CodeSystem found: "' + this.worker.renderer.displayCoded(cs) + '"', this.indentCount);
359
+ for (let i = this.requiredSupplements.length - 1; i >= 0; i--) {
360
+ if (cs.hasSupplement(this.requiredSupplements[i])) {
361
+ this.requiredSupplements.splice(i, 1);
362
+ }
363
+ }
364
+ let i = 0;
365
+ for (let ccf of cc.filter || []) {
366
+ this.worker.deadCheck('prepareConceptSet#2');
367
+ Extensions.checkNoModifiers(ccf, 'ValueSetChecker.prepare', desc + '.filter');
368
+ if (!ccf.value) {
369
+ throw new Issue('error', 'invalid', "ValueSet.compose."+desc+".filter["+i+"]", 'UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE',
370
+ this.worker.i18n.translate('UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE', this.params.HTTPLanguages, [cs.system(), ccf.property, ccf.op]), "vs-invalid").handleAsOO(400);
371
+ }
372
+ if (!(ccf.property === 'concept' && ['is-a', 'descendent-of'].includes(ccf.op))) {
373
+ if (!(await cs.doesFilter(ccf.property, ccf.op, ccf.value))) {
374
+ throw new Issue('error', 'not-supported', "ValueSet.compose."+desc+".filter["+i+"]", 'FILTER_NOT_UNDERSTOOD', this.worker.i18n.translate('FILTER_NOT_UNDERSTOOD',
375
+ this.params.HTTPLanguages, [ccf.property, ccf.op, ccf.value, this.valueSet.url, cs.system]), "vs-invalid").handleAsOO(400);
376
+ }
377
+ }
378
+ i++;
379
+ }
380
+ } else if (cc.system) {
381
+ this.worker.opContext.addNote(this.valueSet, 'CodeSystem version ' + v + ' not found: "' + this.worker.renderer.displayCoded(cc.system, cc.version) + '"', this.indentCount);
382
+ }
383
+ }
384
+
385
+ async findCode(cs, code, list, displays, isabstract) {
386
+ let result = false;
387
+ for (let i = 0; i < list.length; i++) {
388
+ this.worker.deadCheck('findCode');
389
+ if (code === list[i].code) {
390
+ result = true;
391
+ if (cs === null) {
392
+ isabstract.value = false;
393
+ } else {
394
+ isabstract.value = await cs.isAbstract(list[i]);
395
+ }
396
+ displays.baseLang = this.FLanguages.parse(cs.language);
397
+ !displays.addDesignation(true, "active", '', '', list[i].displayElement);
398
+ throw new Error("Check this");
399
+ // return result;
400
+ }
401
+ let ccl = list[i].conceptList;
402
+ if (await this.findCode(cs, code, ccl, displays, isabstract)) {
403
+ result = true;
404
+ return result;
405
+ }
406
+ }
407
+ return result;
408
+ }
409
+
410
+ getName() {
411
+ if (this.valueSet !== null) {
412
+ return this.valueSet.name;
413
+ } else {
414
+ return '??';
415
+ }
416
+ }
417
+
418
+ async checkSimple(issuePath, system, version, code, abstractOk, inferSystem, op) {
419
+ this.worker.opContext.clearContexts();
420
+ if (inferSystem) {
421
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + code + '" and infer system', this.indentCount);
422
+ } else {
423
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(system, version, code) + '"', this.indentCount);
424
+ }
425
+ let unknownSystems = new Set();
426
+ let ts = [];
427
+ let msgs = [];
428
+ let ver = {value: ''};
429
+ let inactive = {value: false};
430
+ let normalForm = {value: ''};
431
+ let vstatus = {value: ''};
432
+ let it = {value: null};
433
+ let contentMode = {value: null};
434
+ let impliedSystem = {value: ''};
435
+ let defLang = {value: null};
436
+ return await this.check(issuePath, system, version, code, abstractOk, inferSystem, null, unknownSystems, ver, inactive, normalForm, vstatus, it, op, null, null, contentMode, impliedSystem, ts, msgs, defLang);
437
+ }
438
+
439
+ async check(path, system, version, code, abstractOk, inferSystem, displays, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, vcc, params, contentMode, impliedSystem, unkCodes, messages, defLang) {
440
+ defLang.value = new Language('en');
441
+ this.worker.opContext.addNote(this.valueSet, 'Check "' + this.worker.renderer.displayCoded(system, version, code) + '"', this.indentCount);
442
+ if (!system && !inferSystem) {
443
+ let msg = this.worker.i18n.translate('Coding_has_no_system__cannot_validate', this.params.HTTPLanguages, []);
444
+ messages.push(msg);
445
+ op.addIssue(new Issue('warning', 'invalid', path, 'Coding_has_no_system__cannot_validate', msg, 'invalid-data'));
446
+ return false;
447
+ }
448
+
449
+ let result;
450
+ let s = this.valueSet.url;
451
+ if (s === 'http://hl7.org/fhir/ValueSet/@all') {
452
+ if (system) {
453
+ let msg = this.worker.i18n.translate('Coding_has_no_system__cannot_validate_NO_INFER', this.params.HTTPLanguages, []);
454
+ messages.push(msg);
455
+ op.addIssue(new Issue('warning', 'invalid', path, 'Coding_has_no_system__cannot_validate_NO_INFER', msg, 'invalid-data'));
456
+ return false;
457
+ }
458
+ let cs = await this.worker.findCodeSystem(system, version, this.params, ['complete', 'fragment'], op,true);
459
+ this.seeSourceProvider(cs, system);
460
+ if (cs === null) {
461
+ this.worker.opContext.addNote(this.valueSet, 'Didn\'t find CodeSystem "' + this.worker.renderer.displayCoded(system, version) + '"', this.indentCount);
462
+ result = null;
463
+ cause.value = 'not-found';
464
+ let vss = await this.worker.findValueSet(system, '');
465
+ if (vss !== null) {
466
+ vss = null;
467
+ let msg = this.worker.i18n.translate('Terminology_TX_System_ValueSet2', this.params.HTTPLanguages, [system]);
468
+ messages.push(msg);
469
+ op.addIssue(new Issue('error', 'invalid', addToPath(path, 'system'), 'Terminology_TX_System_ValueSet2', msg, 'invalid-data'));
470
+ unknownSystems.add(system);
471
+ } else {
472
+ let css = await this.worker.findCodeSystem(system, version, this.params, ['supplement'], op,true);
473
+ if (css !== null) {
474
+ vss = null;
475
+ let msg = this.worker.i18n.translate('CODESYSTEM_CS_NO_SUPPLEMENT', this.params.HTTPLanguages, [this.canonical(css.system(), css.version())]);
476
+ messages.push(msg);
477
+ op.addIssue(new Issue('error', 'invalid', addToPath(path, 'system'), 'CODESYSTEM_CS_NO_SUPPLEMENT', msg, 'invalid-data'));
478
+ unknownSystems.add(system);
479
+ } else if (version) {
480
+ let vl = await this.worker.listVersions(system);
481
+ let mid, vn;
482
+ if (vl.length == 0) {
483
+ mid = 'UNKNOWN_CODESYSTEM_VERSION_NONE';
484
+ vn = system;
485
+ } else {
486
+ mid = 'UNKNOWN_CODESYSTEM_VERSION';
487
+ vn = system + '|' + version;
488
+ }
489
+ let msg = this.worker.i18n.translate(mid, this.params.HTTPLanguages, [system, version, this.worker.presentVersionList(vl)]);
490
+ messages.push(msg);
491
+ if (!unknownSystems.has(vn)) {
492
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), mid, msg, 'not-found'));
493
+ unknownSystems.add(vn);
494
+ }
495
+ } else {
496
+ let msg = this.worker.i18n.translate('UNKNOWN_CODESYSTEM', this.params.HTTPLanguages, [system]);
497
+ messages.push(msg);
498
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), 'UNKNOWN_CODESYSTEM', msg, 'not-found'));
499
+ unknownSystems.add(system);
500
+ }
501
+ }
502
+ } else {
503
+ defLang.value = cs.defLang();
504
+ this.worker.opContext.addNote(this.valueSet, 'Using CodeSystem "' + this.worker.renderer.displayCoded(cs) + '" (content = ' + cs.contentMode() + ')', this.indentCount);
505
+ await this.checkCanonicalStatus(path, op, cs, this.valueSet);
506
+ ver.value = cs.version();
507
+ contentMode.value = cs.contentMode();
508
+ let ctxt = await cs.locate(code);
509
+ if (ctxt.context === null) {
510
+ unkCodes.push(cs.system() + '|' + cs.version + '#' + code);
511
+ if (cs.contentMode() !== 'complete') {
512
+ result = true;
513
+ cause.value = 'code-invalid';
514
+ this.worker.opContext.addNote(this.valueSet, 'Not found in Incomplete Code System', this.indentCount);
515
+ let msg = this.worker.i18n.translate('UNKNOWN_CODE_IN_FRAGMENT', this.params.HTTPLanguages, [code, cs.system(), cs.version()]);
516
+ // messages.push(msg); disabled 15-1-2026 GG - it's not considered invalid if it's just a warning
517
+ op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'UNKNOWN_CODE_IN_FRAGMENT', msg, 'invalid-code'));
518
+ } else {
519
+ result = false;
520
+ cause.value = 'code-invalid';
521
+ this.worker.opContext.addNote(this.valueSet, 'Unknown code', this.indentCount);
522
+ let msg = this.worker.i18n.translate(Unknown_Code_in_VersionSCT(cs.system), this.params.HTTPLanguages, [code, cs.system(), cs.version(), SCTVersion(cs.system(), cs.version())]);
523
+ messages.push(msg);
524
+ op.addIssue(new Issue('error', 'code-invalid', addToPath(path, 'code'), 'Unknown_Code_in_Version', msg, 'invalid-code'));
525
+ }
526
+ } else {
527
+ if (vcc !== null) {
528
+ vcc.addCoding(cs.system(), cs.version(), await cs.code(ctxt), cs.display(ctxt, this.params.workingLanguages()));
529
+ }
530
+ cause.value = 'null';
531
+ if (!(abstractOk || !(await cs.IsAbstract(ctxt)))) {
532
+ result = false;
533
+ this.worker.opContext.addNote(this.valueSet, 'Abstract code when not allowed', this.indentCount);
534
+ cause.value = 'business-rule';
535
+ let msg = this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [system, code]);
536
+ messages.push(msg);
537
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', msg, 'code-rule'));
538
+ } else if (this.params !== null && this.params.activeOnly && await cs.isInactive(ctxt)) {
539
+ result = false;
540
+ this.worker.opContext.addNote(this.valueSet, 'Inactive code when not allowed', this.indentCount);
541
+ cause.value = 'business-rule';
542
+ let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
543
+ messages.push(msg);
544
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
545
+ } else {
546
+ this.worker.opContext.addNote(this.valueSet, 'found OK', this.indentCount);
547
+ result = true;
548
+ if ((await cs.code(ctxt.context)) !== code) {
549
+ let msg = this.worker.i18n.translate('CODE_CASE_DIFFERENCE', this.params.HTTPLanguages, [code, await cs.code(ctxt), cs.system]);
550
+ messages.push(msg);
551
+ op.addIssue(new Issue('warning', 'business-rule', addToPath(path, 'code'), 'CODE_CASE_DIFFERENCE', msg, 'code-rule'));
552
+ }
553
+ let msg = await cs.incompleteValidationMessage(ctxt.context, this.params.HTTPLanguages);
554
+ if (msg) {
555
+ op.addIssueNoId('information', 'informational', addToPath(path, 'code'), msg, 'process-note');
556
+ }
557
+ inactive.value = await cs.isInactive(ctxt.context);
558
+ inactive.path = path;
559
+ vstatus.value = await cs.getStatus(ctxt.context);
560
+ }
561
+ if (displays !== null) {
562
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, ctxt.context);
563
+ }
564
+ }
565
+ }
566
+ } else if (DEV_IGNORE_VALUESET) {
567
+ // anyhow, we ignore the value set (at least for now)
568
+ let cs = await this.worker.findCodeSystem(system, version, this.params, ['complete', 'fragment'], op, true, true, false);
569
+ if (cs === null) {
570
+ result = null;
571
+ cause.value = 'not-found';
572
+ this.worker.opContext.addNote(this.valueSet, 'Unknown code system', this.indentCount);
573
+ let vl, mid, vn;
574
+ if (version) {
575
+ vl = this.listVersions(system);
576
+ if (vl.length == 0) {
577
+ mid = 'UNKNOWN_CODESYSTEM_VERSION_NONE';
578
+ vn = system + '|' + version;
579
+ } else {
580
+ mid = 'UNKNOWN_CODESYSTEM_VERSION';
581
+ vn = system + '|' + version;
582
+ }
583
+ let msg = this.worker.i18n.translate(mid, this.params.HTTPLanguages, [system, version, this.worker.presentVersionList(vl)]);
584
+ messages.push(msg);
585
+ if (!unknownSystems.has(vn)) {
586
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), mid, msg, 'not-found'));
587
+ unknownSystems.add(vn);
588
+ }
589
+ } else {
590
+ let msg = this.worker.i18n.translate('UNKNOWN_CODESYSTEM', this.params.HTTPLanguages, [system]);
591
+ messages.push(msg);
592
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), 'UNKNOWN_CODESYSTEM', msg, 'not-found'));
593
+ unknownSystems.add(system);
594
+ }
595
+ } else {
596
+ defLang.value = cs.defLang();
597
+ this.checkCanonicalStatus(path, op, cs, this.valueSet);
598
+ ver.value = cs.version();
599
+ contentMode.value = cs.contentMode;
600
+ let ctxt = cs.locate(code);
601
+ if (ctxt.context === null) {
602
+ unkCodes.push(system + '|' + version + '#' + code);
603
+ if (cs.contentMode !== 'complete') {
604
+ result = true;
605
+ cause.value = 'code-invalid';
606
+ this.worker.opContext.addNote(this.valueSet, 'Not found in Incomplete Code System', this.indentCount);
607
+ let msg = this.worker.i18n.translate('UNKNOWN_CODE_IN_FRAGMENT', this.params.HTTPLanguages, [code, system, version]);
608
+ // messages.push(msg); it's just a warning
609
+ op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'UNKNOWN_CODE_IN_FRAGMENT', msg, 'invalid-code'));
610
+ } else {
611
+ result = false;
612
+ cause.value = 'code-invalid';
613
+ this.worker.opContext.addNote(this.valueSet, 'Unknown code', this.indentCount);
614
+ let msg = this.worker.i18n.translate(Unknown_Code_in_VersionSCT(system), this.params.HTTPLanguages, [code, system, version, SCTVersion(system, version)]);
615
+ messages.push(msg);
616
+ op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'Unknown_Code_in_Version', msg, 'invalid-code'));
617
+ }
618
+ } else {
619
+ ctxt = ctxt.context;
620
+ cause.value = 'null';
621
+ if (!(abstractOk || !cs.IsAbstract(ctxt))) {
622
+ result = false;
623
+ this.worker.opContext.addNote(this.valueSet, 'Abstract code when not allowed', this.indentCount);
624
+ cause.value = 'business-rule';
625
+ let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
626
+ messages.push(msg);
627
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
628
+ } else if (this.params !== null && this.params.activeOnly && await cs.isInactive(ctxt)) {
629
+ result = false;
630
+ this.worker.opContext.addNote(this.valueSet, 'Inactive code when not allowed', this.indentCount);
631
+ cause.value = 'business-rule';
632
+ let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
633
+ messages.push(msg);
634
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
635
+ } else {
636
+ this.worker.opContext.addNote(this.valueSet, 'found', this.indentCount);
637
+ result = true;
638
+ }
639
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, ctxt);
640
+ }
641
+ }
642
+ } else {
643
+ if (!system && inferSystem) {
644
+ let systems = new Set();
645
+ system = await this.determineSystem(this.worker.opContext, code, systems, op);
646
+ if (!system) {
647
+ let msg;
648
+ if (systems.size > 1) {
649
+ msg = this.worker.i18n.translate('Unable_to_resolve_system__value_set_has_multiple_matches', this.params.HTTPLanguages, [code, this.valueSet.vurl, Array.from(systems).join(',')]);
650
+ messages.push(msg);
651
+ op.addIssue(new Issue('error', 'not-found', 'code', 'Unable_to_resolve_system__value_set_has_multiple_matches', msg, 'cannot-infer'));
652
+ } else {
653
+ msg = this.worker.i18n.translate('UNABLE_TO_INFER_CODESYSTEM', this.params.HTTPLanguages, [code, this.valueSet.vurl]);
654
+ messages.push(msg);
655
+ op.addIssue(new Issue('error', 'not-found', 'code', 'UNABLE_TO_INFER_CODESYSTEM', msg, 'cannot-infer'));
656
+ }
657
+ return false;
658
+ } else {
659
+ impliedSystem.value = system;
660
+ this.worker.opContext.addNote(this.valueSet, 'Inferred CodeSystem = "' + system + '"', this.indentCount);
661
+ }
662
+ }
663
+
664
+ if (this.requiredSupplements.length > 0) {
665
+ throw new Issue('error', 'not-found', null, 'VALUESET_SUPPLEMENT_MISSING', this.worker.i18n.translatePlural(this.requiredSupplements.length, 'VALUESET_SUPPLEMENT_MISSING', this.params.HTTPLanguages, [this.requiredSupplements.join(',')])).handleAsOO(400);
666
+ }
667
+
668
+ if (Extensions.checkNoModifiers(this.valueSet.jsonObj.compose, 'ValueSetChecker.prepare', 'ValueSet.compose')) {
669
+ result = false;
670
+ for (let cc of this.valueSet.jsonObj.compose.include || []) {
671
+ this.worker.deadCheck('check#2');
672
+ if (!cc.system) {
673
+ result = true;
674
+ } else if (cc.system === system || system === '%%null%%') {
675
+ let v = await this.determineVersion(path, cc.system, cc.version, version, op, unknownSystems, messages);
676
+ let cs = await this.worker.findCodeSystem(system, v, this.params, ["complete", "fragment"], op,true, true, false);
677
+ if (cs === null) {
678
+ this.worker.opContext.addNote(this.valueSet, 'CodeSystem not found: ' + this.worker.renderer.displayCoded(cc.system, v), this.indentCount);
679
+ if (!this.params.membershipOnly) {
680
+ let bAdd = true;
681
+ let msg, mid, vn;
682
+ if (!v) {
683
+ msg = this.worker.i18n.translate('UNKNOWN_CODESYSTEM', this.params.HTTPLanguages, [system]);
684
+ unknownSystems.add(system);
685
+ mid = 'UNKNOWN_CODESYSTEM';
686
+ } else {
687
+ let vl = await this.worker.listVersions(system);
688
+ if (vl.length == 0) {
689
+ mid = 'UNKNOWN_CODESYSTEM_VERSION_NONE';
690
+ vn = system;
691
+ } else {
692
+ mid = 'UNKNOWN_CODESYSTEM_VERSION';
693
+ vn = system + '|' + v;
694
+ }
695
+ msg = this.worker.i18n.translate(mid, this.params.HTTPLanguages, [system, v, this.worker.presentVersionList(vl)]);
696
+ bAdd = !unknownSystems.has(vn);
697
+ if (bAdd) {
698
+ unknownSystems.add(vn);
699
+ }
700
+ }
701
+ messages.push(msg);
702
+ if (bAdd) {
703
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), mid, msg, 'not-found'));
704
+ }
705
+ return null;
706
+ } else {
707
+ return false;
708
+ }
709
+ }
710
+ defLang.value = new Language(cs.defLang());
711
+ this.worker.opContext.addNote(this.valueSet, 'CodeSystem found: ' + this.worker.renderer.displayCoded(cs) + ' for ' + this.worker.renderer.displayCoded(cc.system, v), this.indentCount);
712
+ await this.checkCanonicalStatusCS(path, op, cs, this.valueSet);
713
+ ver.value = cs.version();
714
+ this.worker.checkSupplements(cs, cc, this.requiredSupplements);
715
+ contentMode.value = cs.contentMode();
716
+
717
+ let msg = '';
718
+ if ((system === '%%null%%' || cs.system() === system) && await this.checkConceptSet(path, 'in', cs, cc, code, abstractOk, displays, this.valueSet, msg, inactive, normalForm, vstatus, op, vcc, messages)) {
719
+ result = true;
720
+ } else {
721
+ result = false;
722
+ }
723
+ if (msg) {
724
+ messages.push(msg);
725
+ }
726
+ } else {
727
+ result = false;
728
+ }
729
+ for (let u of cc.valueSet || []) {
730
+ this.worker.deadCheck('check#3');
731
+ let s = this.worker.pinValueSet(u);
732
+ this.worker.opContext.addNote(this.valueSet, 'Check included value set ' + s, this.indentCount);
733
+ let checker = this.others.get(s);
734
+ if (checker === null || checker === undefined) {
735
+ throw new Issue('error', 'unknown', null, null, 'No Match for ' + s + ' in ' + Array.from(this.others.keys()).join(','));
736
+ }
737
+ this.checkCanonicalStatus(path, op, checker.valueSet, this.valueSet);
738
+ if (result === true) {
739
+ result = await checker.check(path, system, version, code, abstractOk, inferSystem, displays, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, null, params, contentMode, impliedSystem, unkCodes, messages, defLang);
740
+ }
741
+ }
742
+ if (result === true) {
743
+ break;
744
+ }
745
+ }
746
+ if (result === true) {
747
+ for (let cc of this.valueSet.jsonObj.compose.exclude || []) {
748
+ this.worker.deadCheck('check#4');
749
+ let excluded;
750
+ if (cc.system) {
751
+ excluded = true;
752
+ } else {
753
+ let cs = await this.worker.findCodeSystem(cc.system, cc.version, this.params, ['complete', 'fragment'], op,true, true, false);
754
+ if (cs === null) {
755
+ throw new Issue('error', 'unknown', null, null, 'No Match for ' + cc.system + '|' + cc.version);
756
+ }
757
+ await this.checkCanonicalStatus(path, op, cs, this.valueSet);
758
+ this.worker.checkSupplements(cs, cc, this.requiredSupplements);
759
+ ver.value = cs.version();
760
+ contentMode.value = cs.contentMode();
761
+ let msg = '';
762
+ excluded = (system === '%%null%%' || cs.system() === system) && await this.checkConceptSet(path, 'not in', cs, cc, code, abstractOk, displays, this.valueSet, msg, inactive, normalForm, vstatus, op, vcc);
763
+ if (msg) {
764
+ messages.push(msg);
765
+ }
766
+ }
767
+ for (let u of cc.valueSets || []) {
768
+ this.worker.deadCheck('check#5');
769
+ let s = this.worker.pinValueSet(u);
770
+ let checker = this.others.get(s);
771
+ if (checker === null) {
772
+ throw new Issue('error', 'unknown', null, null, 'No Match for ' + cc.system + '|' + cc.version + ' in ' + Array.from(this.others.keys()).join(','));
773
+ }
774
+ this.checkCanonicalStatus(path, op, checker.valueSet, this.valueSet);
775
+ excluded = excluded && (await checker.check(path, system, version, code, abstractOk, inferSystem, displays, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, null, params, contentMode, impliedSystem, unkCodes, messages, defLang) === true);
776
+ }
777
+ if (excluded) {
778
+ return false;
779
+ }
780
+ }
781
+ }
782
+ } else if (Extensions.checkNoModifiers(this.valueSet.jsonObj.expansion, 'ValueSetChecker.prepare', 'ValueSet.expansion')) {
783
+ let ccc = this.valueSet.findContains(system, version, code);
784
+ if (ccc === null) {
785
+ result = false;
786
+ } else {
787
+ let v;
788
+ if (!ccc.version && !version) {
789
+ v = '';
790
+ } else if (!ccc.version) {
791
+ v = version;
792
+ } else if (!version || version === ccc.version) {
793
+ v = ccc.version;
794
+ } else if (cs !== null && cs.versionIsMoreDetailed(ccc.version, version)) {
795
+ v = version;
796
+ } else {
797
+ let msg = 'The code system "' + ccc.system + '" version "' + ccc.version + '" in the ValueSet expansion is different to the one in the value ("' + version + '")';
798
+ messages.push(msg);
799
+ op.addIssueNoId('error', 'not-found', addToPath(path, 'version'), msg, 'vs-invalid');
800
+ return false;
801
+ }
802
+ let cs = await this.worker.findCodeSystem(system, v, this.params, ['complete', 'fragment'], op, true, true, false);
803
+ if (cs === null) {
804
+ if (!this.params.membershipOnly) {
805
+ let bAdd = true;
806
+ let msg, mid, vn;
807
+ if (!v) {
808
+ mid = 'UNKNOWN_CODESYSTEM';
809
+ msg = this.worker.i18n.translate('UNKNOWN_CODESYSTEM', this.params.HTTPLanguages, [system]);
810
+ unknownSystems.add(system);
811
+ } else {
812
+ bAdd = !unknownSystems.has(system + '|' + version);
813
+ if (bAdd) {
814
+ let vl = await this.listVersions(system);
815
+ if (vl.length == 0) {
816
+ mid = 'UNKNOWN_CODESYSTEM_VERSION_NONE';
817
+ vn = system;
818
+ } else {
819
+ mid = 'UNKNOWN_CODESYSTEM_VERSION';
820
+ vn = system + '|' + v;
821
+ }
822
+ msg = this.worker.i18n.translate(mid, this.params.HTTPLanguages, [system, v, this.worker.presentVersionList(vl)]);
823
+ unknownSystems.add(vn);
824
+ }
825
+ }
826
+ messages.push(msg);
827
+ if (bAdd) {
828
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), mid, msg, 'not-found'));
829
+ }
830
+ return null;
831
+ } else {
832
+ return false;
833
+ }
834
+ }
835
+ defLang.value = cs.defLang();
836
+ await this.checkCanonicalStatus(path, op, cs, this.valueSet);
837
+ ver.value = cs.version();
838
+ contentMode.value = cs.contentMode();
839
+ let msg = '';
840
+ if ((system === '%%null%%' || cs.system() === system) && await this.checkExpansion(path, cs, ccc, code, abstractOk, displays, this.valueSet, msg, inactive, vstatus, op)) {
841
+ result = true;
842
+ } else {
843
+ result = false;
844
+ }
845
+ if (msg) {
846
+ messages.push(msg);
847
+ }
848
+ }
849
+ } else {
850
+ result = false;
851
+ }
852
+ }
853
+
854
+ return result;
855
+ }
856
+
857
+ async checkCoding(issuePath, coding, abstractOk, inferSystem) {
858
+ let inactive = false;
859
+ let path = issuePath;
860
+ let unknownSystems = new Set();
861
+ let unkCodes = [];
862
+ let messages = [];
863
+ let result = new Parameters();
864
+
865
+ this.worker.opContext.clearContexts();
866
+ if (inferSystem) {
867
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(coding) + '" and infer system', this.indentCount);
868
+ } else {
869
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(coding) + '"', this.indentCount);
870
+ }
871
+
872
+ let op = new OperationOutcome();
873
+ this.checkCanonicalStatus(path, op, this.valueSet, this.valueSet);
874
+ let list = new Designations(this.worker.languages);
875
+ let ver = {value: ''};
876
+ inactive = {value: false};
877
+ let normalForm = {value: ''};
878
+ let vstatus = {value: ''};
879
+ let cause = {value: null};
880
+ let contentMode = {value: null};
881
+ let impliedSystem = {value: ''};
882
+ let defLang = {value: null};
883
+
884
+ let ok = await this.check(path, coding.system, coding.version, coding.code, abstractOk, inferSystem, list, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, null, result, contentMode, impliedSystem, unkCodes, messages, defLang);
885
+ if (ok === true) {
886
+ result.AddParamBool('result', true);
887
+ if ((cause.value === 'not-found' && contentMode.value !== 'complete') || contentMode.value === 'example') {
888
+ result.addParamStr('message', 'The system "' + coding.system + ' was found but did not contain enough information to properly validate the code (mode = ' + contentMode.value + ')');
889
+ }
890
+ if (coding.display && !list.hasDisplay(this.params.workingLanguages(), defLang.value, coding.display, false, DisplayCheckingStyle.CASE_INSENSITIVE).found) {
891
+ let baseMsg = 'Display_Name_for__should_be_one_of__instead_of';
892
+ let dc = list.displayCount(this.params.workingLanguages(), null, true);
893
+ if (dc > 0) {
894
+ if (list.hasDisplay(this.params.workingLanguages(), defLang.value, coding.display, false, DisplayCheckingStyle.CASE_INSENSITIVE).difference === DisplayDifference.Normalised) {
895
+ baseMsg = 'Display_Name_WS_for__should_be_one_of__instead_of';
896
+ }
897
+ if (dc === 1) {
898
+ result.addParamStr('message', this.worker.i18n.translate(baseMsg + '_one', this.params.HTTPLanguages,
899
+ ['', coding.system, coding.code, list.present(this.params.workingLanguages(), defLang.value, true), coding.display, this.params.langSummary()]));
900
+ } else {
901
+ result.addParamStr('message', this.worker.i18n.translate(baseMsg + '_other', this.params.HTTPLanguages, [dc.toString(), coding.system, coding.code, list.present(this.params.workingLanguages(), defLang.value, true), coding.display, this.params.langSummary()]));
902
+ }
903
+ }
904
+ }
905
+ let pd = list.preferredDisplay(this.params.workingLanguages());
906
+ if (pd) {
907
+ result.addParamStr('display', pd);
908
+ }
909
+ result.addParamUri('system', coding.system);
910
+ if (ver.value) {
911
+ result.addParamStr('version', ver.value);
912
+ }
913
+ if (cause.value !== 'null') {
914
+ result.AddParamCode('cause', cause.value);
915
+ }
916
+ if (inactive.value) {
917
+ result.AddParamBool('inactive', inactive.value);
918
+ if (vstatus.value && vstatus.value !== 'inactive') {
919
+ result.addParamStr('status', vstatus.value);
920
+ }
921
+ let msg = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, coding.code]);
922
+ messages.push(msg);
923
+ op.addIssue(new Issue('warning', 'business-rule', path, 'INACTIVE_CONCEPT_FOUND', msg, 'code-comment'));
924
+ } else if (vstatus.value.toLowerCase() === 'deprecated') {
925
+ result.addParamStr('status', vstatus.value);
926
+ let msg = this.worker.i18n.translate('DEPRECATED_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, coding.code]);
927
+ messages.push(msg);
928
+ op.addIssue(new Issue('warning', 'business-rule', path, 'DEPRECATED_CONCEPT_FOUND', msg, 'code-comment'));
929
+ }
930
+ } else if (ok === null) {
931
+ result.AddParamBool('result', false);
932
+ result.addParamStr('message', 'The CodeSystem "' + coding.system + '" is unknown, so the code "' + coding.code + '" is not known to be in the ' + this.valueSet.name);
933
+ for (let us of unknownSystems) {
934
+ result.addParamCanonical('x-caused-by-unknown-system', us);
935
+ }
936
+ } else {
937
+ result.AddParamBool('result', false);
938
+ if (ver.value) {
939
+ result.addParamStr('version', ver.value);
940
+ }
941
+ result.addParamStr('message', 'The system/code "' + coding.system + '"/"' + coding.code + '" is not in the value set ' + this.valueSet.name);
942
+ if (cause.value !== 'null') {
943
+ result.AddParamCode('cause', cause.value);
944
+ }
945
+ }
946
+ if (op.hasIssues) {
947
+ result.addParam('issues').resource = op.jsonObj;
948
+ }
949
+ return result;
950
+ }
951
+
952
+ valueSetDependsOnCodeSystem(url, version) {
953
+ for (let inc of this.valueSet.include) {
954
+ this.worker.deadCheck('valueSetDependsOnCodeSystem');
955
+ if (inc.system === url && (!version || version === inc.version || !inc.version)) {
956
+ return true;
957
+ }
958
+ }
959
+ return false;
960
+ }
961
+
962
+ async checkSupplementsExist(vs) {
963
+ for (let inc of vs.jsonObj.compose.include) {
964
+ if (inc.system) {
965
+ let cs = await this.worker.findCodeSystem(inc.system, inc.version, this.params, ['complete', 'fragment'], null,true);
966
+ if (cs !== null) {
967
+ await this.worker.checkSupplements(cs, null, this.requiredSupplements);
968
+ }
969
+ }
970
+ }
971
+ }
972
+
973
+ async checkCodeableConcept(issuePath, code, abstractOk, inferSystem, mode) {
974
+ this.worker.opContext.clearContexts();
975
+ if (inferSystem) {
976
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(code) + '" and infer system', this.indentCount);
977
+ } else {
978
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(code) + '"', this.indentCount);
979
+ }
980
+
981
+ let inactive = { value: false };
982
+ let cause = { value: "null" };
983
+ if (this.valueSet === null) {
984
+ throw new Issue('error', 'invalid', null, null, 'Error: cannot validate a CodeableConcept without a nominated valueset');
985
+ }
986
+ let pdisp;
987
+ let psys;
988
+ let pcode;
989
+ let pver;
990
+
991
+
992
+ let vstatus = {value: ''};
993
+ let normalForm = {value: ''};
994
+ let mt = [];
995
+ let ts = [];
996
+ let tsys = '';
997
+ let tcode = '';
998
+ let tver = '';
999
+ let vcc = {};
1000
+ if (code.text) {
1001
+ vcc.text = code.text;
1002
+ }
1003
+ let unknownSystems = new Set();
1004
+ let result = new Parameters();
1005
+
1006
+ const msg = (s, clear = false) => {
1007
+ if (!s) {
1008
+ return;
1009
+ }
1010
+ if (clear) {
1011
+ mt = [];
1012
+ }
1013
+ if (!mt.includes(s)) {
1014
+ mt.push(s);
1015
+ }
1016
+ };
1017
+
1018
+ let op = new OperationOutcome();
1019
+ this.checkCanonicalStatus(issuePath, op, this.valueSet.jsonObj, this.valueSet.jsonObj);
1020
+ let list = new Designations(this.worker.languages);
1021
+ let ok = false;
1022
+ let codelist = '';
1023
+ mt = [];
1024
+ let i = 0;
1025
+ let impliedSystem = { value: '' };
1026
+ for (let c of code.coding) {
1027
+ const csd = await this.worker.findCodeSystem(c.system, null, this.params, ['complete', 'fragment'], false, true);
1028
+ this.worker.seeSourceProvider(csd, c.system);
1029
+
1030
+ this.worker.deadCheck('check-b#1');
1031
+ let path;
1032
+ if (issuePath === 'CodeableConcept') {
1033
+ path = addToPath(issuePath, 'coding[' + i + ']');
1034
+ } else {
1035
+ path = issuePath;
1036
+ }
1037
+ list.clear();
1038
+ let ver = { value: '' };
1039
+ let contentMode = { value: null };
1040
+ let defLang = { value: null };
1041
+ let v = await this.check(path, c.system, c.version, c.code, abstractOk, inferSystem, list, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, vcc, result, contentMode, impliedSystem, ts, mt, defLang);
1042
+ if (v === false) {
1043
+ cause.value = 'code-invalid';
1044
+ }
1045
+ let ws;
1046
+ if (impliedSystem.value) {
1047
+ ws = impliedSystem.value;
1048
+ } else {
1049
+ ws = c.system;
1050
+ }
1051
+ if (!tcode || v == true) {
1052
+ tsys = c.system;
1053
+ tcode = c.code;
1054
+ tver = c.version;
1055
+ }
1056
+ let cc;
1057
+ if (!ws) {
1058
+ ws = "";
1059
+ }
1060
+ if (!c.version) {
1061
+ cc = ws + '#' + c.code;
1062
+ } else {
1063
+ cc = ws + '|' + c.version + '#' + c.code;
1064
+ }
1065
+ if (c.display) {
1066
+ cc = cc + ' (\'' + c.display + '\')';
1067
+ }
1068
+ codelist = !codelist ? '\'' + cc + '\'' : codelist + ', \'' + cc + '\'';
1069
+
1070
+ if (v === false && !this.valueSet.jsonObj.internallyDefined && mode === 'codeableConcept') {
1071
+ let m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.vurl, '\'' + cc + '\'']);
1072
+ let p = issuePath + '.coding[' + i + '].code';
1073
+ op.addIssue(new Issue('information', 'code-invalid', p, 'None_of_the_provided_codes_are_in_the_value_set_one', m, 'this-code-not-in-vs'));
1074
+ if (cause.value === 'null') {
1075
+ cause.value = 'unknown';
1076
+ }
1077
+ }
1078
+
1079
+ if (ok !== true && v !== false) {
1080
+ ok = v;
1081
+ }
1082
+ if (v === true) {
1083
+ if ((cause.value === 'not-found' && contentMode.value !== 'complete') || contentMode.value === 'example') {
1084
+ let m = 'The system ' + c.system + ' was found but did not contain enough information to properly validate the code "' + c.code + '" ("' + c.display + '") (mode = ' + contentMode.value + ')';
1085
+ msg(m);
1086
+ op.addIssueNoId('warning', 'not-found', path, m, 'vs-invalid');
1087
+ } else if (c.display && list.designations.length > 0) {
1088
+ await this.checkDisplays(list, defLang, c, msg, op, path);
1089
+ }
1090
+ psys = c.system;
1091
+ pcode = c.code;
1092
+ if (ver.value) {
1093
+ pver = ver.value;
1094
+ }
1095
+ let pd = list.preferredDisplay(this.params.workingLanguages());
1096
+ if (pd) {
1097
+ pdisp = pd;
1098
+ }
1099
+ if (!pdisp) {
1100
+ pdisp = list.preferredDisplay(null);
1101
+ }
1102
+ } else if (!this.params.membershipOnly && ws) {
1103
+ if (!isAbsoluteUrl(ws)) {
1104
+ let m = this.worker.i18n.translate('Terminology_TX_System_Relative', this.params.HTTPLanguages, []);
1105
+ let p;
1106
+ if (mode === 'coding') {
1107
+ p = issuePath + '.system';
1108
+ } else if (mode === 'codeableConcept') {
1109
+ p = issuePath + '.coding[' + i + '].system';
1110
+ } else {
1111
+ p = issuePath;
1112
+ }
1113
+ mt.push(m);
1114
+ op.addIssue(new Issue('error', 'invalid', p, 'Terminology_TX_System_Relative', m, 'invalid-data'));
1115
+ }
1116
+ let prov = await this.worker.findCodeSystem(ws, c.version, this.params, ['complete', 'fragment'], op,true, true, false);
1117
+ if (prov === null) {
1118
+ let vss = await this.worker.findValueSet(ws, '');
1119
+ if (vss !== null) {
1120
+ vss = null;
1121
+ let m = this.worker.i18n.translate('Terminology_TX_System_ValueSet2', this.params.HTTPLanguages, [ws]);
1122
+ msg(m);
1123
+ op.addIssue(new Issue('error', 'invalid', addToPath(path, 'system'), 'Terminology_TX_System_ValueSet2', m, 'invalid-data'));
1124
+ cause.value = 'invalid';
1125
+ } else {
1126
+ let provS = await this.worker.findCodeSystem(ws, c.version, this.params, ['supplement'], op,true, true, false);
1127
+ if (provS !== null) {
1128
+ vss = null;
1129
+ let m = this.worker.i18n.translate('CODESYSTEM_CS_NO_SUPPLEMENT', this.params.HTTPLanguages, [provS.vurl()]);
1130
+ msg(m);
1131
+ op.addIssue(new Issue('error', 'invalid', addToPath(path, 'system'), 'CODESYSTEM_CS_NO_SUPPLEMENT', m, 'invalid-data'));
1132
+ cause.value = 'invalid';
1133
+ } else {
1134
+ let prov2 = await this.worker.findCodeSystem(ws, '', this.params, ['complete', 'fragment'], op,true, true, false);
1135
+ let bAdd = true;
1136
+ let m, mid, vn;
1137
+ if (prov2 === null && !c.version) {
1138
+ mid = 'UNKNOWN_CODESYSTEM';
1139
+ m = this.worker.i18n.translate('UNKNOWN_CODESYSTEM', this.params.HTTPLanguages, [ws]);
1140
+ bAdd = !unknownSystems.has(ws);
1141
+ if (bAdd) {
1142
+ unknownSystems.add(ws);
1143
+ }
1144
+ } else {
1145
+ let vl = await this.worker.listVersions(c.system);
1146
+ if (vl.length == 0) {
1147
+ mid = 'UNKNOWN_CODESYSTEM_VERSION_NONE';
1148
+ vn = ws;
1149
+ } else {
1150
+ mid = 'UNKNOWN_CODESYSTEM_VERSION';
1151
+ vn = ws + '|' + c.version;
1152
+ }
1153
+ m = this.worker.i18n.translate(mid, this.params.HTTPLanguages, [ws, c.version, this.worker.presentVersionList(vl)]);
1154
+ bAdd = !unknownSystems.has(vn);
1155
+ if (bAdd) {
1156
+ unknownSystems.add(vn);
1157
+ }
1158
+ }
1159
+ if (bAdd) {
1160
+ op.addIssue(new Issue('error', 'not-found', addToPath(path, 'system'), mid, m, 'not-found'));
1161
+ }
1162
+ msg(m);
1163
+ cause.value = 'not-found';
1164
+ }
1165
+ }
1166
+ } else {
1167
+ this.checkCanonicalStatusCS(path, op, prov, this.valueSet);
1168
+ let ctxt = await prov.locate(c.code);
1169
+ if (!ctxt.context) {
1170
+ // message can never be populated in pascal?
1171
+ // if (ctxt.message) {
1172
+ // let p;
1173
+ // if (mode !== 'code') {
1174
+ // p = path + '.code';
1175
+ // }
1176
+ // op.addIssue(new Issue('information', cause.value, p, null, ctxt.message, 'invalid-code'));
1177
+ // message = '';
1178
+ // }
1179
+ if (vcc.coding) {
1180
+ vcc.coding = vcc.coding.filter(ccc => ccc.system === prov.system() && (!prov.version() || ccc.version == prov.version()) && ccc.code === c.code);
1181
+ }
1182
+ let vs = ws + '|' + prov.version() + '#' + c.code;
1183
+ if (!ts.includes(vs)) {
1184
+ ts.push(vs);
1185
+ let m;
1186
+ if (prov.contentMode() === 'complete') {
1187
+ m = this.worker.i18n.translate(Unknown_Code_in_VersionSCT(ws), this.params.HTTPLanguages, [c.code, ws, prov.version(), SCTVersion(ws, prov.version())]);
1188
+ cause.value = 'code-invalid';
1189
+ msg(m);
1190
+ op.addIssue(new Issue('error', 'code-invalid', addToPath(path, 'code'), 'Unknown_Code_in_Version', m, 'invalid-code'), true);
1191
+ } else {
1192
+ m = this.worker.i18n.translate('UNKNOWN_CODE_IN_FRAGMENT', this.params.HTTPLanguages, [c.code, ws, prov.version()]);
1193
+ cause.value = 'code-invalid';
1194
+ // msg(m); - it's just a warning
1195
+ op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'UNKNOWN_CODE_IN_FRAGMENT', m, 'invalid-code'), true);
1196
+ }
1197
+ }
1198
+ } else {
1199
+ await this.worker.listDisplaysFromCodeSystem(list, prov, ctxt.context);
1200
+ let pd = list.preferredDisplay(this.params.workingLanguages());
1201
+ if (pd) {
1202
+ pdisp = pd;
1203
+ }
1204
+ if (!pdisp) {
1205
+ pdisp = list.preferredDisplay(null);
1206
+ }
1207
+ let severity = this.dispWarning();
1208
+ if (c.display && list.designations.length > 0 && !list.hasDisplay(this.params.workingLanguages(), defLang.value, c.display, false, DisplayCheckingStyle.CASE_INSENSITIVE).found) {
1209
+ let baseMsg;
1210
+ if (list.hasDisplay(this.params.workingLanguages(), defLang.value, c.display, false, DisplayCheckingStyle.CASE_INSENSITIVE).difference === DisplayDifference.Normalized) {
1211
+ baseMsg = 'Display_Name_WS_for__should_be_one_of__instead_of';
1212
+ } else {
1213
+ baseMsg = 'Display_Name_for__should_be_one_of__instead_of';
1214
+ }
1215
+
1216
+ let dc = list.displayCount(this.params.workingLanguages(), null, true);
1217
+ let m;
1218
+ if (dc === 0) {
1219
+ severity = 'warning';
1220
+ baseMsg = 'NO_VALID_DISPLAY_AT_ALL';
1221
+ m = this.worker.i18n.translate('NO_VALID_DISPLAY_AT_ALL', this.params.HTTPLanguages,
1222
+ [c.display, prov.system(), c.code, this.params.langSummary()]);
1223
+ } else if (dc === 1) {
1224
+ m = this.worker.i18n.translate(baseMsg + '_one', this.params.HTTPLanguages,
1225
+ ['', prov.system(), c.code, list.present(this.params.workingLanguages(), defLang.value, true), c.display, this.params.langSummary()]);
1226
+ } else {
1227
+ m = this.worker.i18n.translate(baseMsg + '_other', this.params.HTTPLanguages,
1228
+ [dc.toString(), prov.system(), c.code, list.present(this.params.workingLanguages(), defLang.value, true), c.display, this.params.langSummary()]);
1229
+ }
1230
+ msg(m);
1231
+ op.addIssue(new Issue(severity, 'invalid', addToPath(path, 'display'), baseMsg, m, 'invalid-display'));
1232
+ }
1233
+ if (prov.version()) {
1234
+ result.addParamStr('version', prov.version());
1235
+ }
1236
+ }
1237
+ }
1238
+ }
1239
+ i++;
1240
+ }
1241
+ if (ok === false && !this.valueSet.jsonObj.internallyDefined) {
1242
+ let mid, m, p;
1243
+ if (mode === 'codeableConcept') {
1244
+ mid = 'TX_GENERAL_CC_ERROR_MESSAGE';
1245
+ m = this.worker.i18n.translate('TX_GENERAL_CC_ERROR_MESSAGE', this.params.HTTPLanguages, [this.valueSet.vurl]);
1246
+ } else {
1247
+ mid = 'None_of_the_provided_codes_are_in_the_value_set_one';
1248
+ m = this.worker.i18n.translate('None_of_the_provided_codes_are_in_the_value_set_one', this.params.HTTPLanguages, ['', this.valueSet.vurl, codelist]);
1249
+ }
1250
+
1251
+ if (mode === 'codeableConcept') {
1252
+ p = '';
1253
+ } else if (!issuePath) {
1254
+ p = 'code';
1255
+ } else if (issuePath !== 'CodeableConcept') {
1256
+ p = issuePath + '.code';
1257
+ } else if (code.codingCount === 1) {
1258
+ p = issuePath + '.coding[0].code';
1259
+ } else {
1260
+ p = issuePath;
1261
+ }
1262
+
1263
+ if (op.addIssue(new Issue('error', 'code-invalid', p, mid, m, 'not-in-vs'))) {
1264
+ msg(m);
1265
+ }
1266
+ if (cause.value === 'null') {
1267
+ cause.value = 'unknown';
1268
+ }
1269
+ }
1270
+
1271
+ result.addParamBool('result', ok === true && !op.hasErrors());
1272
+ if (psys) {
1273
+ result.addParamUri('system', psys);
1274
+ } else if (ok === true && impliedSystem.value) {
1275
+ result.addParamUri('system', impliedSystem.value);
1276
+ } else if (tsys && mode !== 'codeableConcept') {
1277
+ result.addParamUri('system', tsys);
1278
+ }
1279
+
1280
+ for (let us of unknownSystems) {
1281
+ if (ok === false) {
1282
+ result.addParamCanonical('x-unknown-system', us);
1283
+ } else {
1284
+ result.addParamCanonical('x-caused-by-unknown-system', us);
1285
+ }
1286
+ }
1287
+ if (normalForm.value) {
1288
+ result.addParamCode('normalized-code', normalForm.value);
1289
+ }
1290
+
1291
+ if (pcode) {
1292
+ result.addParamCode('code', pcode);
1293
+ } else if (tcode && mode !== 'codeableConcept') {
1294
+ result.addParamCode('code', tcode);
1295
+ }
1296
+ if (pver) {
1297
+ result.addParamStr('version', pver);
1298
+ } else if (tver && mode !== 'codeableConcept') {
1299
+ result.addParamStr('version', tver);
1300
+ }
1301
+
1302
+ if (pdisp && (pcode || (tcode && mode !== 'codeableConcept'))) {
1303
+ result.addParamStr('display', pdisp);
1304
+ }
1305
+
1306
+ if (inactive.value) {
1307
+ result.addParamBool('inactive', inactive.value);
1308
+ if (vstatus.value && vstatus.value !== 'inactive') {
1309
+ result.addParamStr('status', vstatus.value);
1310
+ }
1311
+ let m = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, tcode]);
1312
+ msg(m);
1313
+ op.addIssue(new Issue('warning', 'business-rule', inactive.path, 'INACTIVE_CONCEPT_FOUND', m, 'code-comment'));
1314
+ } else if (vstatus.value && vstatus.value.toLowerCase() === 'deprecated') {
1315
+ result.addParamStr('status', 'deprecated');
1316
+ let m = this.worker.i18n.translate('DEPRECATED_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, tcode]);
1317
+ msg(m);
1318
+ op.addIssue(new Issue('warning', 'business-rule', issuePath, 'DEPRECATED_CONCEPT_FOUND', m, 'code-comment'));
1319
+ }
1320
+ for (let iss of op.issue || []) {
1321
+ if (iss.severity === 'error') {
1322
+ if (!mt.includes(iss.display)) {
1323
+ mt.push(iss.display);
1324
+ }
1325
+ }
1326
+ }
1327
+ op.listMissedErrors(mt);
1328
+ if (mt.length > 0) {
1329
+ mt.sort();
1330
+ result.addParamStr('message', toText(mt, '; '));
1331
+ }
1332
+ if (mode === 'codeableConcept') {
1333
+ result.addParam('codeableConcept', 'valueCodeableConcept', code);
1334
+ }
1335
+ if (op.hasIssues()) {
1336
+ result.addParamResource('issues', op.jsonObj);
1337
+ }
1338
+ return result;
1339
+ }
1340
+
1341
+ async checkDisplays(list, defLang, c, msg, op, path) {
1342
+ let hd = list.hasDisplay(this.params.workingLanguages(), null, c.display, false, DisplayCheckingStyle.CASE_INSENSITIVE)
1343
+ if (!hd.found) {
1344
+ let baseMsg;
1345
+ if (hd.difference === DisplayDifference.Normalized) {
1346
+ baseMsg = 'Display_Name_WS_for__should_be_one_of__instead_of';
1347
+ } else {
1348
+ baseMsg = 'Display_Name_for__should_be_one_of__instead_of';
1349
+ }
1350
+ let mid = baseMsg;
1351
+ let dc = list.displayCount(this.params.workingLanguages(), null, true);
1352
+ let severity = this.dispWarning();
1353
+ if (dc === 0) {
1354
+ severity = 'warning';
1355
+ dc = list.displayCount(this.params.workingLanguages(), null, false);
1356
+ }
1357
+
1358
+ let m, ds;
1359
+ if (dc === 0) {
1360
+ ds = await list.preferredDisplay(null);
1361
+ if (!ds) {
1362
+ m = this.worker.i18n.translate('NO_VALID_DISPLAY_AT_ALL', this.params.HTTPLanguages, [c.display, c.system, c.code]);
1363
+ mid = 'NO_VALID_DISPLAY_AT_ALL';
1364
+ } else {
1365
+ if (ds === c.display) {
1366
+ m = this.worker.i18n.translate('NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_OK', this.params.HTTPLanguages, [c.display, c.system, c.code, this.params.langSummary(), ds]);
1367
+ mid = 'NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_OK';
1368
+ severity = 'information';
1369
+ } else {
1370
+ m = this.worker.i18n.translate('NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR', this.params.HTTPLanguages, [c.display, c.system, c.code, this.params.langSummary(), ds]);
1371
+ mid = 'NO_VALID_DISPLAY_FOUND_NONE_FOR_LANG_ERR';
1372
+ if (this.params.displayWarning) {
1373
+ severity = 'warning';
1374
+ } else {
1375
+ severity = 'error';
1376
+ }
1377
+ }
1378
+ }
1379
+ } else if (dc === 1) {
1380
+ m = this.worker.i18n.translate(baseMsg + '_one', this.params.workingLanguages(),
1381
+ ['', c.system, c.code, list.present(this.params.workingLanguages(), defLang.value, dc > 0), c.display, this.params.langSummary()]);
1382
+ } else {
1383
+ m = this.worker.i18n.translate(baseMsg + '_other', this.params.workingLanguages(),
1384
+ [dc.toString(), c.system, c.code, list.present(this.params.workingLanguages(), defLang.value, dc > 0), c.display, this.params.langSummary()]);
1385
+ }
1386
+ msg(m);
1387
+ op.addIssue(new Issue(severity, 'invalid', addToPath(path, 'display'), mid, m, 'invalid-display'));
1388
+ } else {
1389
+ let hd = list.hasDisplay(this.params.workingLanguages(), null, c.display, false, DisplayCheckingStyle.CASE_INSENSITIVE);
1390
+ if (!hd.found) {
1391
+ let m, mid;
1392
+ if (list.source !== null && list.source.hasAnyDisplays(this.params.workingLanguages())) {
1393
+ mid = 'NO_VALID_DISPLAY_FOUND_LANG_SOME';
1394
+ m = this.worker.i18n.translatePlural(this.params.workingLanguages().length, 'NO_VALID_DISPLAY_FOUND_LANG_SOME', this.params.HTTPLanguages,
1395
+ [c.system, c.code, c.display, this.params.workingLanguages().toString(), c.display]);
1396
+ } else {
1397
+ mid = 'NO_VALID_DISPLAY_FOUND_LANG_NONE';
1398
+ m = this.worker.i18n.translatePlural(this.params.workingLanguages().length, 'NO_VALID_DISPLAY_FOUND_LANG_NONE', this.params.HTTPLanguages,
1399
+ [c.system, c.code, c.display, this.params.workingLanguages().toString(), c.display]);
1400
+ }
1401
+ op.addIssue(new Issue('information', 'invalid', addToPath(path, 'display'), mid, m, 'display-comment'));
1402
+ } else {
1403
+ let hd = list.hasDisplay(this.params.workingLanguages(), null, c.display, true, DisplayCheckingStyle.CASE_INSENSITIVE);
1404
+ if (!hd.found) {
1405
+ let ts2 = [];
1406
+ list.allowedDisplays(ts2, null, defLang.value);
1407
+ let mid = 'INACTIVE_DISPLAY_FOUND';
1408
+ let m = this.worker.i18n.translatePlural(ts2.length, mid, this.params.HTTPLanguages, [c.display, c.code, ts2.join(','), list.status(c.display)]);
1409
+ op.addIssue(new Issue('warning', 'invalid', addToPath(path, 'display'), mid, m, 'display-comment'));
1410
+ }
1411
+ }
1412
+ }
1413
+ }
1414
+
1415
+ async checkSystemCode(issuePath, system, version, code, inferSystem) {
1416
+ this.worker.opContext.clearContexts();
1417
+ if (inferSystem) {
1418
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + code + '" and infer system', this.indentCount);
1419
+ } else {
1420
+ this.worker.opContext.addNote(this.valueSet, 'Validate "' + this.worker.renderer.displayCoded(system, version, code) + '"', this.indentCount);
1421
+ }
1422
+ let unknownSystems = new Set();
1423
+ let unkCodes = [];
1424
+ let messages = [];
1425
+ let result = new Parameters();
1426
+ let op = new OperationOutcome();
1427
+ this.checkCanonicalStatus(issuePath, op, this.valueSet, this.valueSet);
1428
+ let list = new Designations(this.worker.languages);
1429
+ let ver = {value: ''};
1430
+ let inactive = {value: false};
1431
+ let normalForm = {value: ''};
1432
+ let vstatus = {value: ''};
1433
+ let cause = {value: null};
1434
+ let contentMode = {value: null};
1435
+ let impliedSystem = {value: ''};
1436
+ let defLang = {value: null};
1437
+
1438
+ let ok = await this.check(issuePath, system, version, code, true, inferSystem, list, unknownSystems, ver, inactive, normalForm, vstatus, cause, op, null, result, contentMode, impliedSystem, unkCodes, messages, defLang);
1439
+ if (ok === true) {
1440
+ result.AddParamBool('result', true);
1441
+ let pd = list.preferredDisplay(this.params.workingLanguages());
1442
+ if (pd) {
1443
+ result.addParamStr('display', pd);
1444
+ }
1445
+ result.addParamUri('system', system);
1446
+ if ((cause.value === 'not-found' && contentMode.value !== 'complete') || contentMode.value === 'example') {
1447
+ result.addParamStr('message', 'The system "' + system + ' was found but did not contain enough information to properly validate the code (mode = ' + contentMode.value + ')');
1448
+ }
1449
+ if (cause.value) {
1450
+ result.addParamCode('cause', cause.value);
1451
+ }
1452
+ if (inactive.value) {
1453
+ result.addParamBool('inactive', inactive.value);
1454
+ if (vstatus.value && vstatus.value !== 'inactive') {
1455
+ result.addParamStr('status', vstatus.value);
1456
+ }
1457
+ let msg = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, code]);
1458
+ messages.push(msg);
1459
+ op.addIssue(new Issue('warning', 'business-rule', 'code', 'INACTIVE_CONCEPT_FOUND', msg, 'code-comment'));
1460
+ } else if (vstatus.value.toLowerCase() === 'deprecated') {
1461
+ result.addParamStr('status', vstatus.value);
1462
+ let msg = this.worker.i18n.translate('DEPRECATED_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, code]);
1463
+ messages.push(msg);
1464
+ op.addIssue(new Issue('warning', 'business-rule', 'code', 'DEPRECATED_CONCEPT_FOUND', msg, 'code-comment'));
1465
+ }
1466
+ } else if (ok === null) {
1467
+ result.AddParamBool('result', false);
1468
+ result.addParamStr('message', 'The system "' + system + '" is unknown so the /"' + code + '" cannot be confirmed to be in the value set ' + this.valueSet.name);
1469
+ op.addIssueNoId('error', cause.value, 'code', 'The system "' + system + '" is unknown so the /"' + code + '" cannot be confirmed to be in the value set ' + this.valueSet.name, 'not-found');
1470
+ for (let us of unknownSystems) {
1471
+ result.addParamCanonical('x-caused-by-unknown-system', us);
1472
+ }
1473
+ } else {
1474
+ result.AddParamBool('result', false);
1475
+ result.addParamStr('message', 'The system/code "' + system + '"/"' + code + '" is not in the value set ' + this.valueSet.name);
1476
+ op.addIssueNoId('error', cause.value, 'code', 'The system/code "' + system + '"/"' + code + '" is not in the value set ' + this.valueSet.name, 'not-in-vs');
1477
+ if (cause.value) {
1478
+ result.AddParamCode('cause', cause.value);
1479
+ }
1480
+ }
1481
+ if (op.hasIssues()) {
1482
+ result.addParam('issues').resource = op.jsonObj;
1483
+ }
1484
+ return result;
1485
+ }
1486
+
1487
+ async checkConceptSet(path, role, cs, cset, code, abstractOk, displays, vs, message, inactive, normalForm, vstatus, op, vcc, messages) {
1488
+ this.worker.opContext.addNote(vs, 'check code ' + role + ' ' + this.worker.renderer.displayValueSetInclude(cset) + ' at ' + path, this.indentCount);
1489
+ inactive.value = false;
1490
+ let result = false;
1491
+ if (!cset.concept && !cset.filter) {
1492
+ let loc = await cs.locate(code);
1493
+ result = false;
1494
+ if (loc.context == null) {
1495
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs)+": "+loc.mesage, this.indentCount);
1496
+ if (!this.params.membershipOnly) {
1497
+ if (cs.contentMode() !== 'complete') {
1498
+ op.addIssue(new Issue('warning', 'code-invalid', addToPath(path, 'code'), 'UNKNOWN_CODE_IN_FRAGMENT', this.worker.i18n.translate('UNKNOWN_CODE_IN_FRAGMENT', this.params.HTTPLanguages, [code, cs.system(), cs.version()]), 'invalid-code'));
1499
+ result = true;
1500
+ } else {
1501
+ op.addIssue(new Issue('error', 'code-invalid', addToPath(path, 'code'), 'Unknown_Code_in_Version',
1502
+ this.worker.i18n.translate(Unknown_Code_in_VersionSCT(cs.system()), this.params.HTTPLanguages, [code, cs.system(), cs.version(), SCTVersion(cs.system(), cs.version())]), 'invalid-code'));
1503
+ }
1504
+ }
1505
+ if (loc.message && op) {
1506
+ op.addIssue(new Issue('information', 'code-invalid', addToPath(path, 'code'), null, loc.message, 'invalid-code'));
1507
+ }
1508
+ } else if (!(abstractOk || !cs.IsAbstract(loc.context))) {
1509
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
1510
+ if (!this.params.membershipOnly) {
1511
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1512
+ }
1513
+ } else if (this.excludeInactives() && await cs.isInactive(loc.context)) {
1514
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
1515
+ let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
1516
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
1517
+ result = false;
1518
+ messages.push(msg);
1519
+ if (!this.params.membershipOnly) {
1520
+ inactive.value = true;
1521
+ inactive.path = path;
1522
+ if (inactive.value) {
1523
+ vstatus.value = await cs.getStatus(loc.context);
1524
+ }
1525
+ }
1526
+ } else if (this.params.activeOnly && await cs.isInactive(loc.context)) {
1527
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
1528
+ result = false;
1529
+ inactive.value = true;
1530
+ inactive.path = path;
1531
+ vstatus.value = await cs.getStatus(loc.context);
1532
+ let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
1533
+ messages.push(msg);
1534
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
1535
+ } else {
1536
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1537
+ result = true;
1538
+ if (await cs.code(loc.context) != code) {
1539
+ let msg;
1540
+ if (cs.version()) {
1541
+ msg = this.worker.i18n.translate('CODE_CASE_DIFFERENCE', this.params.HTTPLanguages, [code, await cs.code(loc.context), cs.system() + '|' + cs.version()]);
1542
+ } else {
1543
+ msg = this.worker.i18n.translate('CODE_CASE_DIFFERENCE', this.params.HTTPLanguages, [code, await cs.code(loc.context), cs.system()]);
1544
+ }
1545
+ op.addIssue(new Issue('information', 'business-rule', addToPath(path, 'code'), 'CODE_CASE_DIFFERENCE', msg, 'code-rule'));
1546
+ normalForm.value = await cs.code(loc.context);
1547
+ }
1548
+ let msg = await cs.incompleteValidationMessage(loc.context, this.params.HTTPLanguages);
1549
+ if (msg) {
1550
+ op.addIssue(new Issue('information', 'informational', addToPath(path, 'code'), null, msg, 'process-note'));
1551
+ }
1552
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc.context);
1553
+ inactive.value = await cs.isInactive(loc.context);
1554
+ inactive.path = path;
1555
+ vstatus.value = await cs.getStatus(loc.context);
1556
+
1557
+ if (vcc !== null) {
1558
+ if (!vcc.coding) {
1559
+ vcc.coding = [];
1560
+ }
1561
+ vcc.coding.push({
1562
+ system: cs.system(),
1563
+ version: cs.version(),
1564
+ code: await cs.code(loc.context),
1565
+ display: displays.preferredDisplay(this.params.workingLanguages())
1566
+ });
1567
+ }
1568
+ return result;
1569
+ }
1570
+ }
1571
+
1572
+ for (let cc of cset.concept || []) {
1573
+ this.worker.deadCheck('checkConceptSet#1');
1574
+ let c = cc.code;
1575
+ if (code === c) {
1576
+ let loc = await cs.locate(code);
1577
+ if (loc.context !== null) {
1578
+ loc = loc.context;
1579
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1580
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc);
1581
+ this.worker.listDisplaysFromIncludeConcept(displays, cc, vs);
1582
+ if (!(abstractOk || !cs.IsAbstract(loc))) {
1583
+ if (!this.params.membershipOnly) {
1584
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1585
+ }
1586
+ } else if (this.excludeInactives() && await cs.isInactive(loc)) {
1587
+ result = false;
1588
+ if (!this.params.membershipOnly) {
1589
+ inactive.value = true;
1590
+ inactive.path = path;
1591
+ vstatus.value = await cs.getStatus(loc);
1592
+ }
1593
+ } else {
1594
+ if (vcc !== null) {
1595
+ if (!vcc.coding) {vcc.coding = [];}
1596
+ vcc.coding.push({system: cs.system(), version: cs.version(), code: await cs.code(loc), display: displays.preferredDisplay(this.params.workingLanguages())});
1597
+ }
1598
+ let sstatus = Extensions.readString(cc, 'http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status');
1599
+ if (['withdrawn', 'deprecated'].includes(sstatus)) {
1600
+ op.addIssue(new Issue('warning', 'business-rule', addToPath(path, 'code'), 'CONCEPT_DEPRECATED_IN_VALUESET', this.worker.i18n.translate('CONCEPT_DEPRECATED_IN_VALUESET', this.params.HTTPLanguages, [cs.system(), code, sstatus, vs.vurl]), 'code-comment'));
1601
+ } else if (Extensions.has(cc,'http://hl7.org/fhir/StructureDefinition/valueset-deprecated')) {
1602
+ op.addIssue(new Issue('warning', 'business-rule', addToPath(path, 'code'), 'CONCEPT_DEPRECATED_IN_VALUESET', this.worker.i18n.translate('CONCEPT_DEPRECATED_IN_VALUESET', this.params.HTTPLanguages, [cs.system(), code, 'deprecated', vs.vurl]), 'code-comment'));
1603
+ }
1604
+ inactive.value = await cs.isInactive(loc);
1605
+ inactive.path = path;
1606
+ vstatus.value = await cs.getStatus(loc);
1607
+ result = true;
1608
+ return result;
1609
+ }
1610
+ } else {
1611
+ this.worker.opContext.addNote(this.valueSet, 'Code "' + code + '" in concept list, but not found in ' + this.worker.renderer.displayCoded(cs)+": "+loc.message, this.indentCount);
1612
+ }
1613
+ }
1614
+ }
1615
+
1616
+ if (cset.filter) {
1617
+ let cfl = cset.filter;
1618
+ let prep = await cs.getPrepContext(false);
1619
+ for (let fc of cfl) {
1620
+ this.worker.deadCheck('checkConceptSet#2');
1621
+ if (!fc.value) {
1622
+ throw new Issue('error', 'invalid', null, 'UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE', this.worker.i18n.translate('UNABLE_TO_HANDLE_SYSTEM_FILTER_WITH_NO_VALUE', this.params.HTTPLanguages, [cs.system(), fc.property, fc.op]));
1623
+ }
1624
+ await cs.filter(prep, fc.property, fc.op, fc.value);
1625
+ // if (f === null) {
1626
+ // throw new Issue('error', 'not-supported', null, 'FILTER_NOT_UNDERSTOOD', this.worker.i18n.translate('FILTER_NOT_UNDERSTOOD', this.params.HTTPLanguages, [fc.property, fc.op, fc.value, vs.vurl, cs.system()]) + ' (2)', 'vs-invalid');
1627
+ // }
1628
+ }
1629
+ let filters = await cs.executeFilters(prep);
1630
+ if (filters) {
1631
+ let ctxt = filters[0];
1632
+ let loc = await cs.filterLocate(prep, ctxt, code);
1633
+ if (loc != null && !(typeof loc === 'string')) {
1634
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc);
1635
+ if (!(abstractOk || !cs.IsAbstract(loc))) {
1636
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
1637
+ if (!this.params.membershipOnly) {
1638
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1639
+ }
1640
+ } else if (this.excludeInactives() && await cs.isInactive(loc)) {
1641
+ result = false;
1642
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
1643
+ if (!this.params.membershipOnly) {
1644
+ inactive.value = true;
1645
+ inactive.path = path;
1646
+ vstatus.value = await cs.getStatus(loc);
1647
+ }
1648
+ } else {
1649
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1650
+ if (vcc !== null) {
1651
+ if (!vcc.coding) { vcc.coding = []}
1652
+ vcc.coding.push( { system : cs.system(), version: cs.version(), code: await cs.code(loc), display: displays.preferredDisplay(this.params.workingLanguages())});
1653
+ }
1654
+ result = true;
1655
+ return result;
1656
+ }
1657
+ } else if (loc != null) {
1658
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs)+ ": "+loc, this.indentCount);
1659
+ messages.push(loc);
1660
+ } else {
1661
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1662
+ }
1663
+ } else {
1664
+ result = true;
1665
+ let i = 0;
1666
+ for (let fc of cfl) {
1667
+ this.worker.deadCheck('checkConceptSet#3');
1668
+ if (fc.propertyerty === 'concept' && ["is-a", "descendent-of"].includes(fc.op)) {
1669
+ let loc = await cs.locateIsA(code, fc.value, fc.op === "descendent-of");
1670
+ if (loc !== null) {
1671
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc);
1672
+ if (!(abstractOk || !cs.IsAbstract(loc))) {
1673
+ this.worker.opContext.addNote(this.valueSet, 'Filter "' + fc.property + '' + fc.op + '' + fc.value + '": Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
1674
+ if (!this.params.membershipOnly) {
1675
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1676
+ }
1677
+ } else {
1678
+ this.worker.opContext.addNote(this.valueSet, 'Filter "' + fc.property + fc.op + fc.value + '": Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1679
+ if (vcc !== null) {
1680
+ vcc.addCoding(cs.system(), cs.version(), await cs.code(loc), displays.preferredDisplay(this.params.workingLanguages()));
1681
+ }
1682
+ result = true;
1683
+ return result;
1684
+ }
1685
+ } else {
1686
+ result = false;
1687
+ this.worker.opContext.addNote(this.valueSet, 'Filter "' + fc.property + fc.op + fc.value + '": Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1688
+ }
1689
+ } else if (fc.property === 'concept' && fc.op === 'is-not-a') {
1690
+ let loc = await cs.locateIsA(code, fc.value);
1691
+ result = loc === null;
1692
+ if (result) {
1693
+ let msg;
1694
+ loc = await cs.locate(code, null, msg);
1695
+ if (loc !== null) {
1696
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc);
1697
+ if (!(abstractOk || !cs.IsAbstract(loc))) {
1698
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + fc.property + fc.op + fc.value + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
1699
+ if (!this.params.membershipOnly) {
1700
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1701
+ }
1702
+ } else if (this.excludeInactives() && await cs.isInactive(loc)) {
1703
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + fc.property + fc.op + fc.value + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
1704
+ result = false;
1705
+ if (!this.params.membershipOnly) {
1706
+ inactive.value = true;
1707
+ inactive.path = path;
1708
+ vstatus.value = await cs.getStatus(loc);
1709
+ }
1710
+ } else {
1711
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + fc.property + fc.op + fc.value + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1712
+ if (vcc !== null) {
1713
+ vcc.addCoding(cs.system(), cs.version(), await cs.code(loc), displays.preferredDisplay(this.params.workingLanguages()));
1714
+ }
1715
+ result = true;
1716
+ return result;
1717
+ }
1718
+ }
1719
+ } else {
1720
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + fc.property + fc.op + fc.value + ': Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1721
+ }
1722
+ } else {
1723
+ let ctxt = filters[i];
1724
+ result = false;
1725
+ let loc = await cs.filterLocate(prep, ctxt, code);
1726
+ if (!(typeof loc === 'string')) {
1727
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc);
1728
+ if (!(abstractOk || !cs.IsAbstract(loc))) {
1729
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is abstract', this.indentCount);
1730
+ if (!this.params.membershipOnly) {
1731
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1732
+ }
1733
+ } else if (this.excludeInactives() && await cs.isInactive(loc)) {
1734
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs) + ' but is inactive', this.indentCount);
1735
+ result = false;
1736
+ if (!this.params.membershipOnly) {
1737
+ inactive.value = true;
1738
+ inactive.path = path;
1739
+ vstatus.value = await cs.getStatus(loc);
1740
+ }
1741
+ } else {
1742
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" found in ' + this.worker.renderer.displayCoded(cs), this.indentCount);
1743
+ if (vcc !== null) {
1744
+ vcc.addCoding(cs.system(), cs.version(), await cs.code(loc), displays.preferredDisplay(this.params.workingLanguages()));
1745
+ }
1746
+ result = true;
1747
+ return result;
1748
+ }
1749
+ } else {
1750
+ this.worker.opContext.addNote(this.valueSet, 'Filter ' + ctxt.summary + ': Code "' + code + '" not found in ' + this.worker.renderer.displayCoded(cs)+": "+loc, this.indentCount);
1751
+ }
1752
+ }
1753
+ if (!result) {
1754
+ break;
1755
+ }
1756
+ i++;
1757
+ }
1758
+ }
1759
+ }
1760
+ return result;
1761
+ }
1762
+
1763
+ async checkExpansion(path, cs, cset, code, abstractOk, displays, vs, message, inactive, vstatus, op) {
1764
+ let result = false;
1765
+ let loc = await cs.locate(code, null, message);
1766
+ result = false;
1767
+ if (loc === null || loc.context == null) {
1768
+ if (!this.params.membershipOnly) {
1769
+ op.addIssue(new Issue('error', 'code-invalid', addToPath(path, 'code'), 'Unknown_Code_in_Version',
1770
+ this.worker.i18n.translate(Unknown_Code_in_VersionSCT(cs.system()), this.params.HTTPLanguages, [code, cs.system(), cs.version(), SCTVersion(cs.system(), cs.version())]), 'invalid-code'));
1771
+ }
1772
+ } else if (!(abstractOk || !cs.IsAbstract(loc.context))) {
1773
+ if (!this.params.membershipOnly) {
1774
+ op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'ABSTRACT_CODE_NOT_ALLOWED', this.worker.i18n.translate('ABSTRACT_CODE_NOT_ALLOWED', this.params.HTTPLanguages, [cs.system(), code]), 'code-rule'));
1775
+ }
1776
+ } else {
1777
+ result = true;
1778
+ inactive.value = await cs.isInactive(loc.context);
1779
+ inactive.path = path;
1780
+ vstatus.value = await cs.getStatus(loc.context);
1781
+ await this.worker.listDisplaysFromCodeSystem(displays, cs, loc.context);
1782
+ return result;
1783
+ }
1784
+ return result;
1785
+ }
1786
+
1787
+
1788
+ excludeInactives() {
1789
+ return this.valueSet.jsonObj.compose && this.valueSet.jsonObj.compose.inactive != undefined && !this.valueSet.jsonObj.compose.inactive;
1790
+ }
1791
+
1792
+ }
1793
+
1794
+ function addToPath(path, name) {
1795
+ if (!path) {
1796
+ return name;
1797
+ } else {
1798
+ return path + '.' + name;
1799
+ }
1800
+ }
1801
+
1802
+
1803
+ function Unknown_Code_in_VersionSCT(url) {
1804
+ if (url === 'http://snomed.info/sct') {
1805
+ return 'Unknown_Code_in_Version_SCT';
1806
+ } else {
1807
+ return 'Unknown_Code_in_Version';
1808
+ }
1809
+ }
1810
+
1811
+ function SCTVersion(url, ver) {
1812
+ if (url !== 'http://snomed.info/sct' || !ver) {
1813
+ return '';
1814
+ } else {
1815
+ let result = 'unknown';
1816
+ let s = ver.split('/');
1817
+ if (s.length >= 5) {
1818
+ if (s[4] === '900000000000207008') result = 'International Edition';
1819
+ else if (s[4] === '449081005') result = 'International Spanish Edition';
1820
+ else if (s[4] === '11000221109') result = 'Argentinian Edition';
1821
+ else if (s[4] === '32506021000036107') result = 'Australian Edition (with drug extension)';
1822
+ else if (s[4] === '11000234105') result = 'Austrian Edition';
1823
+ else if (s[4] === '11000172109') result = 'Belgian Edition';
1824
+ else if (s[4] === '20621000087109') result = 'Canadian English Edition';
1825
+ else if (s[4] === '20611000087101') result = 'Canadian Canadian French Edition';
1826
+ else if (s[4] === '11000279109') result = 'Czech Edition';
1827
+ else if (s[4] === '554471000005108') result = 'Danish Edition';
1828
+ else if (s[4] === '11000181102') result = 'Estonian Edition';
1829
+ else if (s[4] === '11000229106') result = 'Finnish Edition';
1830
+ else if (s[4] === '11000274103') result = 'German Edition';
1831
+ else if (s[4] === '1121000189102') result = 'Indian Edition';
1832
+ else if (s[4] === '827022005') result = 'IPS Terminology';
1833
+ else if (s[4] === '11000220105') result = 'Irish Edition';
1834
+ else if (s[4] === '11000146104') result = 'Netherlands Edition';
1835
+ else if (s[4] === '21000210109') result = 'New Zealand Edition';
1836
+ else if (s[4] === '51000202101') result = 'Norwegian Edition';
1837
+ else if (s[4] === '11000267109') result = 'Republic of Korea Edition (South Korea)';
1838
+ else if (s[4] === '900000001000122104') result = 'Spanish National Edition';
1839
+ else if (s[4] === '45991000052106') result = 'Swedish Edition';
1840
+ else if (s[4] === '2011000195101') result = 'Swiss Edition';
1841
+ else if (s[4] === '83821000000107') result = 'UK Edition';
1842
+ else if (s[4] === '999000021000000109') result = 'UK Clinical Edition';
1843
+ else if (s[4] === '5631000179106') result = 'Uruguay Edition';
1844
+ else if (s[4] === '21000325107') result = 'Chilean Edition';
1845
+ else if (s[4] === '731000124108') result = 'US Edition';
1846
+ else if (s[4] === '5991000124107') result = 'US Edition (with ICD-10-CM maps)';
1847
+ }
1848
+ return result;
1849
+ }
1850
+ }
1851
+
1852
+
1853
+ function toText(st, sep) {
1854
+ if (st === null || st.length === 0) {
1855
+ return '';
1856
+ } else {
1857
+ let result = st[0];
1858
+ for (let i = 1; i < st.length; i++) {
1859
+ result = result + sep + st[i];
1860
+ }
1861
+ return result;
1862
+ }
1863
+ }
1864
+
1865
+ class ValidateWorker extends TerminologyWorker {
1866
+
1867
+ /**
1868
+ * @param {OperationContext} opContext - Operation context
1869
+ * @param {Logger} log - Logger instance
1870
+ * @param {Provider} provider - Provider for code systems and resources
1871
+ * @param {LanguageDefinitions} languages - Language definitions
1872
+ * @param {I18nSupport} i18n - Internationalization support
1873
+ */
1874
+ constructor(opContext, log, provider, languages, i18n) {
1875
+ super(opContext, log, provider, languages, i18n);
1876
+ }
1877
+
1878
+ /**
1879
+ * Get operation name
1880
+ * @returns {string}
1881
+ */
1882
+ opName() {
1883
+ return 'validate-code';
1884
+ }
1885
+
1886
+ // ========== Entry Points ==========
1887
+
1888
+ /**
1889
+ * Handle a type-level CodeSystem $validate-code request
1890
+ * GET/POST /CodeSystem/$validate-code
1891
+ */
1892
+ async handleCodeSystem(req, res) {
1893
+ try {
1894
+ const params = this.buildParameters(req);
1895
+ this.addHttpParams(req, params);
1896
+ this.log.debug('CodeSystem $validate-code with params:', params);
1897
+
1898
+ let result = await this.handleCodeSystemInner(params);
1899
+
1900
+ return res.status(200).json(result);
1901
+
1902
+ } catch (error) {
1903
+ this.log.error(error);
1904
+ console.error(error);
1905
+ if (error instanceof Issue) {
1906
+ if (error.isHandleAsOO()) {
1907
+ let oo = new OperationOutcome();
1908
+ oo.addIssue(error);
1909
+ return res.status(error.statusCode || 500).json(oo.jsonObj);
1910
+ } else {
1911
+ // this is actually handled in the inner method
1912
+ }
1913
+ } else {
1914
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
1915
+ 'error', error.issueCode || 'exception', error.message));
1916
+ }
1917
+
1918
+ }
1919
+ }
1920
+
1921
+ async handleCodeSystemInner(params, req) {
1922
+ let coded;
1923
+ let mode;
1924
+
1925
+ try {
1926
+ // Handle tx-resource and cache-id parameters
1927
+ this.setupAdditionalResources(params);
1928
+
1929
+ let txp = new TxParameters(this.languages, this.i18n, true);
1930
+ txp.readParams(params);
1931
+
1932
+ // Extract coded value
1933
+ mode = {mode: null};
1934
+ coded = this.extractCodedValue(params, true, mode);
1935
+ if (!coded) {
1936
+ throw new Issue('error', 'invalid', null, null, 'Unable to find code to validate (looked for coding | codeableConcept | code in parameters =codingX:Coding)', null, 400);
1937
+ }
1938
+
1939
+ // Get the CodeSystem - from parameter or by url
1940
+ const codeSystem = await this.resolveCodeSystem(params, txp, coded?.coding?.[0] ?? null, mode);
1941
+ if (!codeSystem) {
1942
+ throw new Issue('error', 'invalid', null, null, 'No CodeSystem specified - provide url parameter or codeSystem resource', null, 400);
1943
+ }
1944
+ if (codeSystem.contentMode() == 'supplement') {
1945
+ throw new Issue('error', 'invalid', this.systemPath(mode), 'CODESYSTEM_CS_NO_SUPPLEMENT', this.opContext.i18n.translate('CODESYSTEM_CS_NO_SUPPLEMENT', txp.HTTPLanguages, [codeSystem.vurl()]), "invalid-data");
1946
+ }
1947
+
1948
+ // Perform validation
1949
+ const result = await this.doValidationCS(coded, codeSystem, txp, mode);
1950
+ if (req) {
1951
+ req.logInfo = this.usedSources.join("|") + txp.logInfo();
1952
+ }
1953
+ return result;
1954
+ } catch (error) {
1955
+ this.log.error(error);
1956
+ if (error instanceof Issue && !error.isHandleAsOO()) {
1957
+ return this.handlePrepareError(error, coded, mode.mode);
1958
+ } else {
1959
+ throw error;
1960
+ }
1961
+
1962
+ }
1963
+
1964
+
1965
+ }
1966
+ systemPath(mode) {
1967
+ switch (mode.mode) {
1968
+ case 'code': return 'system';
1969
+ case 'coding': return 'Coding.system';
1970
+ default: return 'CodeableConcept.coding[0].system';
1971
+ }
1972
+ }
1973
+
1974
+ /**
1975
+ * Handle an instance-level CodeSystem $validate-code request
1976
+ * GET/POST /CodeSystem/{id}/$validate-code
1977
+ */
1978
+ async handleCodeSystemInstance(req, res) {
1979
+ try {
1980
+ const {id} = req.params;
1981
+ const params = this.buildParameters(req);
1982
+ this.log.debug(`CodeSystem/${id}/$validate-code with params:`, params);
1983
+
1984
+ // Handle tx-resource and cache-id parameters
1985
+ this.setupAdditionalResources(params);
1986
+
1987
+ let txp = new TxParameters(this.languages, this.i18n, true);
1988
+ txp.readParams(params);
1989
+
1990
+ // Get the CodeSystem by id
1991
+ const codeSystem = await this.provider.getCodeSystemById(this.opContext, id);
1992
+ if (!codeSystem) {
1993
+ return res.status(404).json(this.operationOutcome('error', 'not-found',
1994
+ `CodeSystem/${id} not found`));
1995
+ }
1996
+ const csp = new FhirCodeSystemProvider(this.opContext, new CodeSystem(codeSystem), []);
1997
+
1998
+ // Extract coded value
1999
+ let mode = { mode : null }
2000
+ const coded = this.extractCodedValue(params, true, mode);
2001
+ if (!coded) {
2002
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
2003
+ 'Unable to find code to validate (looked for coding | codeableConcept | code in parameters =codingX:Coding)'));
2004
+ }
2005
+
2006
+ // Perform validation
2007
+ const result = await this.doValidationCS(coded, csp, txp, mode);
2008
+ req.logInfo = this.usedSources.join("|") + txp.logInfo();
2009
+ return res.json(result);
2010
+
2011
+ } catch (error) {
2012
+ this.log.error(error);
2013
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
2014
+ 'error', error.issueCode || 'exception', error.message));
2015
+ }
2016
+ }
2017
+
2018
+ /**
2019
+ * Handle a type-level ValueSet $validate-code request
2020
+ * GET/POST /ValueSet/$validate-code
2021
+ */
2022
+ async handleValueSet(req, res) {
2023
+ try {
2024
+ const params = this.buildParameters(req);
2025
+ this.addHttpParams(req, params);
2026
+ this.log.debug('ValueSet $validate-code with params:', params);
2027
+
2028
+ const result = await this.handleValueSetInner(params, req);
2029
+ return res.json(result);
2030
+
2031
+ } catch (error) {
2032
+ this.log.error(error);
2033
+ if (error instanceof Issue) {
2034
+ let op = new OperationOutcome();
2035
+ op.addIssue(error);
2036
+ return res.status(error.statusCode || 500).json(op.jsonObj);
2037
+ } else {
2038
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
2039
+ 'error', error.issueCode || 'exception', error.message));
2040
+ }
2041
+ }
2042
+ }
2043
+
2044
+ async handleValueSetInner(params, req) {
2045
+ // Handle tx-resource and cache-id parameters
2046
+ this.setupAdditionalResources(params);
2047
+
2048
+ let txp = new TxParameters(this.languages, this.i18n, true);
2049
+ txp.readParams(params);
2050
+
2051
+ // Get the ValueSet - from parameter or by url
2052
+ const valueSet = await this.resolveValueSet(params, txp);
2053
+ if (!valueSet) {
2054
+ throw new Issue("error", "invalid", null, null, 'No ValueSet specified - provide url parameter or valueSet resource', null, 400);
2055
+ }
2056
+ // Extract coded value
2057
+
2058
+ let mode = { mode : null };
2059
+ const coded = this.extractCodedValue(params, false, mode);
2060
+ if (!coded) {
2061
+ throw new Issue("error", "invalid", null, null, 'Unable to find code to validate (looked for coding | codeableConcept | code in parameters =codingX:Coding)', null, 400);
2062
+ }
2063
+
2064
+ // Perform validation
2065
+ let res = await this.doValidationVS(coded, valueSet, txp, mode.mode, mode.issuePath);
2066
+ if (req) {
2067
+ req.logInfo = this.usedSources.join("|") + txp.logInfo();
2068
+ }
2069
+ return res;
2070
+ }
2071
+ /**
2072
+ * Handle an instance-level ValueSet $validate-code request
2073
+ * GET/POST /ValueSet/{id}/$validate-code
2074
+ */
2075
+ async handleValueSetInstance(req, res) {
2076
+ try {
2077
+ const {id} = req.params;
2078
+ const params = this.buildParameters(req);
2079
+ this.log.debug(`ValueSet/${id}/$validate-code with params:`, params);
2080
+
2081
+ // Handle tx-resource and cache-id parameters
2082
+ this.setupAdditionalResources(params);
2083
+
2084
+ let txp = new TxParameters(this.languages, this.i18n, true);
2085
+ txp.readParams(params);
2086
+
2087
+ // Get the ValueSet by id
2088
+ const valueSet = await this.provider.getValueSetById(this.opContext, id);
2089
+ this.seeSourceVS(valueSet, id);
2090
+ if (!valueSet) {
2091
+ return res.status(404).json(this.operationOutcome('error', 'not-found',
2092
+ `ValueSet/${id} not found`));
2093
+ }
2094
+
2095
+ // Extract coded value
2096
+ let mode = { mode : null };
2097
+ const coded = this.extractCodedValue(params, false, mode);
2098
+ if (!coded) {
2099
+ return res.status(400).json(this.operationOutcome('error', 'invalid',
2100
+ 'Unable to find code to validate (looked for coding | codeableConcept | code in parameters =codingX:Coding)'));
2101
+ }
2102
+
2103
+ // Perform validation
2104
+ const result = await this.doValidationVS(coded, valueSet, txp, mode.mode, mode.issuePath);
2105
+ req.logInfo = this.usedSources.join("|")+txp.logInfo();
2106
+ return res.json(result);
2107
+
2108
+ } catch (error) {
2109
+ this.log.error(error);
2110
+ return res.status(error.statusCode || 500).json(this.operationOutcome(
2111
+ 'error', error.issueCode || 'exception', error.message));
2112
+ }
2113
+ }
2114
+
2115
+ // ========== Resource Resolution ==========
2116
+
2117
+ /**
2118
+ * Resolve the CodeSystem to validate against
2119
+ * @param {Object} params - Parameters resource
2120
+ * @param {string|null} id - Instance id (if instance-level request)
2121
+ * @returns {Object|null} CodeSystem resource (wrapper or JSON)
2122
+ */
2123
+ async resolveCodeSystem(params, txParams, coded, mode) {
2124
+ // Check for codeSystem resource parameter
2125
+ const csResource = this.getResourceParam(params, 'codeSystem');
2126
+ if (csResource) {
2127
+ return csResource;
2128
+ }
2129
+ let path = coded == null ? null : mode.issuePath+".system";
2130
+ let fromCoded = false;
2131
+ // Check for url parameter
2132
+ let url = this.getStringParam(params, 'url');
2133
+ if (!url && coded.system) {
2134
+ fromCoded = true;
2135
+ url = coded.system;
2136
+ }
2137
+ if (!url) {
2138
+ return null;
2139
+ }
2140
+
2141
+ let issue = null;
2142
+ if (!isAbsoluteUrl(url)) {
2143
+ let m = this.i18n.translate('Terminology_TX_System_Relative', txParams.HTTPLanguages, [url]);
2144
+ issue = new Issue('error', 'invalid', path, 'Terminology_TX_System_Relative', m, 'invalid-data');
2145
+ }
2146
+
2147
+ let version = this.getStringParam(params, 'version');
2148
+ if (!version && fromCoded) {
2149
+ version = coded.version;
2150
+ }
2151
+ version = this.determineVersionBase(url, version, txParams);
2152
+
2153
+ let supplements = this.loadSupplements(url, version);
2154
+
2155
+ // First check additional resources
2156
+ const fromAdditional = this.findInAdditionalResources(url, version, 'CodeSystem', false);
2157
+ if (fromAdditional) {
2158
+ return this.provider.createCodeSystemProvider(this.opContext, fromAdditional, supplements);
2159
+ } else {
2160
+
2161
+ let csp = await this.provider.getCodeSystemProvider(this.opContext, url, version, supplements);
2162
+ if (csp) {
2163
+ return csp;
2164
+ } else {
2165
+ let vs = await this.findValueSet(url, version);
2166
+ if (vs) {
2167
+ let msg = this.i18n.translate('Terminology_TX_System_ValueSet2', txParams.HTTPLanguages, [url]);
2168
+ throw new Issue('error', 'invalid', path, 'Terminology_TX_System_ValueSet2', msg, 'invalid-data');
2169
+ } else if (version) {
2170
+ let vl = await this.listVersions(url);
2171
+ if (vl.length == 0) {
2172
+ throw new Issue("error", "not-found", this.systemPath(mode), 'UNKNOWN_CODESYSTEM_VERSION_NONE', this.opContext.i18n.translate('UNKNOWN_CODESYSTEM_VERSION_NONE', this.opContext.HTTPLanguages, [url, version]), 'not-found').setUnknownSystem(url).addIssue(issue);
2173
+ } else {
2174
+ throw new Issue("error", "not-found", this.systemPath(mode), 'UNKNOWN_CODESYSTEM_VERSION', this.opContext.i18n.translate('UNKNOWN_CODESYSTEM_VERSION', this.opContext.HTTPLanguages, [url, version, this.presentVersionList(vl)]), 'not-found').setUnknownSystem(url + "|" + version).addIssue(issue);
2175
+ }
2176
+ } else {
2177
+ throw new Issue("error", "not-found", this.systemPath(mode), 'UNKNOWN_CODESYSTEM', this.opContext.i18n.translate('UNKNOWN_CODESYSTEM', this.opContext.HTTPLanguages, [url]), 'not-found').setUnknownSystem(url).addIssue(issue);
2178
+ }
2179
+ }
2180
+ }
2181
+ }
2182
+
2183
+ /**
2184
+ * Resolve the ValueSet to validate against
2185
+ * @param {Object} params - Parameters resource
2186
+ * @param {string|null} id - Instance id (if instance-level request)
2187
+ * @returns {Object|null} ValueSet resource (wrapper or JSON)
2188
+ */
2189
+ async resolveValueSet(params, txParams) {
2190
+ // Check for valueSet resource parameter
2191
+ const vsResource = this.getResourceParam(params, 'valueSet');
2192
+ if (vsResource) {
2193
+ this.seeSourceVS(vsResource);
2194
+ return new ValueSet(vsResource);
2195
+ }
2196
+
2197
+ // Check for url parameter
2198
+ const url = this.getStringParam(params, 'url');
2199
+ if (url) {
2200
+ const version = this.determineVersionBase(url, this.getStringParam(params, 'valueSetVersion'), txParams);
2201
+
2202
+ // First check additional resources
2203
+ const fromAdditional = this.findInAdditionalResources(url, version, 'ValueSet', false);
2204
+ if (fromAdditional) {
2205
+ return fromAdditional;
2206
+ }
2207
+
2208
+ let vs = await this.provider.findValueSet(this.opContext, url, version);
2209
+ this.seeSourceVS(vs, url);
2210
+ if (vs == null) {
2211
+ throw new Issue('error', 'not-found', null, 'Unable_to_resolve_value_Set_', this.i18n.translate('Unable_to_resolve_value_Set_', params.HTTPLanguages, [url+(version ? "|"+version : "")]), 'not-found', 400);
2212
+ } else {
2213
+ return vs;
2214
+ }
2215
+ }
2216
+
2217
+ return null;
2218
+ }
2219
+
2220
+ // ========== Coded Value Extraction ==========
2221
+
2222
+ /**
2223
+ * Extract the coded value to validate as a CodeableConcept
2224
+ * @param {Object} params - Parameters resource
2225
+ * @param {string} mode - 'cs' for CodeSystem, 'vs' for ValueSet
2226
+ * @returns {Object|null} CodeableConcept or null
2227
+ */
2228
+ extractCodedValue(params, isCs, mode) {
2229
+ // Priority 1: codeableConcept parameter
2230
+ const cc = this.getCodeableConceptParam(params, 'codeableConcept');
2231
+ if (cc) {
2232
+ mode.mode = 'codeableConcept';
2233
+ mode.issuePath = "CodeableConcept";
2234
+ return cc;
2235
+ }
2236
+
2237
+ // Priority 2: coding parameter
2238
+ const coding = this.getCodingParam(params, 'coding');
2239
+ if (coding) {
2240
+ mode.mode = 'coding';
2241
+ mode.issuePath = "Coding";
2242
+ return {coding: [coding]};
2243
+ }
2244
+
2245
+ // Priority 3: individual parameters (code required)
2246
+ const code = this.getStringParam(params, 'code');
2247
+ if (code) {
2248
+ mode.mode = 'code';
2249
+ mode.issuePath = "";
2250
+ // For CodeSystem mode: url/version
2251
+ // For ValueSet mode: system/systemVersion
2252
+ let system, version;
2253
+ if (isCs) {
2254
+ system = this.getStringParam(params, 'url');
2255
+ if (!system) {
2256
+ system = this.getStringParam(params, 'system');
2257
+
2258
+ }
2259
+ version = this.getStringParam(params, 'version');
2260
+ } else {
2261
+ system = this.getStringParam(params, 'system');
2262
+ version = this.getStringParam(params, 'systemVersion');
2263
+ }
2264
+ const display = this.getStringParam(params, 'display');
2265
+
2266
+ const codingObj = {code};
2267
+ if (system) codingObj.system = system;
2268
+ if (version) codingObj.version = version;
2269
+ if (display) codingObj.display = display;
2270
+
2271
+ return {coding: [codingObj]};
2272
+ }
2273
+
2274
+ return null;
2275
+ }
2276
+
2277
+ // ========== Validation Logic ==========
2278
+
2279
+ /**
2280
+ * Perform CodeSystem validation
2281
+ * @param {Object} coded - CodeableConcept to validate
2282
+ * @param {Object} codeSystem - CodeSystem to validate against
2283
+ * @param {Object} params - Full parameters
2284
+ * @returns {Object} Parameters resource with result
2285
+ */
2286
+ async doValidationCS(coded, codeSystem, params, mode) {
2287
+ this.deadCheck('doValidationCS');
2288
+ this.params = params;
2289
+
2290
+ let vs = this.makeVsForCS(codeSystem);
2291
+
2292
+ // Get parameters
2293
+ const abstractOk = this._getBoolParam(params, 'abstract', true);
2294
+
2295
+ // Create and prepare checker
2296
+ const checker = new ValueSetChecker(this, vs, params);
2297
+
2298
+ // Perform validation
2299
+ const result = await checker.checkCodeableConcept(mode.issuePath, coded, abstractOk, false, mode.mode);
2300
+
2301
+ // Add diagnostics if requested
2302
+ if (params.diagnostics) {
2303
+ result.jsonObj.parameter.push({name: 'diagnostics', valueString: this.opContext.diagnostics()});
2304
+ }
2305
+
2306
+ return result.jsonObj;
2307
+ }
2308
+
2309
+ makeVsForCS(codeSystem) {
2310
+ let vs = {
2311
+ resourceType: "ValueSet",
2312
+ internallyDefined : true,
2313
+ status: 'active',
2314
+ url : codeSystem.valueSet() ? codeSystem.valueSet() : codeSystem.system()+"/vs",
2315
+ compose : {
2316
+ "include" : [{
2317
+ system: codeSystem.system()
2318
+ }]
2319
+ }
2320
+ }
2321
+ if (codeSystem.version()) {
2322
+ vs.version = codeSystem.version();
2323
+ vs.compose.include[0].version = codeSystem.version();
2324
+ }
2325
+ return new ValueSet(vs);
2326
+ }
2327
+
2328
+ /**
2329
+ * Perform ValueSet validation
2330
+ * @param {Object} coded - CodeableConcept to validate
2331
+ * @param {Object} valueSet - ValueSet to validate against
2332
+ * @param {Object} params - Full parameters
2333
+ * @returns {Object} Parameters resource with result
2334
+ */
2335
+ async doValidationVS(coded, valueSet, params, mode, issuePath) {
2336
+ this.deadCheck('doValidationVS');
2337
+ this.params = params;
2338
+
2339
+ // Get parameters
2340
+ const abstractOk = this._getBoolParam(params, 'abstract', true);
2341
+ const inferSystem = this._getBoolParam(params, 'inferSystem', false) || (mode === 'code' && !coded.coding[0].system)
2342
+
2343
+ // Create and prepare checker
2344
+ const checker = new ValueSetChecker(this, valueSet, params);
2345
+ try {
2346
+ await checker.prepare();
2347
+ } catch (error) {
2348
+ this.log.error(error);
2349
+ if (!(error instanceof Issue) || error.isHandleAsOO()) {
2350
+ throw error;
2351
+ } else {
2352
+ return this.handlePrepareError(error, coded, mode);
2353
+ }
2354
+ }
2355
+
2356
+ // Perform validation
2357
+ const result = await checker.checkCodeableConcept(issuePath, coded, abstractOk, inferSystem, mode);
2358
+
2359
+ // Add diagnostics if requested
2360
+ if (params.diagnostics) {
2361
+ result.jsonObj.parameter.push({name: 'diagnostics', valueString: this.opContext.diagnostics()});
2362
+ }
2363
+
2364
+ return result.jsonObj;
2365
+ }
2366
+
2367
+ /**
2368
+ * Get a boolean parameter value
2369
+ * @private
2370
+ */
2371
+ _getBoolParam(params, name, defaultValue) {
2372
+ if (!params?.parameter) return defaultValue;
2373
+ const p = params.parameter.find(param => param.name === name);
2374
+ if (!p) return defaultValue;
2375
+ if (p.valueBoolean !== undefined) return p.valueBoolean;
2376
+ if (p.valueString !== undefined) return p.valueString === 'true';
2377
+ return defaultValue;
2378
+ }
2379
+
2380
+ /**
2381
+ * Find a ValueSet by URL
2382
+ * @param {string} url - ValueSet URL
2383
+ * @param {string} [version] - ValueSet version
2384
+ * @returns {Object|null} ValueSet resource or null
2385
+ */
2386
+ async findValueSet(url, version = null) {
2387
+ // First check additional resources
2388
+ const found = this.findInAdditionalResources(url, version || '', 'ValueSet', false);
2389
+ if (found) {
2390
+ return found;
2391
+ }
2392
+
2393
+ // Then check provider
2394
+ return await this.provider.findValueSet(this.opContext, url, version);
2395
+ }
2396
+
2397
+ /**
2398
+ * Get display text for a code (stub implementation for doValidationCS)
2399
+ * @private
2400
+ */
2401
+ getDisplayForCode(code) {
2402
+ const displays = {
2403
+ 'male': 'Male',
2404
+ 'female': 'Female',
2405
+ 'unknown': 'Unknown',
2406
+ 'other': 'Other'
2407
+ };
2408
+ return displays[code] || code;
2409
+ }
2410
+
2411
+ /**
2412
+ * Build the validation result Parameters resource
2413
+ */
2414
+ buildValidationResult(result, message, display, coded) {
2415
+ const parameters = {
2416
+ resourceType: 'Parameters',
2417
+ parameter: [
2418
+ {name: 'result', valueBoolean: result}
2419
+ ]
2420
+ };
2421
+
2422
+ if (message) {
2423
+ parameters.parameter.push({name: 'message', valueString: message});
2424
+ }
2425
+
2426
+ if (display && result) {
2427
+ parameters.parameter.push({name: 'display', valueString: display});
2428
+ }
2429
+
2430
+ // Include the code that was validated
2431
+ if (coded.coding && coded.coding.length > 0) {
2432
+ const coding = coded.coding[0];
2433
+ if (coding.code) {
2434
+ parameters.parameter.push({name: 'code', valueCode: coding.code});
2435
+ }
2436
+ if (coding.system) {
2437
+ parameters.parameter.push({name: 'system', valueUri: coding.system});
2438
+ }
2439
+ if (coding.version) {
2440
+ parameters.parameter.push({name: 'version', valueString: coding.version});
2441
+ }
2442
+ }
2443
+
2444
+ return parameters;
2445
+ }
2446
+
2447
+ /**
2448
+ * Build an OperationOutcome
2449
+ */
2450
+ operationOutcome(severity, code, message) {
2451
+ return {
2452
+ resourceType: 'OperationOutcome',
2453
+ issue: [{
2454
+ severity,
2455
+ code,
2456
+ details: {
2457
+ text: message
2458
+ },
2459
+ diagnostics: message
2460
+ }]
2461
+ };
2462
+ }
2463
+
2464
+
2465
+ handlePrepareError(error, coded, mode) {
2466
+ let op = new OperationOutcome();
2467
+ op.addIssue(error);
2468
+ let p = new Parameters();
2469
+ p.addParamResource('issues', op.jsonObj);
2470
+ p.addParamBool('result', false);
2471
+ p.addParamStr('message', error.message);
2472
+ if (mode == 'codeableConcept') {
2473
+ p.addParam('codeableConcept', 'valueCodeableConcept', coded);
2474
+ } else if (coded.coding) {
2475
+ if (coded.coding[0].system) {
2476
+ p.addParamUri('system', coded.coding[0].system)
2477
+ }
2478
+ if (coded.coding[0].version) {
2479
+ p.addParamStr('version', coded.coding[0].version)
2480
+ }
2481
+ if (coded.coding[0].code) {
2482
+ p.addParamCode('code', coded.coding[0].code)
2483
+ }
2484
+ if (coded.coding[0].display) {
2485
+ p.addParamStr('display', coded.coding[0].display)
2486
+ }
2487
+ }
2488
+ if (error.unknownSystem) {
2489
+ p.addParamCanonical("x-caused-by-unknown-system", error.unknownSystem);
2490
+ }
2491
+ return p.jsonObj;
2492
+ }
2493
+
2494
+ isValidating() {
2495
+ return true;
2496
+ }
2497
+
2498
+ }
2499
+
2500
+ module.exports = {
2501
+ ValidateWorker,
2502
+ ValueSetChecker,
2503
+ ValidationCheckMode,
2504
+ };