@aehrc/smart-forms-renderer 1.0.0-alpha.48.dev1 → 1.0.0-alpha.49

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 (108) hide show
  1. package/lib/components/Checkbox.styles.js +11 -0
  2. package/lib/components/Checkbox.styles.js.map +1 -1
  3. package/lib/components/FormComponents/BooleanItem/BooleanField.js +4 -2
  4. package/lib/components/FormComponents/BooleanItem/BooleanField.js.map +1 -1
  5. package/lib/components/FormComponents/ChoiceItems/CheckboxFormGroup.d.ts +16 -0
  6. package/lib/components/FormComponents/ChoiceItems/CheckboxFormGroup.js +24 -0
  7. package/lib/components/FormComponents/ChoiceItems/CheckboxFormGroup.js.map +1 -0
  8. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js +6 -10
  9. package/lib/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.js.map +1 -1
  10. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxFormGroup.d.ts +16 -0
  11. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxFormGroup.js +24 -0
  12. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxFormGroup.js.map +1 -0
  13. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxGroup.d.ts +0 -0
  14. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxGroup.js +2 -0
  15. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxGroup.js.map +1 -0
  16. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxList.d.ts +0 -0
  17. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxList.js +2 -0
  18. package/lib/components/FormComponents/ChoiceItems/ChoiceCheckboxList.js.map +1 -0
  19. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js +2 -1
  20. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.js.map +1 -1
  21. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js +2 -1
  22. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.js.map +1 -1
  23. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioGroup.d.ts +16 -0
  24. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioGroup.js +29 -0
  25. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioGroup.js.map +1 -0
  26. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioSingle.js +2 -1
  27. package/lib/components/FormComponents/ChoiceItems/ChoiceRadioSingle.js.map +1 -1
  28. package/lib/components/FormComponents/ChoiceItems/RadioFormGroup.d.ts +16 -0
  29. package/lib/components/FormComponents/ChoiceItems/RadioFormGroup.js +29 -0
  30. package/lib/components/FormComponents/ChoiceItems/RadioFormGroup.js.map +1 -0
  31. package/lib/components/FormComponents/ItemParts/CheckboxFormGroup.d.ts +16 -0
  32. package/lib/components/FormComponents/ItemParts/CheckboxFormGroup.js +24 -0
  33. package/lib/components/FormComponents/ItemParts/CheckboxFormGroup.js.map +1 -0
  34. package/lib/components/FormComponents/ItemParts/CheckboxSingle.js +1 -1
  35. package/lib/components/FormComponents/ItemParts/CheckboxSingle.js.map +1 -1
  36. package/lib/components/FormComponents/ItemParts/CheckboxSingleWithOpenLabel.js +1 -1
  37. package/lib/components/FormComponents/ItemParts/CheckboxSingleWithOpenLabel.js.map +1 -1
  38. package/lib/components/FormComponents/ItemParts/RadioFormGroup.d.ts +16 -0
  39. package/lib/components/FormComponents/ItemParts/RadioFormGroup.js +29 -0
  40. package/lib/components/FormComponents/ItemParts/RadioFormGroup.js.map +1 -0
  41. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js +5 -8
  42. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.js.map +1 -1
  43. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js +2 -1
  44. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.js.map +1 -1
  45. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.js +2 -1
  46. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.js.map +1 -1
  47. package/lib/components/FormComponents/Tables/GroupTableRow.js +2 -2
  48. package/lib/components/FormComponents/Tables/GroupTableRow.js.map +1 -1
  49. package/lib/components/FormComponents/Tables/GroupTableView.js +5 -2
  50. package/lib/components/FormComponents/Tables/GroupTableView.js.map +1 -1
  51. package/lib/components/FormComponents/Tables/SelectRowButton.d.ts +1 -1
  52. package/lib/components/FormComponents/Tables/SelectRowButton.js +2 -2
  53. package/lib/components/FormComponents/Tables/SelectRowButton.js.map +1 -1
  54. package/lib/components/Radio.styles.js +11 -0
  55. package/lib/components/Radio.styles.js.map +1 -1
  56. package/lib/hooks/useAnswerOptionsToggleExpressions.d.ts +7 -0
  57. package/lib/hooks/useAnswerOptionsToggleExpressions.js +67 -0
  58. package/lib/hooks/useAnswerOptionsToggleExpressions.js.map +1 -0
  59. package/lib/interfaces/answerOptionsToggleExpression.interface.d.ts +9 -0
  60. package/lib/interfaces/answerOptionsToggleExpression.interface.js +2 -0
  61. package/lib/interfaces/answerOptionsToggleExpression.interface.js.map +1 -0
  62. package/lib/stores/extractOperationStore.d.ts +26 -0
  63. package/lib/stores/extractOperationStore.js +20 -0
  64. package/lib/stores/extractOperationStore.js.map +1 -0
  65. package/lib/templates/bloodPressureTemplate.d.ts +23 -0
  66. package/lib/templates/bloodPressureTemplate.js +80 -0
  67. package/lib/templates/bloodPressureTemplate.js.map +1 -0
  68. package/lib/tests/test-data/bloodPressureSample.d.ts +3 -0
  69. package/lib/tests/test-data/bloodPressureSample.js +250 -0
  70. package/lib/tests/test-data/bloodPressureSample.js.map +1 -0
  71. package/lib/tests/test-data/complexTemplateSample.d.ts +3 -0
  72. package/lib/tests/test-data/complexTemplateSample.js +578 -0
  73. package/lib/tests/test-data/complexTemplateSample.js.map +1 -0
  74. package/lib/utils/answerOptionsToggleExpressions.d.ts +24 -0
  75. package/lib/utils/answerOptionsToggleExpressions.js +144 -0
  76. package/lib/utils/answerOptionsToggleExpressions.js.map +1 -0
  77. package/lib/utils/calculatedExpression.js +8 -5
  78. package/lib/utils/calculatedExpression.js.map +1 -1
  79. package/lib/utils/checkbox.d.ts +2 -0
  80. package/lib/utils/checkbox.js +6 -0
  81. package/lib/utils/checkbox.js.map +1 -0
  82. package/lib/utils/extractTemplate.d.ts +44 -0
  83. package/lib/utils/extractTemplate.js +809 -0
  84. package/lib/utils/extractTemplate.js.map +1 -0
  85. package/lib/utils/questionnaireStoreUtils/extractAnswerOptionsToggleExpressions.d.ts +3 -0
  86. package/lib/utils/questionnaireStoreUtils/extractAnswerOptionsToggleExpressions.js +6 -0
  87. package/lib/utils/questionnaireStoreUtils/extractAnswerOptionsToggleExpressions.js.map +1 -0
  88. package/lib/utils/templateMatching.d.ts +15 -0
  89. package/lib/utils/templateMatching.js +62 -0
  90. package/lib/utils/templateMatching.js.map +1 -0
  91. package/package.json +2 -2
  92. package/src/components/Checkbox.styles.ts +14 -0
  93. package/src/components/FormComponents/BooleanItem/BooleanField.tsx +7 -0
  94. package/src/components/FormComponents/ChoiceItems/ChoiceAutocompleteField.tsx +6 -10
  95. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerOptionFields.tsx +2 -0
  96. package/src/components/FormComponents/ChoiceItems/ChoiceRadioAnswerValueSetFields.tsx +2 -0
  97. package/src/components/FormComponents/ChoiceItems/ChoiceRadioSingle.tsx +2 -1
  98. package/src/components/FormComponents/ItemParts/CheckboxSingle.tsx +3 -0
  99. package/src/components/FormComponents/ItemParts/CheckboxSingleWithOpenLabel.tsx +3 -0
  100. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteField.tsx +5 -8
  101. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerOptionFields.tsx +2 -0
  102. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceRadioAnswerValueSetFields.tsx +2 -0
  103. package/src/components/FormComponents/Tables/GroupTableRow.tsx +2 -2
  104. package/src/components/FormComponents/Tables/GroupTableView.tsx +14 -6
  105. package/src/components/FormComponents/Tables/SelectRowButton.tsx +6 -3
  106. package/src/components/Radio.styles.tsx +13 -0
  107. package/src/utils/calculatedExpression.ts +13 -5
  108. package/src/utils/checkbox.ts +7 -0
