diff --git a/databaseData/db.json b/databaseData/db.json index b6c7d2dc..c228d7d5 100644 --- a/databaseData/db.json +++ b/databaseData/db.json @@ -1,3 +1,4 @@ + { "clients": [], "logs": [], diff --git a/src/App.jsx b/src/App.jsx index 190eb598..001eb83c 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -129,7 +129,7 @@ export default class App extends Component { this.setState({ questionnaire: artifacts.questionnaire }); this.setState({ deviceRequest: deviceRequest }); this.setState({ isAdaptiveFormWithoutExtension: artifacts.questionnaire.meta && artifacts.questionnaire.meta.profile && artifacts.questionnaire.meta.profile.includes("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-adapt") && (artifacts.questionnaire.extension === undefined || !artifacts.questionnaire.extension.includes(e => e.url === "http://hl7.org/fhir/StructureDefinition/cqf-library")) }); - + this.setState({ }); // execute for each main library return Promise.all( artifacts.mainLibraryElms.map(mainLibraryElm => { @@ -157,7 +157,7 @@ export default class App extends Component { const executionInputs = { elm: mainLibraryElm, // look at main library elms to determine dependent elms to include - elmDependencies: mainLibraryElm.library.includes.def.map( + elmDependencies: mainLibraryElm.library.includes ? mainLibraryElm.library.includes.def.map( includeStatement => { let foundLibrary = artifacts.dependentElms.find(elm => { return ( @@ -172,7 +172,7 @@ export default class App extends Component { this.consoleLog(`Could not find library ${includeStatement.path}. Check if it is referenced in FHIR Library (${mainLibraryElm.library.identifier.id}) properly.`, `errorClass`) } } - ), + ) : undefined, valueSetDB: {}, parameters: parameterObj, mainLibraryMaps: artifacts.mainLibraryMaps @@ -263,6 +263,9 @@ export default class App extends Component { // fill the valueSetDB in executionInputs with the required valuesets from their artifact source fillValueSetDB(executionInputs, artifacts) { + if (!executionInputs.elmDependencies) { + return; + } // create list of all ELMs that will be used let allElms = executionInputs.elmDependencies.slice(); allElms.push(executionInputs.elm); diff --git a/src/components/QuestionnaireForm/QuestionnaireForm.jsx b/src/components/QuestionnaireForm/QuestionnaireForm.jsx index 0d1c96c0..de291f5b 100644 --- a/src/components/QuestionnaireForm/QuestionnaireForm.jsx +++ b/src/components/QuestionnaireForm/QuestionnaireForm.jsx @@ -451,7 +451,7 @@ export default class QuestionnaireForm extends Component { getLibraryPrepopulationResult(item, cqlResults) { let prepopulationResult; item.extension.forEach(e => { - let value; + let value, valueExpression; if ( e.url === "http://hl7.org/fhir/StructureDefinition/cqif-calculatedValue" @@ -464,26 +464,34 @@ export default class QuestionnaireForm extends Component { ) { // r4 value = findValueByPrefix(e, "value"); - value = value.expression; + valueExpression = value.expression; } else { // not a cql statement reference return; } - // split library designator from statement - const valueComponents = value.split("."); let libraryName; let statementName; - if (valueComponents.length > 1) { - libraryName = valueComponents[0].substring( - 1, - valueComponents[0].length - 1 - ); - statementName = valueComponents[1]; - } else { - // if there is not library name grab the first library name - statementName = value; - libraryName = Object.keys(cqlResults)[0]; + // this is embedded CQL in Questionnaire + if(value.language === "application/elm+json") { + libraryName = "LibraryLinkId" + item.linkId; + statementName = "LinkId." + item.linkId; + } + else { + // split library designator from statement + const valueComponents = valueExpression.split("."); + + if (valueComponents.length > 1) { + libraryName = valueComponents[0].substring( + 1, + valueComponents[0].length - 1 + ); + statementName = valueComponents[1]; + } else { + // if there is not library name grab the first library name + statementName = valueExpression; + libraryName = Object.keys(cqlResults)[0]; + } } if (cqlResults[libraryName] != null) { diff --git a/src/elmExecutor/buildPopulatedResourceBundle.js b/src/elmExecutor/buildPopulatedResourceBundle.js index cc51b023..feaee0e4 100644 --- a/src/elmExecutor/buildPopulatedResourceBundle.js +++ b/src/elmExecutor/buildPopulatedResourceBundle.js @@ -192,6 +192,11 @@ function buildPopulatedResourceBundle( } }; + // at least grab patient + if(!neededResources) { + neededResources = []; + neededResources.push("Patient"); + } readResources(neededResources.slice(), () => { const bundle = { resourceType: "Bundle", diff --git a/src/elmExecutor/executeElm.js b/src/elmExecutor/executeElm.js index 8275a8f8..1e700a8b 100644 --- a/src/elmExecutor/executeElm.js +++ b/src/elmExecutor/executeElm.js @@ -1,6 +1,5 @@ import cql from "cql-execution"; import cqlfhir from "cql-exec-fhir"; -// import fhirhelpersElm from "./FHIRHelpers.json"; import extractFhirResourcesThatNeedFetching from "./extractFhirResourcesThatNeedFetching"; import buildPopulatedResourceBundle from "./buildPopulatedResourceBundle"; @@ -56,8 +55,18 @@ function findDifference(array1, array2) { function executeElmAgainstPatientSource(executionInputs, patientSource) { // executionInputs.elmDependencies = [ fhirhelpersElm ] - const repository = new cql.Repository(executionInputs.elmDependencies); - const lib = new cql.Library(executionInputs.elm, repository); + let repository = undefined; + if(executionInputs.elmDependencies) { + repository = new cql.Repository(executionInputs.elmDependencies); + } + + let lib = undefined; + if(repository) { + lib = new cql.Library(executionInputs.elm, repository); + } else { + lib = new cql.Library(executionInputs.elm); + } + const codeService = new cql.CodeService(executionInputs.valueSetDB); const executor = new cql.Executor(lib, codeService, executionInputs.parameters); const results = executor.exec(patientSource); diff --git a/src/util/fetchArtifacts.js b/src/util/fetchArtifacts.js index 3c9a4da6..d2be597f 100644 --- a/src/util/fetchArtifacts.js +++ b/src/util/fetchArtifacts.js @@ -33,6 +33,35 @@ function fetchArtifacts(fhirPrefix, filePrefix, questionnaireReference, fhirVers else reject("Failed to fetch all artifacts."); } + function findQuestionnaireEmbeddedCql(inputItems) { + if(!inputItems) { + return; + } + inputItems.forEach(item => { + const itemExtensions = item.extension; + if(item.extension) { + let findEmbeddedCql = item.extension.find(ext => + ext.url === "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression" + && ext.valueExpression && ext.valueExpression.language === "application/elm+json"); + + if(findEmbeddedCql) { + const itemLibrary = JSON.parse(findEmbeddedCql.valueExpression.expression); + itemLibrary.library.identifier= { + id: "LibraryLinkId" + item.linkId, + version: "0.0.1" + }; + elmLibraryMaps[itemLibrary.library.identifier.id] = itemLibrary; + retVal.mainLibraryMaps = elmLibraryMaps; + retVal.mainLibraryElms.push(itemLibrary); + } + } + + if(item.item !== undefined && item.item.length > 0) { + findQuestionnaireEmbeddedCql(item.item); + } + }); + } + pendingFetches += 1; consoleLog("fetching questionnaire and elms", "infoClass"); consoleLog(questionnaireReference, "infoClass"); @@ -46,6 +75,8 @@ function fetchArtifacts(fhirPrefix, filePrefix, questionnaireReference, fhirVers fetchedUrls.add(questionnaireReference); + findQuestionnaireEmbeddedCql(questionnaire.item); + if (questionnaire.extension !== undefined) { // grab all main elm urls // R4 resources use cqf library. @@ -81,6 +112,8 @@ function fetchArtifacts(fhirPrefix, filePrefix, questionnaireReference, fhirVers //fetchedUrls.add(questionnaireReference); + findQuestionnaireEmbeddedCql(questionnaire.item); + if (questionnaire.extension !== undefined) { // grab all main elm urls // R4 resources use cqf library.