diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt index 8f7e31dc46..034ddea9ac 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/QuestionnaireViewModel.kt @@ -71,7 +71,6 @@ import kotlinx.coroutines.flow.update import org.hl7.fhir.r4.model.Base import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.Element -import org.hl7.fhir.r4.model.Expression import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent import org.hl7.fhir.r4.model.QuestionnaireResponse @@ -578,7 +577,41 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat // Check cache first for database queries val answerExpression = item.answerExpression ?: return emptyList() - return loadAnswerExpressionOptions(item, answerExpression) + return when { + answerExpression.isXFhirQuery -> { + xFhirQueryResolver?.let { xFhirQueryResolver -> + val xFhirExpressionString = + ExpressionEvaluator.createXFhirQueryFromExpression( + questionnaire, + questionnaireResponse, + item, + answerExpression, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) + if (answerExpressionMap.containsKey(xFhirExpressionString)) { + answerExpressionMap[xFhirExpressionString] + } + + val data = xFhirQueryResolver.resolve(xFhirExpressionString) + val options = item.extractAnswerOptions(data) + + answerExpressionMap[xFhirExpressionString] = options + options + } + ?: error( + "XFhirQueryResolver cannot be null. Please provide the XFhirQueryResolver via DataCaptureConfig." + ) + } + answerExpression.isFhirPath -> { + val data = fhirPathEngine.evaluate(questionnaireResponse, answerExpression.expression) + item.extractAnswerOptions(data) + } + else -> + throw UnsupportedOperationException( + "${answerExpression.language} not supported for answer-expression yet" + ) + } } private fun resolveCqfExpression( @@ -601,42 +634,6 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat ) } - private suspend fun loadAnswerExpressionOptions( - item: QuestionnaireItemComponent, - expression: Expression, - ): List { - var xFhirExpressionString = "" - val data = - if (expression.isXFhirQuery) { - checkNotNull(xFhirQueryResolver) { - "XFhirQueryResolver cannot be null. Please provide the XFhirQueryResolver via DataCaptureConfig." - } - - xFhirExpressionString = - ExpressionEvaluator.createXFhirQueryFromExpression( - questionnaire, - questionnaireResponse, - item, - expression, - questionnaireItemParentMap, - questionnaireLaunchContextMap - ) - if (answerExpressionMap.contains(xFhirExpressionString)) { - return answerExpressionMap[xFhirExpressionString]!! - } - xFhirQueryResolver!!.resolve(xFhirExpressionString) - } else if (expression.isFhirPath) { - fhirPathEngine.evaluate(questionnaireResponse, expression.expression) - } else { - throw UnsupportedOperationException( - "${expression.language} not supported for answer-expression yet" - ) - } - val options = item.extractAnswerOptions(data) - if (expression.isXFhirQuery) answerExpressionMap[xFhirExpressionString] = options - return options - } - /** * Traverses through the list of questionnaire items, the list of questionnaire response items and * the list of items in the questionnaire response answer list and populates diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt index 0ccf8d5fa7..1098b56150 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt @@ -279,7 +279,8 @@ object ExpressionEvaluator { } /** - * Creates an x-fhir-query string for evaluation + * Creates an x-fhir-query string for evaluation. For this, it evaluates both variables and + * fhir-paths in the expression. * * @param expression x-fhir-query expression * @param launchContextMap if passed, the launch context to evaluate the expression against @@ -308,10 +309,8 @@ object ExpressionEvaluator { .filterKeys { expression.expression.contains("{{%$it}}") } .map { Pair("{{%${it.key}}}", it.value!!.primitiveValue()) } - var fhirPathsEvaluatedPairs = emptySequence>() - if (launchContextMap != null) { - fhirPathsEvaluatedPairs = evaluateXFhirEnhancement(expression, launchContextMap) - } + val fhirPathsEvaluatedPairs = + launchContextMap?.let { evaluateXFhirEnhancement(expression, it) } ?: emptySequence() return (fhirPathsEvaluatedPairs + variablesEvaluatedPairs).fold(expression.expression) { acc: String, pair: Pair ->