@@ -0,0 +1,809 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import fhirpath from 'fhirpath';
11
+ import fhirpath_r4_model from 'fhirpath/fhir-context/r4';
12
+ import { findMatchingItem, FHIR_TEMPLATE_EXTRACT_EXTENSION } from './templateMatching';
13
+ const FHIR_TEMPLATE_REFERENCE_EXTENSION = 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-templateReference';
14
+ const TEMPLATE_EXTRACT_VALUE_EXTENSION = 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-templateExtractValue';
15
+ function evaluateTemplateExpression(questionnaireResponse, expression, context) {
16
+ try {
17
+ // If we have a context, use it as the starting point for evaluation
18
+ const evaluationContext = context || questionnaireResponse;
19
+ // Handle special cases for nested structures
20
+ if (expression.includes('item.where')) {
21
+ // Process nested item expressions
22
+ const result = fhirpath.evaluate(evaluationContext, expression, {}, // Empty context object
23
+ fhirpath_r4_model, {
24
+ async: false
25
+ });
26
+ if (Array.isArray(result)) {
27
+ if (result.length === 0)
28
+ return null;
29
+ if (result.length === 1)
30
+ return result[0];
31
+ return result;
32
+ }
33
+ return result;
34
+ }
35
+ // Handle direct value references
36
+ const result = fhirpath.evaluate(evaluationContext, expression, {}, // Empty context object
37
+ fhirpath_r4_model, {
38
+ async: false
39
+ });
40
+ return result;
41
+ }
42
+ catch (error) {
43
+ console.error('Error evaluating FHIRPath expression:', error);
44
+ return null;
45
+ }
46
+ }
47
+ function findNestedItem(items, linkId) {
48
+ if (!items)
49
+ return null;
50
+ for (const item of items) {
51
+ if (item.linkId === linkId) {
52
+ return item;
53
+ }
54
+ if (item.item) {
55
+ const nested = findNestedItem(item.item, linkId);
56
+ if (nested)
57
+ return nested;
58
+ }
59
+ }
60
+ return null;
61
+ }
62
+ function getNestedAnswerValue(response, linkId, parentLinkId) {
63
+ var _a;
64
+ console.log(`Looking for value at linkId: ${linkId} (parent: ${parentLinkId || 'none'})`);
65
+ // More flexible recursive item finder
66
+ const findItem = (items, currentLevel = 0) => {
67
+ if (!items)
68
+ return null;
69
+ for (const item of items) {
70
+ console.log(`${' '.repeat(currentLevel * 2)}Checking item: ${item.linkId}`);
71
+ // Direct match
72
+ if (item.linkId === linkId) {
73
+ console.log(`${' '.repeat(currentLevel * 2)}✅ Found direct match: ${item.linkId}`);
74
+ return item;
75
+ }
76
+ // Parent match, check children
77
+ if (parentLinkId && item.linkId === parentLinkId && item.item) {
78
+ console.log(`${' '.repeat(currentLevel * 2)}Found parent: ${item.linkId}, checking children...`);
79
+ for (const childItem of item.item) {
80
+ if (childItem.linkId === linkId) {
81
+ console.log(`${' '.repeat(currentLevel * 2)}✅ Found child match: ${childItem.linkId}`);
82
+ return childItem;
83
+ }
84
+ }
85
+ }
86
+ // Recursive search in children
87
+ if (item.item) {
88
+ const foundItem = findItem(item.item, currentLevel + 1);
89
+ if (foundItem)
90
+ return foundItem;
91
+ }
92
+ }
93
+ return null;
94
+ };
95
+ const item = findItem(response.item);
96
+ if (!item || !item.answer || item.answer.length === 0) {
97
+ console.log(`❌ No answer found for linkId: ${linkId}`);
98
+ return null;
99
+ }
100
+ const answer = item.answer[0];
101
+ // Extract the value based on its type
102
+ if (answer.valueDecimal !== undefined)
103
+ return answer.valueDecimal;
104
+ if (answer.valueInteger !== undefined)
105
+ return answer.valueInteger;
106
+ if (answer.valueString !== undefined)
107
+ return answer.valueString;
108
+ if (answer.valueBoolean !== undefined)
109
+ return answer.valueBoolean;
110
+ if (((_a = answer.valueQuantity) === null || _a === void 0 ? void 0 : _a.value) !== undefined)
111
+ return answer.valueQuantity.value;
112
+ console.log(`❌ No supported value type found in answer for linkId: ${linkId}`);
113
+ return null;
114
+ }
115
+ function hasTemplateExtractExtension(item) {
116
+ var _a;
117
+ // Enhanced detection with detailed logging
118
+ console.log(`Checking for template extraction extension in item with linkId: ${item.linkId || 'root questionnaire'}`);
119
+ if (!item.extension || item.extension.length === 0) {
120
+ console.log(`No extensions found for item ${item.linkId || 'root questionnaire'}`);
121
+ return false;
122
+ }
123
+ for (const ext of item.extension) {
124
+ console.log(`Examining extension with URL: ${ext.url}`);
125
+ if (ext.url === FHIR_TEMPLATE_EXTRACT_EXTENSION) {
126
+ // Check for direct boolean value
127
+ if (ext.valueBoolean !== undefined) {
128
+ console.log(`Found template extraction extension with valueBoolean: ${ext.valueBoolean}`);
129
+ return ext.valueBoolean;
130
+ }
131
+ // Check for nested template reference
132
+ if (ext.extension) {
133
+ for (const subExt of ext.extension) {
134
+ if (subExt.url === 'template' && ((_a = subExt.valueReference) === null || _a === void 0 ? void 0 : _a.reference)) {
135
+ console.log(`Found template reference: ${subExt.valueReference.reference}`);
136
+ return true;
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+ /**
145
+ * Processes datetime extraction from templates, handling both static values and expressions
146
+ * @param template The template containing datetime fields
147
+ * @param response The questionnaire response to extract values from
148
+ * @returns An ISO formatted datetime string
149
+ */
150
+ function processDateTimeExtraction(template, response, debugInfo) {
151
+ var _a, _b;
152
+ // Check if we have an effectiveDateTime with extraction extension
153
+ const effectiveDateTime = template.effectiveDateTime;
154
+ const effectiveDateTimeExt = (_b = (_a = template._effectiveDateTime) === null || _a === void 0 ? void 0 : _a.extension) === null || _b === void 0 ? void 0 : _b.find((ext) => ext.url === TEMPLATE_EXTRACT_VALUE_EXTENSION);
155
+ // Initialize datetime debug info
156
+ debugInfo.valueProcessing.datetime = {
157
+ source: 'fallback',
158
+ value: ''
159
+ };
160
+ if (effectiveDateTimeExt === null || effectiveDateTimeExt === void 0 ? void 0 : effectiveDateTimeExt.valueString) {
161
+ // Handle specific extraction expressions
162
+ if (effectiveDateTimeExt.valueString === 'now()') {
163
+ // Use current date/time
164
+ const now = new Date().toISOString();
165
+ console.log(`Processing datetime with now() function: ${now}`);
166
+ // Update datetime debug info
167
+ debugInfo.valueProcessing.datetime = {
168
+ source: 'dynamic',
169
+ expression: 'now()',
170
+ value: now,
171
+ originalValue: effectiveDateTime
172
+ };
173
+ return now;
174
+ }
175
+ else {
176
+ // Try to evaluate as a FHIRPath expression
177
+ const extractedDateTime = evaluateTemplateExpression(response, effectiveDateTimeExt.valueString);
178
+ if (extractedDateTime) {
179
+ console.log(`Extracted datetime using expression: ${extractedDateTime}`);
180
+ // Update datetime debug info
181
+ debugInfo.valueProcessing.datetime = {
182
+ source: 'dynamic',
183
+ expression: effectiveDateTimeExt.valueString,
184
+ value: extractedDateTime,
185
+ originalValue: effectiveDateTime
186
+ };
187
+ return extractedDateTime;
188
+ }
189
+ }
190
+ }
191
+ // Default to template's static value if available
192
+ if (effectiveDateTime) {
193
+ console.log(`Using template's static datetime: ${effectiveDateTime}`);
194
+ // Update datetime debug info
195
+ debugInfo.valueProcessing.datetime = {
196
+ source: 'static',
197
+ value: effectiveDateTime
198
+ };
199
+ return effectiveDateTime;
200
+ }
201
+ // Final fallback to current date/time
202
+ const fallbackTime = new Date().toISOString();
203
+ console.log(`No datetime information found, using current time: ${fallbackTime}`);
204
+ // Update datetime debug info
205
+ debugInfo.valueProcessing.datetime = {
206
+ source: 'fallback',
207
+ value: fallbackTime
208
+ };
209
+ return fallbackTime;
210
+ }
211
+ export function extractTemplateBased(questionnaire, response) {
212
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
213
+ return __awaiter(this, void 0, void 0, function* () {
214
+ const debugInfo = {
215
+ contentAnalysis: {
216
+ detectedTemplates: [],
217
+ confidence: 'Valid',
218
+ patterns: []
219
+ },
220
+ fieldMapping: {
221
+ mappedFields: {},
222
+ assumptions: [],
223
+ alternatives: []
224
+ },
225
+ valueProcessing: {
226
+ values: {},
227
+ transformations: [],
228
+ qualityChecks: []
229
+ },
230
+ resultGeneration: {
231
+ status: 'Pending',
232
+ observations: []
233
+ }
234
+ };
235
+ console.log('=== Template Extraction Debug ===');
236
+ console.log('Stage 1: Initial Validation');
237
+ // Enhanced validation with more detailed error reporting
238
+ if (!questionnaire) {
239
+ console.log('❌ Failed: Questionnaire is undefined or null');
240
+ debugInfo.contentAnalysis.confidence = 'Invalid';
241
+ return {
242
+ result: null,
243
+ error: 'Missing questionnaire',
244
+ debugInfo
245
+ };
246
+ }
247
+ if (!questionnaire.item) {
248
+ console.log('❌ Failed: Questionnaire has no items');
249
+ debugInfo.contentAnalysis.confidence = 'Invalid';
250
+ return {
251
+ result: null,
252
+ error: 'Questionnaire has no items',
253
+ debugInfo
254
+ };
255
+ }
256
+ if (!questionnaire.contained || questionnaire.contained.length === 0) {
257
+ console.log('❌ Failed: Questionnaire has no contained resources for templates');
258
+ debugInfo.contentAnalysis.confidence = 'Invalid';
259
+ return {
260
+ result: null,
261
+ error: 'Questionnaire has no contained resources for templates',
262
+ debugInfo
263
+ };
264
+ }
265
+ if (!response.item) {
266
+ console.log('❌ Failed: Response has no items');
267
+ debugInfo.contentAnalysis.confidence = 'Invalid';
268
+ return {
269
+ result: null,
270
+ error: 'Response has no items',
271
+ debugInfo
272
+ };
273
+ }
274
+ console.log('✅ Passed: Required items present');
275
+ // Check for template extraction extension at questionnaire or item level
276
+ console.log('\nStage 2: Template Extraction Extension Check');
277
+ // Enhanced template detection with recursive item checking
278
+ const hasTemplateExtract = hasTemplateExtractExtension(questionnaire);
279
+ let itemsWithTemplates = [];
280
+ const checkItemsForTemplates = (items) => {
281
+ let found = false;
282
+ for (const item of items) {
283
+ if (hasTemplateExtractExtension(item)) {
284
+ found = true;
285
+ itemsWithTemplates.push(item.linkId);
286
+ }
287
+ if (item.item && checkItemsForTemplates(item.item)) {
288
+ found = true;
289
+ }
290
+ }
291
+ return found;
292
+ };
293
+ const hasItemTemplates = checkItemsForTemplates(questionnaire.item);
294
+ if (!hasTemplateExtract && !hasItemTemplates) {
295
+ console.log('❌ Failed: No template extraction extension found');
296
+ debugInfo.contentAnalysis.confidence = 'Invalid';
297
+ debugInfo.contentAnalysis.detectedTemplates.push('No template type detected');
298
+ // Enhanced debug information for template detection failure
299
+ if (questionnaire.extension && questionnaire.extension.length > 0) {
300
+ const urls = questionnaire.extension.map(e => e.url).join(', ');
301
+ debugInfo.fieldMapping.assumptions.push(`Found extensions but none match template extraction: ${urls}`);
302
+ }
303
+ else {
304
+ debugInfo.fieldMapping.assumptions.push('No extensions found at questionnaire level');
305
+ }
306
+ if (itemsWithTemplates.length > 0) {
307
+ debugInfo.fieldMapping.assumptions.push(`Found items with extensions: ${itemsWithTemplates.join(', ')}`);
308
+ }
309
+ return {
310
+ result: null,
311
+ error: 'Questionnaire is not configured for template extraction',
312
+ debugInfo
313
+ };
314
+ }
315
+ if (hasTemplateExtract) {
316
+ console.log('✅ Passed: Template extraction extension found at questionnaire level');
317
+ }
318
+ if (hasItemTemplates) {
319
+ console.log(`✅ Passed: Template extraction extensions found at item level: ${itemsWithTemplates.join(', ')}`);
320
+ }
321
+ const templates = questionnaire.contained;
322
+ console.log('\nStage 3: Template Analysis');
323
+ console.log(`Found ${templates.length} templates:`);
324
+ // Enhanced template analysis
325
+ const observationTemplates = templates.filter(t => t.resourceType === 'Observation');
326
+ const patientTemplates = templates.filter(t => t.resourceType === 'Patient');
327
+ const otherTemplates = templates.filter(t => !['Observation', 'Patient'].includes(t.resourceType));
328
+ console.log(`- ${observationTemplates.length} Observation templates`);
329
+ console.log(`- ${patientTemplates.length} Patient templates`);
330
+ console.log(`- ${otherTemplates.length} Other templates`);
331
+ templates.forEach(template => {
332
+ const templateId = template.id || 'unnamed';
333
+ console.log(`- ${template.resourceType}: ${templateId}`);
334
+ debugInfo.contentAnalysis.detectedTemplates.push(templateId);
335
+ });
336
+ const observations = [];
337
+ // Initialize field mapping with template information
338
+ console.log('\nStage 4: Field Mapping');
339
+ debugInfo.fieldMapping.mappedFields = templates.reduce((acc, template) => {
340
+ var _a, _b, _c, _d;
341
+ if (template.resourceType === 'Observation') {
342
+ const code = (_c = (_b = (_a = template.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.code;
343
+ if (code) {
344
+ // Skip the boolean observation for now
345
+ if (template._valueBoolean)
346
+ return acc;
347
+ // Find the corresponding item in the questionnaire using the enhanced matcher
348
+ const item = findMatchingItem(questionnaire.item, template.id || 'unknown', template.resourceType, (_d = template.code) === null || _d === void 0 ? void 0 : _d.coding);
349
+ if (!item) {
350
+ console.log(`❌ Failed to find corresponding item in questionnaire for template: ${template.id}`);
351
+ debugInfo.valueProcessing.qualityChecks.push({
352
+ check: `Process ${template.id || 'unknown'}`,
353
+ passed: false,
354
+ message: 'Failed to find corresponding item in questionnaire'
355
+ });
356
+ return acc;
357
+ }
358
+ // Enhanced path detection with better support for different questionnaire structures
359
+ let valuePath = "";
360
+ // Check for parent hierarchy to build proper path
361
+ const buildPath = (items, targetLinkId, path = "") => {
362
+ if (!items)
363
+ return "";
364
+ for (const i of items) {
365
+ if (i.linkId === targetLinkId)
366
+ return path ? `${path}.item.where(linkId='${targetLinkId}')` : `item.where(linkId='${targetLinkId}')`;
367
+ if (i.item) {
368
+ const newPath = path ? `${path}.item.where(linkId='${i.linkId}')` : `item.where(linkId='${i.linkId}')`;
369
+ const result = buildPath(i.item, targetLinkId, newPath);
370
+ if (result)
371
+ return result;
372
+ }
373
+ }
374
+ return "";
375
+ };
376
+ valuePath = buildPath(questionnaire.item, item.linkId);
377
+ if (!valuePath) {
378
+ valuePath = `item.where(linkId='${item.linkId}')`;
379
+ }
380
+ // Add answer type based on item type
381
+ switch (item.type) {
382
+ case 'decimal':
383
+ valuePath += '.answer.valueDecimal';
384
+ break;
385
+ case 'integer':
386
+ valuePath += '.answer.valueInteger';
387
+ break;
388
+ case 'boolean':
389
+ valuePath += '.answer.valueBoolean';
390
+ break;
391
+ case 'string':
392
+ valuePath += '.answer.valueString';
393
+ break;
394
+ case 'quantity':
395
+ valuePath += '.answer.valueQuantity.value';
396
+ break;
397
+ default:
398
+ valuePath += '.answer.value';
399
+ }
400
+ acc[code] = {
401
+ templateId: template.id,
402
+ type: template.resourceType,
403
+ valuePath: valuePath,
404
+ itemType: item.type,
405
+ itemLinkId: item.linkId,
406
+ itemText: item.text || "No text"
407
+ };
408
+ console.log(`Mapped field: ${code} -> ${template.id} (${valuePath})`);
409
+ }
410
+ }
411
+ return acc;
412
+ }, {});
413
+ // Add relevant assumptions about the mapping based on found patterns
414
+ if (Object.keys(debugInfo.fieldMapping.mappedFields).length === 0) {
415
+ debugInfo.fieldMapping.assumptions.push('No fields could be mapped between templates and questionnaire items');
416
+ }
417
+ else {
418
+ debugInfo.fieldMapping.assumptions.push(`Successfully mapped ${Object.keys(debugInfo.fieldMapping.mappedFields).length} fields`);
419
+ }
420
+ // Check for specific patterns in the template (like height, weight, blood pressure)
421
+ const hasHeight = observationTemplates.some(t => { var _a, _b; return (_b = (_a = t.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '8302-2' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('height')); }); });
422
+ const hasWeight = observationTemplates.some(t => { var _a, _b; return (_b = (_a = t.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '29463-7' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('weight')); }); });
423
+ // More precise BP detection to avoid false positives
424
+ const hasBpLoinc = observationTemplates.some(t => { var _a, _b; return (_b = (_a = t.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => c.code === '85354-9'); } // Blood pressure panel with all children optional
425
+ );
426
+ const hasSystolicComponent = observationTemplates.some(t => {
427
+ var _a;
428
+ return (_a = t.component) === null || _a === void 0 ? void 0 : _a.some(comp => { var _a, _b; return (_b = (_a = comp.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '8480-6' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('systolic')); }); });
429
+ });
430
+ const hasDiastolicComponent = observationTemplates.some(t => {
431
+ var _a;
432
+ return (_a = t.component) === null || _a === void 0 ? void 0 : _a.some(comp => { var _a, _b; return (_b = (_a = comp.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '8462-4' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('diastolic')); }); });
433
+ });
434
+ // Separate standalone templates with BP codes
435
+ const hasSystolicTemplate = observationTemplates.some(t => { var _a, _b; return (_b = (_a = t.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '8480-6' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('systolic')); }); });
436
+ const hasDiastolicTemplate = observationTemplates.some(t => { var _a, _b; return (_b = (_a = t.code) === null || _a === void 0 ? void 0 : _a.coding) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return c.code === '8462-4' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('diastolic')); }); });
437
+ // Content-driven pattern detection
438
+ // Instead of fixed assumptions, detect patterns dynamically based on content
439
+ const patterns = [];
440
+ const assumptions = [];
441
+ if (observationTemplates.length > 0) {
442
+ assumptions.push(`Found ${observationTemplates.length} observation templates`);
443
+ }
444
+ if (hasHeight) {
445
+ patterns.push('Height Measurement');
446
+ if (hasWeight) {
447
+ // Both height and weight together form a pattern
448
+ assumptions.push('Detected height and weight template pattern');
449
+ }
450
+ else {
451
+ // Just height alone
452
+ assumptions.push('Detected height measurement template');
453
+ }
454
+ }
455
+ else if (hasWeight) {
456
+ // Just weight alone
457
+ patterns.push('Weight Measurement');
458
+ assumptions.push('Detected weight measurement template');
459
+ }
460
+ // Only detect BP if we have a proper complete BP pattern
461
+ const isCompleteBpPattern = hasBpLoinc ||
462
+ (hasSystolicComponent && hasDiastolicComponent) ||
463
+ (hasSystolicTemplate && hasDiastolicTemplate);
464
+ if (isCompleteBpPattern) {
465
+ patterns.push('Blood Pressure Measurement');
466
+ assumptions.push('Detected complete blood pressure template pattern');
467
+ }
468
+ else if (hasSystolicTemplate && !hasDiastolicTemplate) {
469
+ // Just systolic without diastolic - not a complete BP pattern
470
+ patterns.push('Systolic Measurement');
471
+ assumptions.push('Detected systolic pressure template (incomplete BP pattern)');
472
+ }
473
+ else if (!hasSystolicTemplate && hasDiastolicTemplate) {
474
+ // Just diastolic without systolic - not a complete BP pattern
475
+ patterns.push('Diastolic Measurement');
476
+ assumptions.push('Detected diastolic pressure template (incomplete BP pattern)');
477
+ }
478
+ // Add the detected patterns to debug info
479
+ debugInfo.contentAnalysis.patterns.push(...patterns);
480
+ // Add the assumptions to debug info
481
+ debugInfo.fieldMapping.assumptions.push(...assumptions);
482
+ // Update debug info with resource types
483
+ debugInfo.contentAnalysis.patterns.push(...templates.map(template => `${template.resourceType}: ${template.id || 'unnamed'}`));
484
+ console.log('\nStage 5: Template Processing');
485
+ // Process each template
486
+ for (const template of templates) {
487
+ try {
488
+ if (template.resourceType === 'Observation') {
489
+ const templateId = template.id || 'unnamed';
490
+ console.log(`\nProcessing template: ${templateId}`);
491
+ // Skip the boolean observation for now
492
+ if (template._valueBoolean)
493
+ continue;
494
+ const observation = Object.assign(Object.assign({}, template), { id: undefined // Remove template ID
495
+ });
496
+ // Find the corresponding item in the questionnaire using the enhanced matcher
497
+ const item = findMatchingItem(questionnaire.item, template.id || 'unknown', template.resourceType, (_a = template.code) === null || _a === void 0 ? void 0 : _a.coding);
498
+ if (!item) {
499
+ console.log(`❌ Failed to find corresponding item in questionnaire for template: ${template.id}`);
500
+ debugInfo.valueProcessing.qualityChecks.push({
501
+ check: `Process ${template.id || 'unknown'}`,
502
+ passed: false,
503
+ message: 'Failed to find corresponding item in questionnaire'
504
+ });
505
+ continue;
506
+ }
507
+ // Process datetime values for the observation
508
+ const originalDateTime = template.effectiveDateTime;
509
+ observation.effectiveDateTime = processDateTimeExtraction(template, response, debugInfo);
510
+ // Add information to debug info
511
+ debugInfo.valueProcessing.transformations.push(`Set effectiveDateTime to ${observation.effectiveDateTime} for ${templateId}`);
512
+ // Remove the extraction extension since it's been processed
513
+ if (observation._effectiveDateTime) {
514
+ delete observation._effectiveDateTime;
515
+ }
516
+ // Process value extraction with improved nested handling
517
+ if (template.valueQuantity) {
518
+ // First try direct extension on valueQuantity (common in test files)
519
+ let valueExt = (_b = template.valueQuantity.extension) === null || _b === void 0 ? void 0 : _b.find((ext) => ext.url === TEMPLATE_EXTRACT_VALUE_EXTENSION);
520
+ // If not found, try the nested structure from HL7 SDC examples
521
+ if (!valueExt && ((_c = template.valueQuantity._value) === null || _c === void 0 ? void 0 : _c.extension)) {
522
+ valueExt = template.valueQuantity._value.extension.find((ext) => ext.url === TEMPLATE_EXTRACT_VALUE_EXTENSION);
523
+ console.log('Using nested _value extension structure from HL7 SDC example');
524
+ }
525
+ if (valueExt === null || valueExt === void 0 ? void 0 : valueExt.valueString) {
526
+ console.log(`Extracting value with expression: ${valueExt.valueString}`);
527
+ let value;
528
+ // Handle direct answer value references
529
+ if (valueExt.valueString.includes('answer.value')) {
530
+ value = getNestedAnswerValue(response, item.linkId);
531
+ if (value !== null) {
532
+ // Improved unit detection and value conversion based on context
533
+ const isHeightTemplate = (_e = (_d = template.code) === null || _d === void 0 ? void 0 : _d.coding) === null || _e === void 0 ? void 0 : _e.some(c => { var _a; return c.code === '8302-2' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('height')); });
534
+ // Check if a unit conversion is needed
535
+ if (isHeightTemplate) {
536
+ console.log(`Processing height value: ${value}`);
537
+ // Determine the source unit from the questionnaire item
538
+ const unitExtension = (_f = item.extension) === null || _f === void 0 ? void 0 : _f.find(ext => ext.url === 'http://hl7.org/fhir/StructureDefinition/questionnaire-unit');
539
+ const sourceUnit = ((_g = unitExtension === null || unitExtension === void 0 ? void 0 : unitExtension.valueCoding) === null || _g === void 0 ? void 0 : _g.code) || 'm';
540
+ // Extract target unit from template
541
+ const targetUnit = template.valueQuantity.unit || 'cm';
542
+ // Intelligence for unit conversion
543
+ if (sourceUnit === 'm' && targetUnit === 'cm') {
544
+ // Smart unit conversion - only apply if the value looks like meters
545
+ if (value < 3) {
546
+ const originalValue = value;
547
+ value = value * 100;
548
+ console.log(`Converting height from ${originalValue}m to ${value}cm`);
549
+ debugInfo.valueProcessing.transformations.push(`Converted height from ${originalValue}m to ${value}cm for ${templateId}`);
550
+ }
551
+ else {
552
+ // Value is likely already in cm
553
+ console.log(`Height value ${value} appears to already be in cm, no conversion needed`);
554
+ debugInfo.valueProcessing.transformations.push(`Height value ${value} appears to already be in cm, no conversion needed for ${templateId}`);
555
+ }
556
+ }
557
+ }
558
+ else {
559
+ // Not a height template, just extract the value
560
+ debugInfo.valueProcessing.transformations.push(`Extracted value ${value} for ${templateId}`);
561
+ }
562
+ observation.valueQuantity = {
563
+ value: value,
564
+ unit: template.valueQuantity.unit,
565
+ system: template.valueQuantity.system,
566
+ code: template.valueQuantity.code
567
+ };
568
+ debugInfo.valueProcessing.values[templateId] = value;
569
+ console.log(`✅ Value extracted: ${value}`);
570
+ // Enhanced quality checks based on value type
571
+ if (isHeightTemplate) {
572
+ const inReasonableRange = value > 30 && value < 250;
573
+ debugInfo.valueProcessing.qualityChecks.push({
574
+ check: `Height value in reasonable range (${value}cm)`,
575
+ passed: inReasonableRange,
576
+ message: inReasonableRange
577
+ ? 'Height within expected range'
578
+ : 'Height outside normal range, verify input'
579
+ });
580
+ }
581
+ else if ((_j = (_h = template.code) === null || _h === void 0 ? void 0 : _h.coding) === null || _j === void 0 ? void 0 : _j.some(c => { var _a; return c.code === '29463-7' || ((_a = c.display) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('weight')); })) {
582
+ const inReasonableRange = value > 0.1 && value < 300;
583
+ debugInfo.valueProcessing.qualityChecks.push({
584
+ check: `Weight value in reasonable range (${value}kg)`,
585
+ passed: inReasonableRange,
586
+ message: inReasonableRange
587
+ ? 'Weight within expected range'
588
+ : 'Weight outside normal range, verify input'
589
+ });
590
+ }
591
+ debugInfo.valueProcessing.qualityChecks.push({
592
+ check: `Process ${templateId}`,
593
+ passed: true,
594
+ message: 'Successfully processed observation'
595
+ });
596
+ }
597
+ else {
598
+ console.log('❌ Failed to extract value');
599
+ debugInfo.valueProcessing.qualityChecks.push({
600
+ check: `Process ${templateId}`,
601
+ passed: false,
602
+ message: 'Failed to extract value from questionnaire response'
603
+ });
604
+ continue; // Skip this observation if value extraction failed
605
+ }
606
+ }
607
+ else {
608
+ // Handle complex FHIRPath expressions
609
+ value = evaluateTemplateExpression(response, valueExt.valueString);
610
+ if (value !== null) {
611
+ observation.valueQuantity = {
612
+ value: value,
613
+ unit: template.valueQuantity.unit,
614
+ system: template.valueQuantity.system,
615
+ code: template.valueQuantity.code
616
+ };
617
+ debugInfo.valueProcessing.values[templateId] = value;
618
+ debugInfo.valueProcessing.transformations.push(`Extracted value ${value} for ${templateId} using expression`);
619
+ console.log(`✅ Value extracted with expression: ${value}`);
620
+ debugInfo.valueProcessing.qualityChecks.push({
621
+ check: `Process ${templateId}`,
622
+ passed: true,
623
+ message: 'Successfully processed observation'
624
+ });
625
+ }
626
+ else {
627
+ console.log('❌ Failed to extract value with expression');
628
+ debugInfo.valueProcessing.qualityChecks.push({
629
+ check: `Process ${templateId}`,
630
+ passed: false,
631
+ message: 'Failed to extract value using expression'
632
+ });
633
+ continue;
634
+ }
635
+ }
636
+ }
637
+ else {
638
+ console.log('❌ No template extraction value extension found');
639
+ debugInfo.valueProcessing.qualityChecks.push({
640
+ check: `Process ${templateId}`,
641
+ passed: false,
642
+ message: 'No template extraction value extension found'
643
+ });
644
+ continue;
645
+ }
646
+ }
647
+ else if (template._valueBoolean) {
648
+ // Handle boolean observations
649
+ console.log('Processing boolean observation template');
650
+ // Get the template extraction expression from the boolean extension
651
+ const booleanExt = (_l = (_k = template._valueBoolean) === null || _k === void 0 ? void 0 : _k.extension) === null || _l === void 0 ? void 0 : _l.find((ext) => ext.url === TEMPLATE_EXTRACT_VALUE_EXTENSION);
652
+ if (!(booleanExt === null || booleanExt === void 0 ? void 0 : booleanExt.valueString)) {
653
+ console.log('❌ No template extraction value extension found for boolean value');
654
+ debugInfo.valueProcessing.qualityChecks.push({
655
+ check: `Process ${templateId}`,
656
+ passed: false,
657
+ message: 'No template extraction value extension found for boolean value'
658
+ });
659
+ continue;
660
+ }
661
+ console.log(`Boolean extraction expression: ${booleanExt.valueString}`);
662
+ // Use the extraction expression
663
+ if (booleanExt.valueString.includes('answer.value')) {
664
+ const boolValue = getNestedAnswerValue(response, item.linkId);
665
+ if (boolValue !== null) {
666
+ observation.valueBoolean = boolValue === true || boolValue === 'true';
667
+ debugInfo.valueProcessing.values[templateId] = boolValue;
668
+ debugInfo.valueProcessing.transformations.push(`Extracted boolean value ${boolValue} for ${templateId}`);
669
+ console.log(`✅ Boolean value extracted: ${boolValue}`);
670
+ debugInfo.valueProcessing.qualityChecks.push({
671
+ check: `Process ${templateId}`,
672
+ passed: true,
673
+ message: 'Successfully processed boolean observation'
674
+ });
675
+ }
676
+ else {
677
+ console.log('❌ Failed to extract boolean value');
678
+ debugInfo.valueProcessing.qualityChecks.push({
679
+ check: `Process ${templateId}`,
680
+ passed: false,
681
+ message: 'Failed to extract boolean value from questionnaire response'
682
+ });
683
+ continue;
684
+ }
685
+ }
686
+ else {
687
+ // Handle complex FHIRPath expressions
688
+ const boolValue = evaluateTemplateExpression(response, booleanExt.valueString);
689
+ if (boolValue !== null) {
690
+ observation.valueBoolean = boolValue === true || boolValue === 'true';
691
+ debugInfo.valueProcessing.values[templateId] = boolValue;
692
+ debugInfo.valueProcessing.transformations.push(`Extracted boolean value ${boolValue} for ${templateId} using expression`);
693
+ console.log(`✅ Boolean value extracted with expression: ${boolValue}`);
694
+ debugInfo.valueProcessing.qualityChecks.push({
695
+ check: `Process ${templateId}`,
696
+ passed: true,
697
+ message: 'Successfully processed boolean observation'
698
+ });
699
+ }
700
+ else {
701
+ console.log('❌ Failed to extract boolean value with expression');
702
+ debugInfo.valueProcessing.qualityChecks.push({
703
+ check: `Process ${templateId}`,
704
+ passed: false,
705
+ message: 'Failed to extract boolean value using expression'
706
+ });
707
+ continue;
708
+ }
709
+ }
710
+ }
711
+ else {
712
+ console.log('❌ Template has unsupported value type');
713
+ debugInfo.valueProcessing.qualityChecks.push({
714
+ check: `Process ${templateId}`,
715
+ passed: false,
716
+ message: 'Template has unsupported value type'
717
+ });
718
+ continue;
719
+ }
720
+ observations.push(observation);
721
+ }
722
+ }
723
+ catch (error) {
724
+ console.error(`Error processing template ${template.id}:`, error);
725
+ debugInfo.valueProcessing.qualityChecks.push({
726
+ check: `Process ${template.id || 'unknown'}`,
727
+ passed: false,
728
+ message: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`
729
+ });
730
+ }
731
+ }
732
+ // Stage 6: Generate result
733
+ if (observations.length > 0) {
734
+ debugInfo.resultGeneration.status = 'Success';
735
+ debugInfo.resultGeneration.observations = observations;
736
+ console.log(`✅ Successfully extracted ${observations.length} observations`);
737
+ }
738
+ else {
739
+ debugInfo.resultGeneration.status = 'Failed';
740
+ debugInfo.resultGeneration.warnings = ['No observations could be extracted'];
741
+ console.log('❌ No observations could be extracted');
742
+ }
743
+ return {
744
+ result: observations.length > 0 ? observations : null,
745
+ error: observations.length === 0 ? 'No observations could be extracted' : null,
746
+ debugInfo
747
+ };
748
+ });
749
+ }
750
+ export function mapQItemsTemplate(questionnaire) {
751
+ var _a, _b, _c, _d, _e;
752
+ if (!questionnaire.item || questionnaire.item.length === 0) {
753
+ return {};
754
+ }
755
+ const initialExtension = (_a = questionnaire.extension) === null || _a === void 0 ? void 0 : _a.find((e) => e.url === FHIR_TEMPLATE_EXTRACT_EXTENSION);
756
+ const templateReference = (_c = (_b = questionnaire.extension) === null || _b === void 0 ? void 0 : _b.find((e) => e.url === FHIR_TEMPLATE_REFERENCE_EXTENSION)) === null || _c === void 0 ? void 0 : _c.valueString;
757
+ const initialTemplateMap = {
758
+ [(_d = questionnaire.id) !== null && _d !== void 0 ? _d : 'root']: {
759
+ extractable: (_e = initialExtension === null || initialExtension === void 0 ? void 0 : initialExtension.valueBoolean) !== null && _e !== void 0 ? _e : false,
760
+ templateReference
761
+ }
762
+ };
763
+ transverseQuestionnaire(questionnaire, mapQItemsTemplateRecursive, initialTemplateMap);
764
+ return initialTemplateMap;
765
+ }
766
+ function mapQItemsTemplateRecursive(qItem, root, parent, qItemTemplateMap) {
767
+ var _a, _b, _c, _d, _e, _f;
768
+ if (!qItemTemplateMap)
769
+ return;
770
+ if (!qItemTemplateMap[qItem.linkId]) {
771
+ qItemTemplateMap[qItem.linkId] = { extractable: false };
772
+ }
773
+ // Check if questionnaire extractable
774
+ const extension = (_a = qItem.extension) === null || _a === void 0 ? void 0 : _a.find((e) => e.url === FHIR_TEMPLATE_EXTRACT_EXTENSION);
775
+ const templateReference = (_c = (_b = qItem.extension) === null || _b === void 0 ? void 0 : _b.find((e) => e.url === FHIR_TEMPLATE_REFERENCE_EXTENSION)) === null || _c === void 0 ? void 0 : _c.valueString;
776
+ if ((extension === null || extension === void 0 ? void 0 : extension.valueBoolean) || (extension === null || extension === void 0 ? void 0 : extension.valueBoolean) === false) {
777
+ qItemTemplateMap[qItem.linkId].extractable = (_d = extension === null || extension === void 0 ? void 0 : extension.valueBoolean) !== null && _d !== void 0 ? _d : false;
778
+ }
779
+ else if (parent && qItemTemplateMap[parent.linkId]) {
780
+ qItemTemplateMap[qItem.linkId].extractable = qItemTemplateMap[parent.linkId].extractable;
781
+ }
782
+ else if (root && qItemTemplateMap[(_e = root.id) !== null && _e !== void 0 ? _e : 'root']) {
783
+ qItemTemplateMap[qItem.linkId].extractable = qItemTemplateMap[(_f = root === null || root === void 0 ? void 0 : root.id) !== null && _f !== void 0 ? _f : 'root'].extractable;
784
+ }
785
+ else {
786
+ qItemTemplateMap[qItem.linkId].extractable = false;
787
+ }
788
+ if (templateReference) {
789
+ qItemTemplateMap[qItem.linkId].templateReference = templateReference;
790
+ }
791
+ if (qItem.item && qItem.item.length !== 0) {
792
+ for (const qChildItem of qItem.item) {
793
+ mapQItemsTemplateRecursive(qChildItem, root, qItem, qItemTemplateMap);
794
+ }
795
+ }
796
+ }
797
+ function transverseQuestionnaire(questionnaire, callback, qItemTemplateMap) {
798
+ if (!questionnaire.item)
799
+ return;
800
+ for (const item of questionnaire.item) {
801
+ callback(item, questionnaire, undefined, qItemTemplateMap);
802
+ if (item.item) {
803
+ for (const childItem of item.item) {
804
+ callback(childItem, questionnaire, item, qItemTemplateMap);
805
+ }
806
+ }
807
+ }
808
+ }
809
+ //# sourceMappingURL=extractTemplate.js.map