From d73edd2c919454891812efcae372089e43f74042 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 14 Aug 2023 17:14:50 +0700 Subject: [PATCH 01/40] Provide proper contextMap when evaluating the following: - enableWhenExpression can access variablesMap and launchContextMap - variableExpression can access launchContextMap --- .../datacapture/QuestionnaireViewModel.kt | 36 +++++++++-- .../enablement/EnablementEvaluator.kt | 27 +++++++- .../EnabledAnswerOptionsEvaluator.kt | 12 ++-- .../fhirpath/ExpressionEvaluator.kt | 63 +++++++++++++------ .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 17 +++-- .../QuestionnaireResponseValidator.kt | 39 ++++++++++-- 6 files changed, 152 insertions(+), 42 deletions(-) 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 aa0361e303..5caadc483f 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 @@ -404,7 +404,9 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - getApplication() + getApplication(), + questionnaireItemParentMap, + questionnaireLaunchContextMap ) .also { result -> if (result.values.flatten().filterIsInstance().isNotEmpty()) { @@ -505,7 +507,8 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat updatedQuestionnaireResponseItem, questionnaire, questionnaireResponse, - questionnaireItemParentMap + questionnaireItemParentMap, + questionnaireLaunchContextMap ) .forEach { (questionnaireItem, calculatedAnswers) -> // update all response item with updated values @@ -544,7 +547,8 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireItem, questionnaireResponseItem, cqfExpression, - questionnaireItemParentMap + questionnaireItemParentMap, + questionnaireLaunchContextMap ) } @@ -654,7 +658,13 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat if (questionnaireItem.isHidden) return emptyList() val enabled = EnablementEvaluator(questionnaireResponse) - .evaluate(questionnaireItem, questionnaireResponseItem) + .evaluate( + questionnaireItem, + questionnaireResponseItem, + questionnaire, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) // Disabled questions should not get QuestionnaireItemViewItem instances if (!enabled) { cacheDisabledQuestionnaireItemAnswers(questionnaireResponseItem) @@ -689,7 +699,8 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireItem, questionnaireResponseItem, questionnaireResponse, - questionnaireItemParentMap + questionnaireItemParentMap, + questionnaireLaunchContextMap ) if (disabledQuestionnaireResponseAnswers.isNotEmpty()) { removeDisabledAnswers( @@ -713,7 +724,14 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat enabledDisplayItems = questionnaireItem.item.filter { it.isDisplayItem && - EnablementEvaluator(questionnaireResponse).evaluate(it, questionnaireResponseItem) + EnablementEvaluator(questionnaireResponse) + .evaluate( + it, + questionnaireResponseItem, + questionnaire, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) }, questionViewTextConfiguration = QuestionTextConfiguration( @@ -800,6 +818,9 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat enablementEvaluator.evaluate( questionnaireItem, questionnaireResponseItem, + questionnaire, + questionnaireItemParentMap, + questionnaireLaunchContextMap ) } .map { (questionnaireItem, questionnaireResponseItem) -> @@ -832,6 +853,9 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat .evaluate( questionnaireItem, questionnaireResponseItem, + questionnaire, + questionnaireItemParentMap, + questionnaireLaunchContextMap ), questionnaireItem.isHidden ) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index ab293b0200..400974173b 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,13 @@ package com.google.android.fhir.datacapture.enablement import com.google.android.fhir.compareTo import com.google.android.fhir.datacapture.extensions.allItems import com.google.android.fhir.datacapture.extensions.enableWhenExpression +import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import com.google.android.fhir.datacapture.fhirpath.evaluateToBoolean import com.google.android.fhir.equals +import org.hl7.fhir.r4.model.Base import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse +import org.hl7.fhir.r4.model.Resource /** * Evaluator for the enablement status of a [Questionnaire.QuestionnaireItemComponent]. @@ -100,6 +103,10 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo fun evaluate( questionnaireItem: Questionnaire.QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, + questionnaire: Questionnaire, + questionnaireItemParentMap: + Map, + launchContextMap: Map? ): Boolean { val enableWhenList = questionnaireItem.enableWhen val enableWhenExpression = questionnaireItem.enableWhenExpression @@ -110,10 +117,26 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo // Evaluate `enableWhenExpression`. if (enableWhenExpression != null && enableWhenExpression.hasExpression()) { + val contextMap = + mutableMapOf().apply { + ExpressionEvaluator.extractDependentVariables( + questionnaireItem.enableWhenExpression!!, + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + questionnaireItem, + this, + launchContextMap + ) + if (launchContextMap != null) { + putAll(launchContextMap) + } + } return evaluateToBoolean( questionnaireResponse, questionnaireResponseItem, - enableWhenExpression.expression + enableWhenExpression.expression, + contextMap ) } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index f0bb0a0188..daab7dd986 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -62,7 +62,8 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireItem: QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map + questionnaireItemParentMap: Map, + launchContextMap: Map? ): Pair< List, List @@ -80,7 +81,8 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponseItem, questionnaireResponse, resolvedAnswerOptions, - questionnaireItemParentMap + questionnaireItemParentMap, + launchContextMap ) val disabledAnswers = questionnaireResponseItem.answer @@ -214,7 +216,8 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, questionnaireResponse: QuestionnaireResponse, answerOptions: List, - questionnaireItemParentMap: Map + questionnaireItemParentMap: Map, + launchContextMap: Map? ): List { val results = item.answerOptionsToggleExpressions @@ -229,7 +232,8 @@ internal class EnabledAnswerOptionsEvaluator( item, questionnaireResponseItem, expression, - questionnaireItemParentMap + questionnaireItemParentMap, + launchContextMap ) ) else 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 ed0c1c84a8..6cb3a500f8 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 @@ -97,7 +97,8 @@ object ExpressionEvaluator { questionnaireItem: QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponseItemComponent?, expression: Expression, - questionnaireItemParentMap: Map + questionnaireItemParentMap: Map, + launchContextMap: Map? ): List { val appContext = mutableMapOf().apply { @@ -107,7 +108,8 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, questionnaireItem, - this + this, + launchContextMap ) } return fhirPathEngine.evaluate( @@ -128,7 +130,8 @@ object ExpressionEvaluator { updatedQuestionnaireResponseItemComponent: QuestionnaireResponseItemComponent?, questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map + questionnaireItemParentMap: Map, + launchContextMap: Map? ): List { return questionnaire.item .flattened() @@ -147,7 +150,8 @@ object ExpressionEvaluator { questionnaireItem, updatedQuestionnaireResponseItemComponent, questionnaireItem.calculatedExpression!!, - questionnaireItemParentMap + questionnaireItemParentMap, + launchContextMap ) .map { it.castToType(it) } questionnaireItem to updatedAnswer @@ -184,7 +188,8 @@ object ExpressionEvaluator { questionnaireItemParentMap: Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, - variablesMap: MutableMap = mutableMapOf() + variablesMap: MutableMap = mutableMapOf(), + launchContextMap: Map? ): Base? { require( questionnaireItem.variableExpressions.any { @@ -197,10 +202,11 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, questionnaireItem, - variablesMap + variablesMap, + launchContextMap ) - return evaluateVariable(expression, questionnaireResponse, variablesMap) + return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap) } /** @@ -216,14 +222,15 @@ object ExpressionEvaluator { * @param variablesMap the [Map] of variables, the default value is empty map is * defined */ - private fun extractDependentVariables( + internal fun extractDependentVariables( expression: Expression, questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, - variablesMap: MutableMap = mutableMapOf() + variablesMap: MutableMap = mutableMapOf(), + launchContextMap: Map? ) = findDependentVariables(expression).forEach { variableName -> if (variablesMap[variableName] == null) { @@ -233,7 +240,8 @@ object ExpressionEvaluator { questionnaire, questionnaireResponse, questionnaireItemParentMap, - variablesMap + variablesMap, + launchContextMap ) } } @@ -259,7 +267,8 @@ object ExpressionEvaluator { expression: Expression, questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, - variablesMap: MutableMap = mutableMapOf() + variablesMap: MutableMap = mutableMapOf(), + launchContextMap: Map? ): Base? { findDependentVariables(expression).forEach { variableName -> questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -269,13 +278,14 @@ object ExpressionEvaluator { expression, questionnaire, questionnaireResponse, - variablesMap + variablesMap, + launchContextMap ) } } } - return evaluateVariable(expression, questionnaireResponse, variablesMap) + return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap) } /** @@ -300,7 +310,8 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, questionnaireItem, - this + this, + launchContextMap ) } .filterKeys { expression.expression.contains("{{%$it}}") } @@ -389,7 +400,8 @@ object ExpressionEvaluator { questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, - variablesMap: MutableMap + variablesMap: MutableMap, + launchContextMap: Map? ) { // First, check the questionnaire item itself val evaluatedValue = @@ -400,7 +412,8 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, questionnaireItem, - variablesMap + variablesMap, + launchContextMap ) } // Secondly, check the ancestors of the questionnaire item ?: findVariableInAncestors(variableName, questionnaireItemParentMap, questionnaireItem) @@ -411,7 +424,8 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, questionnaireItem, - variablesMap + variablesMap, + launchContextMap ) } // Finally, check the variables defined on the questionnaire itself ?: questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -419,7 +433,8 @@ object ExpressionEvaluator { expression, questionnaire, questionnaireResponse, - variablesMap + variablesMap, + launchContextMap ) } @@ -465,7 +480,8 @@ object ExpressionEvaluator { private fun evaluateVariable( expression: Expression, questionnaireResponse: QuestionnaireResponse, - dependentVariables: Map = mapOf() + dependentVariables: Map = mapOf(), + launchContextMap: Map? ) = try { require(expression.name?.isNotBlank() == true) { @@ -476,8 +492,15 @@ object ExpressionEvaluator { "Unsupported expression language, language should be text/fhirpath" } + val contextMap = + mutableMapOf().apply { + putAll(dependentVariables) + if (launchContextMap != null) { + putAll(launchContextMap) + } + } fhirPathEngine - .evaluate(dependentVariables, questionnaireResponse, null, null, expression.expression) + .evaluate(contextMap, questionnaireResponse, null, null, expression.expression) .firstOrNull() } catch (exception: FHIRException) { Timber.w("Could not evaluate expression with FHIRPathEngine", exception) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index d09342e94c..accaf7d249 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package com.google.android.fhir.datacapture.fhirpath import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.context.FhirVersionEnum import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext +import org.hl7.fhir.r4.model.Base import org.hl7.fhir.r4.model.QuestionnaireResponse import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemComponent import org.hl7.fhir.r4.model.Resource @@ -47,11 +48,15 @@ internal fun evaluateToDisplay(expressions: List, data: Resource) = internal fun evaluateToBoolean( questionnaireResponse: QuestionnaireResponse, questionnaireResponseItemComponent: QuestionnaireResponseItemComponent, - expression: String -) = - fhirPathEngine.evaluateToBoolean( + expression: String, + contextMap: Map +): Boolean { + val expressionNode = fhirPathEngine.parse(expression) + return fhirPathEngine.evaluateToBoolean( + contextMap, questionnaireResponse, - null, questionnaireResponseItemComponent, - expression + null, + expressionNode ) +} diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index 06d2b275d9..fe4b40a504 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.google.android.fhir.datacapture.enablement.EnablementEvaluator import com.google.android.fhir.datacapture.extensions.packRepeatedGroups import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse +import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.Type object QuestionnaireResponseValidator { @@ -56,7 +57,10 @@ object QuestionnaireResponseValidator { fun validateQuestionnaireResponse( questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, - context: Context + context: Context, + questionnaireItemParentMap: + Map, + launchContextMap: Map? ): Map> { require( questionnaireResponse.questionnaire == null || @@ -73,6 +77,9 @@ object QuestionnaireResponseValidator { context, EnablementEvaluator(questionnaireResponse), linkIdToValidationResultMap, + questionnaire, + questionnaireItemParentMap, + launchContextMap ) return linkIdToValidationResultMap @@ -84,6 +91,10 @@ object QuestionnaireResponseValidator { context: Context, enablementEvaluator: EnablementEvaluator, linkIdToValidationResultMap: MutableMap>, + questionnaire: Questionnaire, + questionnaireItemParentMap: + Map, + launchContextMap: Map? ): Map> { val questionnaireItemListIterator = questionnaireItemList.iterator() val questionnaireResponseItemListIterator = questionnaireResponseItemList.iterator() @@ -98,7 +109,14 @@ object QuestionnaireResponseValidator { questionnaireItem = questionnaireItemListIterator.next() } while (questionnaireItem!!.linkId != questionnaireResponseItem.linkId) - val enabled = enablementEvaluator.evaluate(questionnaireItem, questionnaireResponseItem) + val enabled = + enablementEvaluator.evaluate( + questionnaireItem, + questionnaireResponseItem, + questionnaire, + questionnaireItemParentMap, + launchContextMap + ) if (enabled) { validateQuestionnaireResponseItem( @@ -107,6 +125,9 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, + questionnaire, + questionnaireItemParentMap, + launchContextMap ) } } @@ -118,7 +139,11 @@ object QuestionnaireResponseValidator { questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, context: Context, enablementEvaluator: EnablementEvaluator, - linkIdToValidationResultMap: MutableMap> + linkIdToValidationResultMap: MutableMap>, + questionnaire: Questionnaire, + questionnaireItemParentMap: + Map, + launchContextMap: Map? ): Map> { when (checkNotNull(questionnaireItem.type) { "Questionnaire item must have type" }) { @@ -133,6 +158,9 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, + questionnaire, + questionnaireItemParentMap, + launchContextMap ) else -> { require(questionnaireItem.repeats || questionnaireResponseItem.answer.size <= 1) { @@ -146,6 +174,9 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, + questionnaire, + questionnaireItemParentMap, + launchContextMap ) } From 4d0d9e98c16894552cc799a0e723e2b5691644ca Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 14 Aug 2023 17:15:44 +0700 Subject: [PATCH 02/40] FOR PR TESTING ONLY --- .../src/main/assets/component_dropdown.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/catalog/src/main/assets/component_dropdown.json b/catalog/src/main/assets/component_dropdown.json index f5797d05dc..6e61e9dd9a 100644 --- a/catalog/src/main/assets/component_dropdown.json +++ b/catalog/src/main/assets/component_dropdown.json @@ -1,8 +1,23 @@ { "resourceType": "Questionnaire", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/variable", + "valueExpression": { + "name": "fikri", + "language": "text/fhirpath", + "expression": "%resource.descendants().where(linkId='1').answer.value" + } + } + ], "item": [ { "linkId": "1", + "type": "boolean", + "text": "Choose one from the options below" + }, + { + "linkId": "2", "type": "choice", "extension": [ { @@ -17,6 +32,13 @@ ], "text": "Drop down" } + }, + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%fikri" + } } ], "text": "Choose one from the options below", From 669aeacd10f8465b5fa462078022a28a595545ee Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Tue, 15 Aug 2023 10:22:13 +0700 Subject: [PATCH 03/40] Fix failing test --- .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 14 ++++- ...alidationErrorMessageDialogFragmentTest.kt | 6 ++- .../enablement/EnablementEvaluatorTest.kt | 23 ++++++-- .../fhirpath/ExpressionEvaluatorTest.kt | 54 ++++++++++++++----- .../QuestionnaireResponseValidatorTest.kt | 54 ++++++++++++++----- .../android/fhir/demo/AddPatientViewModel.kt | 6 ++- 6 files changed, 121 insertions(+), 36 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index accaf7d249..13fa7c3ac2 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -55,8 +55,20 @@ internal fun evaluateToBoolean( return fhirPathEngine.evaluateToBoolean( contextMap, questionnaireResponse, - questionnaireResponseItemComponent, null, + questionnaireResponseItemComponent, expressionNode ) } + +internal fun evaluateToBoolean( + questionnaireResponse: QuestionnaireResponse, + questionnaireResponseItemComponent: QuestionnaireResponseItemComponent, + expression: String +) = + fhirPathEngine.evaluateToBoolean( + questionnaireResponse, + null, + questionnaireResponseItemComponent, + expression + ) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt index 54841ee570..240343cd0d 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,7 +82,9 @@ class QuestionnaireValidationErrorMessageDialogFragmentTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - RuntimeEnvironment.getApplication() + RuntimeEnvironment.getApplication(), + mapOf(), + mapOf() ) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt index aebf3921f4..0eab737960 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,12 +53,13 @@ class EnablementEvaluatorTest { type = Questionnaire.QuestionnaireItemType.BOOLEAN addEnableWhen(Questionnaire.QuestionnaireItemEnableWhenComponent().setQuestion("q2")) } + val questionnaire = Questionnaire().addItem(questionnaireItem) val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { linkId = "q1" } val questionnaireResponse = QuestionnaireResponse().apply { addItem(questionnaireResponseItem) } assertThat( EnablementEvaluator(questionnaireResponse) - .evaluate(questionnaireItem, questionnaireResponseItem) + .evaluate(questionnaireItem, questionnaireResponseItem, questionnaire, mapOf(), mapOf()) ) .isFalse() } @@ -177,6 +178,9 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItem, questionnaireResponse.item[1], + questionnaire, + mapOf(), + mapOf() ) ) .isTrue() @@ -256,6 +260,9 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItemComponent, questionnaireResponse.item[1], + questionnaire, + mapOf(), + mapOf() ) ) .isFalse() @@ -335,6 +342,9 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItem, questionnaireResponse.item[1], + questionnaire, + mapOf(), + mapOf() ) ) .isTrue() @@ -759,6 +769,7 @@ class EnablementEvaluatorTest { behavior?.let { enableBehavior = it } type = Questionnaire.QuestionnaireItemType.BOOLEAN } + val questionnaire = Questionnaire().addItem(questionnaireItem) val questionnaireResponse = QuestionnaireResponse().apply { enableWhen.forEachIndexed { index, enableWhen -> @@ -777,7 +788,13 @@ class EnablementEvaluatorTest { } return assertThat( EnablementEvaluator(questionnaireResponse) - .evaluate(questionnaireItem, questionnaireResponse.item.last()) + .evaluate( + questionnaireItem, + questionnaireResponse.item.last(), + questionnaire, + mapOf(), + mapOf() + ) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 5b86000b3a..62daec0a3e 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -67,7 +67,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("1") @@ -104,7 +106,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -158,7 +162,9 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), - questionnaire.item[0].item[0] + questionnaire.item[0].item[0], + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -205,7 +211,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("3") @@ -232,7 +240,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) assertThat(result).isEqualTo(null) @@ -278,7 +288,9 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mapOf(), - questionnaire.item[0] + questionnaire.item[0], + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -314,7 +326,9 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mapOf(), - questionnaire.item[0] + questionnaire.item[0], + mutableMapOf(), + mapOf() ) assertThat(result).isEqualTo(null) @@ -341,7 +355,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) } } @@ -368,7 +384,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) } } @@ -396,7 +414,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) } } @@ -423,7 +443,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), questionnaire, - QuestionnaireResponse() + QuestionnaireResponse(), + mutableMapOf(), + mapOf() ) } } @@ -483,7 +505,9 @@ class ExpressionEvaluatorTest { questionnaire, questionnaireResponse, mapOf(), - questionnaire.item[0] + questionnaire.item[0], + mutableMapOf(), + mapOf() ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -544,7 +568,8 @@ class ExpressionEvaluatorTest { questionnaireResponse.item.elementAt(1), questionnaire, questionnaireResponse, - emptyMap() + emptyMap(), + mapOf() ) assertThat(result.first().second.first().asStringValue()) @@ -617,7 +642,8 @@ class ExpressionEvaluatorTest { questionnaireResponse.item.elementAt(1), questionnaire, questionnaireResponse, - emptyMap() + emptyMap(), + mapOf() ) assertThat(result.first().second.first().asStringValue()) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt index a17e0e084d..8972c972a8 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,7 +82,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result["a-question"]!!.single()).isEqualTo(Valid) } @@ -114,7 +116,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result["a-question"]!!.single()) .isEqualTo( @@ -166,7 +170,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result["a-question"]) .containsExactly( @@ -235,7 +241,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result.keys).containsExactly("q1") assertThat(result["q1"]).containsExactly(Valid) @@ -286,7 +294,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result["question-1"]!!.single()).isEqualTo(Valid) } @@ -300,7 +310,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponse().apply { questionnaire = "http://www.sample-org/FHIR/Resources/Questionnaire/questionnaire-1" }, - context + context, + mapOf(), + mapOf() ) } @@ -319,7 +331,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( Questionnaire().apply { url = "questionnaire-1" }, QuestionnaireResponse(), - context + context, + mapOf(), + mapOf() ) } @@ -387,7 +401,9 @@ class QuestionnaireResponseValidatorTest { questionnaire = "questionnaire-1" addItem(QuestionnaireResponse.QuestionnaireResponseItemComponent(StringType("display-1"))) }, - context + context, + mapOf(), + mapOf() ) } @@ -410,7 +426,9 @@ class QuestionnaireResponseValidatorTest { questionnaire = "questionnaire-1" addItem(QuestionnaireResponse.QuestionnaireResponseItemComponent(StringType("null-1"))) }, - context + context, + mapOf(), + mapOf() ) } @@ -448,7 +466,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) assertThat(result.entries.first().key).isEqualTo("valid-hidden-item") @@ -489,7 +509,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) .entries.first() @@ -1649,7 +1671,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) } assertThat(exception.message).isEqualTo(message) @@ -1666,7 +1690,9 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - context + context, + mapOf(), + mapOf() ) } assertThat(exception.message).isEqualTo(message) diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index 340c33118a..c381fe9f6b 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,9 @@ class AddPatientViewModel(application: Application, private val state: SavedStat if (QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaireResource, questionnaireResponse, - getApplication() + getApplication(), + mapOf(), + mapOf() ) .values .flatten() From 7e1952b640799904e6f892e91022559dcee64c9c Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 08:36:02 +0700 Subject: [PATCH 04/40] Rename questionnaireResource to questionnaire --- .../android/fhir/demo/AddPatientFragment.kt | 2 +- .../android/fhir/demo/AddPatientViewModel.kt | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientFragment.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientFragment.kt index a6213369bd..0ae3cdc864 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientFragment.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientFragment.kt @@ -75,7 +75,7 @@ class AddPatientFragment : Fragment(R.layout.add_patient_fragment) { childFragmentManager.commit { add( R.id.add_patient_container, - QuestionnaireFragment.builder().setQuestionnaire(viewModel.questionnaire).build(), + QuestionnaireFragment.builder().setQuestionnaire(viewModel.questionnaireJson).build(), QUESTIONNAIRE_FRAGMENT_TAG ) } diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index c381fe9f6b..3d17e23fd6 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -37,16 +37,16 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse class AddPatientViewModel(application: Application, private val state: SavedStateHandle) : AndroidViewModel(application) { - val questionnaire: String + private var _questionnaireJson: String? = null + val questionnaireJson: String get() = getQuestionnaireJson() val isPatientSaved = MutableLiveData() - private val questionnaireResource: Questionnaire + private val questionnaire: Questionnaire get() = - FhirContext.forCached(FhirVersionEnum.R4).newJsonParser().parseResource(questionnaire) + FhirContext.forCached(FhirVersionEnum.R4).newJsonParser().parseResource(questionnaireJson) as Questionnaire private var fhirEngine: FhirEngine = FhirApplication.fhirEngine(application.applicationContext) - private var questionnaireJson: String? = null /** * Saves patient registration questionnaire response into the application database. @@ -56,7 +56,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat fun savePatient(questionnaireResponse: QuestionnaireResponse) { viewModelScope.launch { if (QuestionnaireResponseValidator.validateQuestionnaireResponse( - questionnaireResource, + questionnaire, questionnaireResponse, getApplication(), mapOf(), @@ -70,7 +70,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat return@launch } - val entry = ResourceMapper.extract(questionnaireResource, questionnaireResponse).entryFirstRep + val entry = ResourceMapper.extract(questionnaire, questionnaireResponse).entryFirstRep if (entry.resource !is Patient) { return@launch } @@ -82,11 +82,11 @@ class AddPatientViewModel(application: Application, private val state: SavedStat } private fun getQuestionnaireJson(): String { - questionnaireJson?.let { + _questionnaireJson?.let { return it } - questionnaireJson = readFileFromAssets(state[AddPatientFragment.QUESTIONNAIRE_FILE_PATH_KEY]!!) - return questionnaireJson!! + _questionnaireJson = readFileFromAssets(state[AddPatientFragment.QUESTIONNAIRE_FILE_PATH_KEY]!!) + return _questionnaireJson!! } private fun readFileFromAssets(filename: String): String { From 0446d43e164602464ac0c24ac85b3a8788372545 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 08:36:31 +0700 Subject: [PATCH 05/40] Revert component_dropdown.json --- .../src/main/assets/component_dropdown.json | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/catalog/src/main/assets/component_dropdown.json b/catalog/src/main/assets/component_dropdown.json index 6e61e9dd9a..f5797d05dc 100644 --- a/catalog/src/main/assets/component_dropdown.json +++ b/catalog/src/main/assets/component_dropdown.json @@ -1,23 +1,8 @@ { "resourceType": "Questionnaire", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/variable", - "valueExpression": { - "name": "fikri", - "language": "text/fhirpath", - "expression": "%resource.descendants().where(linkId='1').answer.value" - } - } - ], "item": [ { "linkId": "1", - "type": "boolean", - "text": "Choose one from the options below" - }, - { - "linkId": "2", "type": "choice", "extension": [ { @@ -32,13 +17,6 @@ ], "text": "Drop down" } - }, - { - "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression", - "valueExpression": { - "language": "text/fhirpath", - "expression": "%fikri" - } } ], "text": "Choose one from the options below", From 8429ae608f7a31cf1e2736c613ca429d5a58419b Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 08:37:12 +0700 Subject: [PATCH 06/40] Add skip logic w expression to catalog --- .../behavior_skip_logic_with_expression.json | 34 +++++++++++++++++++ .../fhir/catalog/BehaviorListViewModel.kt | 5 +++ catalog/src/main/res/values/strings.xml | 1 + 3 files changed, 40 insertions(+) create mode 100644 catalog/src/main/assets/behavior_skip_logic_with_expression.json diff --git a/catalog/src/main/assets/behavior_skip_logic_with_expression.json b/catalog/src/main/assets/behavior_skip_logic_with_expression.json new file mode 100644 index 0000000000..da4d531d58 --- /dev/null +++ b/catalog/src/main/assets/behavior_skip_logic_with_expression.json @@ -0,0 +1,34 @@ +{ + "resourceType": "Questionnaire", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/variable", + "valueExpression": { + "name": "has-fever", + "language": "text/fhirpath", + "expression": "%resource.descendants().where(linkId='1').answer.value" + } + } + ], + "item": [ + { + "linkId": "1", + "type": "boolean", + "text": "Does patient has fever?" + }, + { + "linkId": "2", + "text": "Since when?", + "type": "date", + "extension": [ + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression", + "valueExpression": { + "language": "text/fhirpath", + "expression": "%has-fever" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt b/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt index 0f5ffe3c16..3fa8709e27 100644 --- a/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt +++ b/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt @@ -48,6 +48,11 @@ class BehaviorListViewModel(application: Application) : AndroidViewModel(applica R.string.behavior_name_skip_logic, "behavior_skip_logic.json" ), + SKIP_LOGIC_WITH_EXPRESSION( + R.drawable.ic_skiplogic_behavior, + R.string.behavior_name_skip_logic_with_expression, + "behavior_skip_logic_with_expression.json" + ), DYNAMIC_QUESTION_TEXT( R.drawable.ic_dynamic_text_behavior, R.string.behavior_name_dynamic_question_text, diff --git a/catalog/src/main/res/values/strings.xml b/catalog/src/main/res/values/strings.xml index bb5b1aa767..4595abe74f 100644 --- a/catalog/src/main/res/values/strings.xml +++ b/catalog/src/main/res/values/strings.xml @@ -41,6 +41,7 @@ Review Read only Skip logic + Skip logic with expression If Yes is selected, a follow-up question is displayed. If No is selected, no follow-up questions are displayed. From 6545f721f0c1aa44057cbcbcc9c3bbb7594f5b71 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 09:06:00 +0700 Subject: [PATCH 07/40] Add trailing comas --- .../datacapture/QuestionnaireViewModel.kt | 16 ++++---- .../enablement/EnablementEvaluator.kt | 6 +-- .../EnabledAnswerOptionsEvaluator.kt | 8 ++-- .../fhirpath/ExpressionEvaluator.kt | 38 +++++++++---------- .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 4 +- .../QuestionnaireResponseValidator.kt | 16 ++++---- ...alidationErrorMessageDialogFragmentTest.kt | 2 +- .../enablement/EnablementEvaluatorTest.kt | 10 ++--- .../fhirpath/ExpressionEvaluatorTest.kt | 28 +++++++------- .../QuestionnaireResponseValidatorTest.kt | 26 ++++++------- .../android/fhir/demo/AddPatientViewModel.kt | 4 +- 11 files changed, 79 insertions(+), 79 deletions(-) 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 5caadc483f..308621518c 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 @@ -406,7 +406,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponse, getApplication(), questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) .also { result -> if (result.values.flatten().filterIsInstance().isNotEmpty()) { @@ -508,7 +508,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaire, questionnaireResponse, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) .forEach { (questionnaireItem, calculatedAnswers) -> // update all response item with updated values @@ -548,7 +548,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, cqfExpression, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) } @@ -663,7 +663,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, questionnaire, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) // Disabled questions should not get QuestionnaireItemViewItem instances if (!enabled) { @@ -700,7 +700,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, questionnaireResponse, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) if (disabledQuestionnaireResponseAnswers.isNotEmpty()) { removeDisabledAnswers( @@ -730,7 +730,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, questionnaire, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) }, questionViewTextConfiguration = @@ -820,7 +820,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, questionnaire, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ) } .map { (questionnaireItem, questionnaireResponseItem) -> @@ -855,7 +855,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponseItem, questionnaire, questionnaireItemParentMap, - questionnaireLaunchContextMap + questionnaireLaunchContextMap, ), questionnaireItem.isHidden ) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 400974173b..9fc5f9be3c 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -106,7 +106,7 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo questionnaire: Questionnaire, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): Boolean { val enableWhenList = questionnaireItem.enableWhen val enableWhenExpression = questionnaireItem.enableWhenExpression @@ -126,7 +126,7 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo questionnaireItemParentMap, questionnaireItem, this, - launchContextMap + launchContextMap, ) if (launchContextMap != null) { putAll(launchContextMap) @@ -136,7 +136,7 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo questionnaireResponse, questionnaireResponseItem, enableWhenExpression.expression, - contextMap + contextMap, ) } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index daab7dd986..66b96d7818 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -63,7 +63,7 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): Pair< List, List @@ -82,7 +82,7 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponse, resolvedAnswerOptions, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) val disabledAnswers = questionnaireResponseItem.answer @@ -217,7 +217,7 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponse: QuestionnaireResponse, answerOptions: List, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): List { val results = item.answerOptionsToggleExpressions @@ -233,7 +233,7 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponseItem, expression, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) ) else 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 6cb3a500f8..088d21861f 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 @@ -98,7 +98,7 @@ object ExpressionEvaluator { questionnaireResponseItem: QuestionnaireResponseItemComponent?, expression: Expression, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): List { val appContext = mutableMapOf().apply { @@ -109,7 +109,7 @@ object ExpressionEvaluator { questionnaireItemParentMap, questionnaireItem, this, - launchContextMap + launchContextMap, ) } return fhirPathEngine.evaluate( @@ -131,7 +131,7 @@ object ExpressionEvaluator { questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): List { return questionnaire.item .flattened() @@ -151,7 +151,7 @@ object ExpressionEvaluator { updatedQuestionnaireResponseItemComponent, questionnaireItem.calculatedExpression!!, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) .map { it.castToType(it) } questionnaireItem to updatedAnswer @@ -189,7 +189,7 @@ object ExpressionEvaluator { Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? + launchContextMap: Map?, ): Base? { require( questionnaireItem.variableExpressions.any { @@ -203,10 +203,10 @@ object ExpressionEvaluator { questionnaireItemParentMap, questionnaireItem, variablesMap, - launchContextMap + launchContextMap, ) - return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap) + return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap,) } /** @@ -230,7 +230,7 @@ object ExpressionEvaluator { Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? + launchContextMap: Map?, ) = findDependentVariables(expression).forEach { variableName -> if (variablesMap[variableName] == null) { @@ -241,7 +241,7 @@ object ExpressionEvaluator { questionnaireResponse, questionnaireItemParentMap, variablesMap, - launchContextMap + launchContextMap, ) } } @@ -268,7 +268,7 @@ object ExpressionEvaluator { questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? + launchContextMap: Map?, ): Base? { findDependentVariables(expression).forEach { variableName -> questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -279,13 +279,13 @@ object ExpressionEvaluator { questionnaire, questionnaireResponse, variablesMap, - launchContextMap + launchContextMap, ) } } } - return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap) + return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap,) } /** @@ -311,7 +311,7 @@ object ExpressionEvaluator { questionnaireItemParentMap, questionnaireItem, this, - launchContextMap + launchContextMap, ) } .filterKeys { expression.expression.contains("{{%$it}}") } @@ -401,7 +401,7 @@ object ExpressionEvaluator { questionnaireItemParentMap: Map, variablesMap: MutableMap, - launchContextMap: Map? + launchContextMap: Map?, ) { // First, check the questionnaire item itself val evaluatedValue = @@ -413,7 +413,7 @@ object ExpressionEvaluator { questionnaireItemParentMap, questionnaireItem, variablesMap, - launchContextMap + launchContextMap, ) } // Secondly, check the ancestors of the questionnaire item ?: findVariableInAncestors(variableName, questionnaireItemParentMap, questionnaireItem) @@ -425,7 +425,7 @@ object ExpressionEvaluator { questionnaireItemParentMap, questionnaireItem, variablesMap, - launchContextMap + launchContextMap, ) } // Finally, check the variables defined on the questionnaire itself ?: questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -434,7 +434,7 @@ object ExpressionEvaluator { questionnaire, questionnaireResponse, variablesMap, - launchContextMap + launchContextMap, ) } @@ -481,7 +481,7 @@ object ExpressionEvaluator { expression: Expression, questionnaireResponse: QuestionnaireResponse, dependentVariables: Map = mapOf(), - launchContextMap: Map? + launchContextMap: Map?, ) = try { require(expression.name?.isNotBlank() == true) { @@ -500,7 +500,7 @@ object ExpressionEvaluator { } } fhirPathEngine - .evaluate(contextMap, questionnaireResponse, null, null, expression.expression) + .evaluate(contextMap, questionnaireResponse, null, null, expression.expression,) .firstOrNull() } catch (exception: FHIRException) { Timber.w("Could not evaluate expression with FHIRPathEngine", exception) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index 13fa7c3ac2..6d1578b857 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -49,7 +49,7 @@ internal fun evaluateToBoolean( questionnaireResponse: QuestionnaireResponse, questionnaireResponseItemComponent: QuestionnaireResponseItemComponent, expression: String, - contextMap: Map + contextMap: Map, ): Boolean { val expressionNode = fhirPathEngine.parse(expression) return fhirPathEngine.evaluateToBoolean( @@ -57,7 +57,7 @@ internal fun evaluateToBoolean( questionnaireResponse, null, questionnaireResponseItemComponent, - expressionNode + expressionNode, ) } diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index fe4b40a504..f982b3f5ff 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -60,7 +60,7 @@ object QuestionnaireResponseValidator { context: Context, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): Map> { require( questionnaireResponse.questionnaire == null || @@ -79,7 +79,7 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap, questionnaire, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) return linkIdToValidationResultMap @@ -94,7 +94,7 @@ object QuestionnaireResponseValidator { questionnaire: Questionnaire, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): Map> { val questionnaireItemListIterator = questionnaireItemList.iterator() val questionnaireResponseItemListIterator = questionnaireResponseItemList.iterator() @@ -115,7 +115,7 @@ object QuestionnaireResponseValidator { questionnaireResponseItem, questionnaire, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) if (enabled) { @@ -127,7 +127,7 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap, questionnaire, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) } } @@ -143,7 +143,7 @@ object QuestionnaireResponseValidator { questionnaire: Questionnaire, questionnaireItemParentMap: Map, - launchContextMap: Map? + launchContextMap: Map?, ): Map> { when (checkNotNull(questionnaireItem.type) { "Questionnaire item must have type" }) { @@ -160,7 +160,7 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap, questionnaire, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) else -> { require(questionnaireItem.repeats || questionnaireResponseItem.answer.size <= 1) { @@ -176,7 +176,7 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap, questionnaire, questionnaireItemParentMap, - launchContextMap + launchContextMap, ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt index 240343cd0d..109b0c359d 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt @@ -84,7 +84,7 @@ class QuestionnaireValidationErrorMessageDialogFragmentTest { questionnaireResponse, RuntimeEnvironment.getApplication(), mapOf(), - mapOf() + mapOf(), ) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt index 0eab737960..cf353335c0 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt @@ -59,7 +59,7 @@ class EnablementEvaluatorTest { val questionnaireResponse = QuestionnaireResponse().apply { addItem(questionnaireResponseItem) } assertThat( EnablementEvaluator(questionnaireResponse) - .evaluate(questionnaireItem, questionnaireResponseItem, questionnaire, mapOf(), mapOf()) + .evaluate(questionnaireItem, questionnaireResponseItem, questionnaire, mapOf(), mapOf(),) ) .isFalse() } @@ -180,7 +180,7 @@ class EnablementEvaluatorTest { questionnaireResponse.item[1], questionnaire, mapOf(), - mapOf() + mapOf(), ) ) .isTrue() @@ -262,7 +262,7 @@ class EnablementEvaluatorTest { questionnaireResponse.item[1], questionnaire, mapOf(), - mapOf() + mapOf(), ) ) .isFalse() @@ -344,7 +344,7 @@ class EnablementEvaluatorTest { questionnaireResponse.item[1], questionnaire, mapOf(), - mapOf() + mapOf(), ) ) .isTrue() @@ -793,7 +793,7 @@ class EnablementEvaluatorTest { questionnaireResponse.item.last(), questionnaire, mapOf(), - mapOf() + mapOf(), ) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 62daec0a3e..0b241c319f 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -69,7 +69,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("1") @@ -108,7 +108,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -164,7 +164,7 @@ class ExpressionEvaluatorTest { mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), questionnaire.item[0].item[0], mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -213,7 +213,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("3") @@ -242,7 +242,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) assertThat(result).isEqualTo(null) @@ -290,7 +290,7 @@ class ExpressionEvaluatorTest { mapOf(), questionnaire.item[0], mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -328,7 +328,7 @@ class ExpressionEvaluatorTest { mapOf(), questionnaire.item[0], mutableMapOf(), - mapOf() + mapOf(), ) assertThat(result).isEqualTo(null) @@ -357,7 +357,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) } } @@ -386,7 +386,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) } } @@ -416,7 +416,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) } } @@ -445,7 +445,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), mutableMapOf(), - mapOf() + mapOf(), ) } } @@ -507,7 +507,7 @@ class ExpressionEvaluatorTest { mapOf(), questionnaire.item[0], mutableMapOf(), - mapOf() + mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -569,7 +569,7 @@ class ExpressionEvaluatorTest { questionnaire, questionnaireResponse, emptyMap(), - mapOf() + mapOf(), ) assertThat(result.first().second.first().asStringValue()) @@ -643,7 +643,7 @@ class ExpressionEvaluatorTest { questionnaire, questionnaireResponse, emptyMap(), - mapOf() + mapOf(), ) assertThat(result.first().second.first().asStringValue()) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt index 8972c972a8..705f3b0c45 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt @@ -84,7 +84,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result["a-question"]!!.single()).isEqualTo(Valid) } @@ -118,7 +118,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result["a-question"]!!.single()) .isEqualTo( @@ -172,7 +172,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result["a-question"]) .containsExactly( @@ -243,7 +243,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result.keys).containsExactly("q1") assertThat(result["q1"]).containsExactly(Valid) @@ -296,7 +296,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result["question-1"]!!.single()).isEqualTo(Valid) } @@ -312,7 +312,7 @@ class QuestionnaireResponseValidatorTest { }, context, mapOf(), - mapOf() + mapOf(), ) } @@ -333,7 +333,7 @@ class QuestionnaireResponseValidatorTest { QuestionnaireResponse(), context, mapOf(), - mapOf() + mapOf(), ) } @@ -403,7 +403,7 @@ class QuestionnaireResponseValidatorTest { }, context, mapOf(), - mapOf() + mapOf(), ) } @@ -428,7 +428,7 @@ class QuestionnaireResponseValidatorTest { }, context, mapOf(), - mapOf() + mapOf(), ) } @@ -468,7 +468,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) assertThat(result.entries.first().key).isEqualTo("valid-hidden-item") @@ -511,7 +511,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) .entries.first() @@ -1673,7 +1673,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) } assertThat(exception.message).isEqualTo(message) @@ -1692,7 +1692,7 @@ class QuestionnaireResponseValidatorTest { questionnaireResponse, context, mapOf(), - mapOf() + mapOf(), ) } assertThat(exception.message).isEqualTo(message) diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index 3d17e23fd6..168fcbf960 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -60,7 +60,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat questionnaireResponse, getApplication(), mapOf(), - mapOf() + mapOf(), ) .values .flatten() @@ -70,7 +70,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat return@launch } - val entry = ResourceMapper.extract(questionnaire, questionnaireResponse).entryFirstRep + val entry = ResourceMapper.extract(questionnaire, questionnaireResponse,).entryFirstRep if (entry.resource !is Patient) { return@launch } From cf06b67f9e4f996b096e3e1ada71b8af60e733b3 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 10:49:32 +0700 Subject: [PATCH 08/40] Add default parameter value for maps and Questionnaire --- .../enablement/EnablementEvaluator.kt | 6 ++-- .../EnabledAnswerOptionsEvaluator.kt | 2 +- .../fhirpath/ExpressionEvaluator.kt | 22 +++++++-------- .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 2 +- .../QuestionnaireResponseValidator.kt | 16 +++++------ ...alidationErrorMessageDialogFragmentTest.kt | 4 +-- .../enablement/EnablementEvaluatorTest.kt | 21 ++------------ .../fhirpath/ExpressionEvaluatorTest.kt | 28 ------------------- .../QuestionnaireResponseValidatorTest.kt | 26 ----------------- .../android/fhir/demo/AddPatientViewModel.kt | 2 -- 10 files changed, 27 insertions(+), 102 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 9fc5f9be3c..65bb82c2a9 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -103,10 +103,10 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo fun evaluate( questionnaireItem: Questionnaire.QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, - questionnaire: Questionnaire, + questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map, - launchContextMap: Map?, + Map = mapOf(), + launchContextMap: Map? = mapOf(), ): Boolean { val enableWhenList = questionnaireItem.enableWhen val enableWhenExpression = questionnaireItem.enableWhenExpression diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index 66b96d7818..2878b3c30a 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -63,7 +63,7 @@ internal class EnabledAnswerOptionsEvaluator( questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ): Pair< List, List 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 088d21861f..934f14b20c 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 @@ -98,7 +98,7 @@ object ExpressionEvaluator { questionnaireResponseItem: QuestionnaireResponseItemComponent?, expression: Expression, questionnaireItemParentMap: Map, - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ): List { val appContext = mutableMapOf().apply { @@ -130,8 +130,8 @@ object ExpressionEvaluator { updatedQuestionnaireResponseItemComponent: QuestionnaireResponseItemComponent?, questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map, - launchContextMap: Map?, + questionnaireItemParentMap: Map = mapOf(), + launchContextMap: Map? = mapOf(), ): List { return questionnaire.item .flattened() @@ -189,7 +189,7 @@ object ExpressionEvaluator { Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ): Base? { require( questionnaireItem.variableExpressions.any { @@ -230,7 +230,7 @@ object ExpressionEvaluator { Map, questionnaireItem: Questionnaire.QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ) = findDependentVariables(expression).forEach { variableName -> if (variablesMap[variableName] == null) { @@ -268,7 +268,7 @@ object ExpressionEvaluator { questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ): Base? { findDependentVariables(expression).forEach { variableName -> questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -298,7 +298,7 @@ object ExpressionEvaluator { questionnaireItem: QuestionnaireItemComponent, questionnaireItemParentMap: Map, expression: Expression, - launchContextMap: Map? + launchContextMap: Map? = mapOf(), ): String { // get all dependent variables and their evaluated values val variablesEvaluatedPairs = @@ -318,7 +318,7 @@ object ExpressionEvaluator { .map { Pair("{{%${it.key}}}", it.value!!.primitiveValue()) } val fhirPathsEvaluatedPairs = - launchContextMap?.let { evaluateXFhirEnhancement(expression, it) } ?: emptySequence() + launchContextMap.takeIf { !it.isNullOrEmpty() }?.let { evaluateXFhirEnhancement(expression, it) } ?: emptySequence() return (fhirPathsEvaluatedPairs + variablesEvaluatedPairs).fold(expression.expression) { acc: String, pair: Pair -> @@ -400,8 +400,8 @@ object ExpressionEvaluator { questionnaireResponse: QuestionnaireResponse, questionnaireItemParentMap: Map, - variablesMap: MutableMap, - launchContextMap: Map?, + variablesMap: MutableMap = mutableMapOf(), + launchContextMap: Map? = mapOf(), ) { // First, check the questionnaire item itself val evaluatedValue = @@ -481,7 +481,7 @@ object ExpressionEvaluator { expression: Expression, questionnaireResponse: QuestionnaireResponse, dependentVariables: Map = mapOf(), - launchContextMap: Map?, + launchContextMap: Map? = mapOf(), ) = try { require(expression.name?.isNotBlank() == true) { diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index 6d1578b857..b84fe9a961 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -49,7 +49,7 @@ internal fun evaluateToBoolean( questionnaireResponse: QuestionnaireResponse, questionnaireResponseItemComponent: QuestionnaireResponseItemComponent, expression: String, - contextMap: Map, + contextMap: Map = mapOf(), ): Boolean { val expressionNode = fhirPathEngine.parse(expression) return fhirPathEngine.evaluateToBoolean( diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index f982b3f5ff..cf5c614d2e 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -59,8 +59,8 @@ object QuestionnaireResponseValidator { questionnaireResponse: QuestionnaireResponse, context: Context, questionnaireItemParentMap: - Map, - launchContextMap: Map?, + Map = mapOf(), + launchContextMap: Map? = mapOf(), ): Map> { require( questionnaireResponse.questionnaire == null || @@ -91,10 +91,10 @@ object QuestionnaireResponseValidator { context: Context, enablementEvaluator: EnablementEvaluator, linkIdToValidationResultMap: MutableMap>, - questionnaire: Questionnaire, + questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map, - launchContextMap: Map?, + Map = mapOf(), + launchContextMap: Map? = mapOf(), ): Map> { val questionnaireItemListIterator = questionnaireItemList.iterator() val questionnaireResponseItemListIterator = questionnaireResponseItemList.iterator() @@ -140,10 +140,10 @@ object QuestionnaireResponseValidator { context: Context, enablementEvaluator: EnablementEvaluator, linkIdToValidationResultMap: MutableMap>, - questionnaire: Questionnaire, + questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map, - launchContextMap: Map?, + Map = mapOf(), + launchContextMap: Map? = mapOf(), ): Map> { when (checkNotNull(questionnaireItem.type) { "Questionnaire item must have type" }) { diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt index 109b0c359d..2a0c881b24 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt @@ -82,9 +82,7 @@ class QuestionnaireValidationErrorMessageDialogFragmentTest { QuestionnaireResponseValidator.validateQuestionnaireResponse( questionnaire, questionnaireResponse, - RuntimeEnvironment.getApplication(), - mapOf(), - mapOf(), + RuntimeEnvironment.getApplication() ) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt index cf353335c0..97b33d7d89 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt @@ -53,13 +53,12 @@ class EnablementEvaluatorTest { type = Questionnaire.QuestionnaireItemType.BOOLEAN addEnableWhen(Questionnaire.QuestionnaireItemEnableWhenComponent().setQuestion("q2")) } - val questionnaire = Questionnaire().addItem(questionnaireItem) val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { linkId = "q1" } val questionnaireResponse = QuestionnaireResponse().apply { addItem(questionnaireResponseItem) } assertThat( EnablementEvaluator(questionnaireResponse) - .evaluate(questionnaireItem, questionnaireResponseItem, questionnaire, mapOf(), mapOf(),) + .evaluate(questionnaireItem, questionnaireResponseItem) ) .isFalse() } @@ -178,9 +177,6 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItem, questionnaireResponse.item[1], - questionnaire, - mapOf(), - mapOf(), ) ) .isTrue() @@ -260,9 +256,6 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItemComponent, questionnaireResponse.item[1], - questionnaire, - mapOf(), - mapOf(), ) ) .isFalse() @@ -342,9 +335,6 @@ class EnablementEvaluatorTest { .evaluate( questionnaireItem, questionnaireResponse.item[1], - questionnaire, - mapOf(), - mapOf(), ) ) .isTrue() @@ -769,7 +759,6 @@ class EnablementEvaluatorTest { behavior?.let { enableBehavior = it } type = Questionnaire.QuestionnaireItemType.BOOLEAN } - val questionnaire = Questionnaire().addItem(questionnaireItem) val questionnaireResponse = QuestionnaireResponse().apply { enableWhen.forEachIndexed { index, enableWhen -> @@ -788,13 +777,7 @@ class EnablementEvaluatorTest { } return assertThat( EnablementEvaluator(questionnaireResponse) - .evaluate( - questionnaireItem, - questionnaireResponse.item.last(), - questionnaire, - mapOf(), - mapOf(), - ) + .evaluate(questionnaireItem, questionnaireResponse.item.last()) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 0b241c319f..517cf136e1 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -68,8 +68,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.first(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("1") @@ -107,8 +105,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.last(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -163,8 +159,6 @@ class ExpressionEvaluatorTest { QuestionnaireResponse(), mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), questionnaire.item[0].item[0], - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -212,8 +206,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.last(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("3") @@ -241,8 +233,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.last(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) assertThat(result).isEqualTo(null) @@ -289,8 +279,6 @@ class ExpressionEvaluatorTest { QuestionnaireResponse(), mapOf(), questionnaire.item[0], - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -327,8 +315,6 @@ class ExpressionEvaluatorTest { QuestionnaireResponse(), mapOf(), questionnaire.item[0], - mutableMapOf(), - mapOf(), ) assertThat(result).isEqualTo(null) @@ -356,8 +342,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.first(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) } } @@ -385,8 +369,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.first(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) } } @@ -415,8 +397,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.first(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) } } @@ -444,8 +424,6 @@ class ExpressionEvaluatorTest { questionnaire.variableExpressions.first(), questionnaire, QuestionnaireResponse(), - mutableMapOf(), - mapOf(), ) } } @@ -506,8 +484,6 @@ class ExpressionEvaluatorTest { questionnaireResponse, mapOf(), questionnaire.item[0], - mutableMapOf(), - mapOf(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -568,8 +544,6 @@ class ExpressionEvaluatorTest { questionnaireResponse.item.elementAt(1), questionnaire, questionnaireResponse, - emptyMap(), - mapOf(), ) assertThat(result.first().second.first().asStringValue()) @@ -642,8 +616,6 @@ class ExpressionEvaluatorTest { questionnaireResponse.item.elementAt(1), questionnaire, questionnaireResponse, - emptyMap(), - mapOf(), ) assertThat(result.first().second.first().asStringValue()) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt index 705f3b0c45..48fa30de8c 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidatorTest.kt @@ -83,8 +83,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result["a-question"]!!.single()).isEqualTo(Valid) } @@ -117,8 +115,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result["a-question"]!!.single()) .isEqualTo( @@ -171,8 +167,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result["a-question"]) .containsExactly( @@ -242,8 +236,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result.keys).containsExactly("q1") assertThat(result["q1"]).containsExactly(Valid) @@ -295,8 +287,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result["question-1"]!!.single()).isEqualTo(Valid) } @@ -311,8 +301,6 @@ class QuestionnaireResponseValidatorTest { questionnaire = "http://www.sample-org/FHIR/Resources/Questionnaire/questionnaire-1" }, context, - mapOf(), - mapOf(), ) } @@ -332,8 +320,6 @@ class QuestionnaireResponseValidatorTest { Questionnaire().apply { url = "questionnaire-1" }, QuestionnaireResponse(), context, - mapOf(), - mapOf(), ) } @@ -402,8 +388,6 @@ class QuestionnaireResponseValidatorTest { addItem(QuestionnaireResponse.QuestionnaireResponseItemComponent(StringType("display-1"))) }, context, - mapOf(), - mapOf(), ) } @@ -427,8 +411,6 @@ class QuestionnaireResponseValidatorTest { addItem(QuestionnaireResponse.QuestionnaireResponseItemComponent(StringType("null-1"))) }, context, - mapOf(), - mapOf(), ) } @@ -467,8 +449,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) assertThat(result.entries.first().key).isEqualTo("valid-hidden-item") @@ -510,8 +490,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) .entries.first() @@ -1672,8 +1650,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) } assertThat(exception.message).isEqualTo(message) @@ -1691,8 +1667,6 @@ class QuestionnaireResponseValidatorTest { questionnaire, questionnaireResponse, context, - mapOf(), - mapOf(), ) } assertThat(exception.message).isEqualTo(message) diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index 168fcbf960..a2fa2b6808 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -59,8 +59,6 @@ class AddPatientViewModel(application: Application, private val state: SavedStat questionnaire, questionnaireResponse, getApplication(), - mapOf(), - mapOf(), ) .values .flatten() From cd974a9c29847ede2c84920fa48a5f9d2502b7d8 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 11:04:38 +0700 Subject: [PATCH 09/40] spotlessApply --- .../fhir/catalog/BehaviorListViewModel.kt | 2 +- catalog/src/main/res/values/strings.xml | 4 ++- .../enablement/EnablementEvaluator.kt | 3 +- .../fhirpath/ExpressionEvaluator.kt | 30 +++++++++++++++---- .../QuestionnaireResponseValidator.kt | 9 ++++-- .../android/fhir/demo/AddPatientViewModel.kt | 7 ++++- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt b/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt index 3fa8709e27..86df9c6314 100644 --- a/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt +++ b/catalog/src/main/java/com/google/android/fhir/catalog/BehaviorListViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/catalog/src/main/res/values/strings.xml b/catalog/src/main/res/values/strings.xml index 4595abe74f..30c54c4d6e 100644 --- a/catalog/src/main/res/values/strings.xml +++ b/catalog/src/main/res/values/strings.xml @@ -41,7 +41,9 @@ Review Read only Skip logic - Skip logic with expression + Skip logic with expression If Yes is selected, a follow-up question is displayed. If No is selected, no follow-up questions are displayed. diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 65bb82c2a9..55f8158ce1 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -105,7 +105,8 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map = mapOf(), + Map = + mapOf(), launchContextMap: Map? = mapOf(), ): Boolean { val enableWhenList = questionnaireItem.enableWhen 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 934f14b20c..bc3646f8d3 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 @@ -130,7 +130,8 @@ object ExpressionEvaluator { updatedQuestionnaireResponseItemComponent: QuestionnaireResponseItemComponent?, questionnaire: Questionnaire, questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map = mapOf(), + questionnaireItemParentMap: Map = + mapOf(), launchContextMap: Map? = mapOf(), ): List { return questionnaire.item @@ -206,7 +207,12 @@ object ExpressionEvaluator { launchContextMap, ) - return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap,) + return evaluateVariable( + expression, + questionnaireResponse, + variablesMap, + launchContextMap, + ) } /** @@ -285,7 +291,12 @@ object ExpressionEvaluator { } } - return evaluateVariable(expression, questionnaireResponse, variablesMap, launchContextMap,) + return evaluateVariable( + expression, + questionnaireResponse, + variablesMap, + launchContextMap, + ) } /** @@ -318,7 +329,10 @@ object ExpressionEvaluator { .map { Pair("{{%${it.key}}}", it.value!!.primitiveValue()) } val fhirPathsEvaluatedPairs = - launchContextMap.takeIf { !it.isNullOrEmpty() }?.let { evaluateXFhirEnhancement(expression, it) } ?: emptySequence() + launchContextMap + .takeIf { !it.isNullOrEmpty() } + ?.let { evaluateXFhirEnhancement(expression, it) } + ?: emptySequence() return (fhirPathsEvaluatedPairs + variablesEvaluatedPairs).fold(expression.expression) { acc: String, pair: Pair -> @@ -500,7 +514,13 @@ object ExpressionEvaluator { } } fhirPathEngine - .evaluate(contextMap, questionnaireResponse, null, null, expression.expression,) + .evaluate( + contextMap, + questionnaireResponse, + null, + null, + expression.expression, + ) .firstOrNull() } catch (exception: FHIRException) { Timber.w("Could not evaluate expression with FHIRPathEngine", exception) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index cf5c614d2e..8664239d69 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -59,7 +59,8 @@ object QuestionnaireResponseValidator { questionnaireResponse: QuestionnaireResponse, context: Context, questionnaireItemParentMap: - Map = mapOf(), + Map = + mapOf(), launchContextMap: Map? = mapOf(), ): Map> { require( @@ -93,7 +94,8 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap: MutableMap>, questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map = mapOf(), + Map = + mapOf(), launchContextMap: Map? = mapOf(), ): Map> { val questionnaireItemListIterator = questionnaireItemList.iterator() @@ -142,7 +144,8 @@ object QuestionnaireResponseValidator { linkIdToValidationResultMap: MutableMap>, questionnaire: Questionnaire = Questionnaire(), questionnaireItemParentMap: - Map = mapOf(), + Map = + mapOf(), launchContextMap: Map? = mapOf(), ): Map> { diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index a2fa2b6808..544452c0ad 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -68,7 +68,12 @@ class AddPatientViewModel(application: Application, private val state: SavedStat return@launch } - val entry = ResourceMapper.extract(questionnaire, questionnaireResponse,).entryFirstRep + val entry = + ResourceMapper.extract( + questionnaire, + questionnaireResponse, + ) + .entryFirstRep if (entry.resource !is Patient) { return@launch } From f49eb8e2fab1e174bd23c37f82de528d600756f6 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 4 Sep 2023 14:54:39 +0700 Subject: [PATCH 10/40] Change method name to avoid conflict with questionnaireJson variable --- .../java/com/google/android/fhir/demo/AddPatientViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt index 544452c0ad..fd24788475 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/AddPatientViewModel.kt @@ -39,7 +39,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat private var _questionnaireJson: String? = null val questionnaireJson: String - get() = getQuestionnaireJson() + get() = fetchQuestionnaireJson() val isPatientSaved = MutableLiveData() private val questionnaire: Questionnaire @@ -84,7 +84,7 @@ class AddPatientViewModel(application: Application, private val state: SavedStat } } - private fun getQuestionnaireJson(): String { + private fun fetchQuestionnaireJson(): String { _questionnaireJson?.let { return it } From c198e672ea02f7f3d98ee55cc89376354f1eb85e Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 08:47:35 +0700 Subject: [PATCH 11/40] Refactor evaluators - ExpressionEvaluator, EnablementEvaluator, EnabledAnswerOptionsEvaluator. - Moving the params from method to class constructor for easier use of methods by having less params. --- .../datacapture/QuestionnaireViewModel.kt | 53 ++-- .../enablement/EnablementEvaluator.kt | 30 +-- .../EnabledAnswerOptionsEvaluator.kt | 41 +-- .../fhirpath/ExpressionEvaluator.kt | 151 +++-------- .../QuestionnaireResponseValidator.kt | 36 +-- .../enablement/EnablementEvaluatorTest.kt | 29 +- .../fhirpath/ExpressionEvaluatorTest.kt | 252 ++++++++++++------ 7 files changed, 278 insertions(+), 314 deletions(-) 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 308621518c..d09281430d 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 @@ -46,9 +46,7 @@ import com.google.android.fhir.datacapture.extensions.shouldHaveNestedItemsUnder import com.google.android.fhir.datacapture.extensions.unpackRepeatedGroups import com.google.android.fhir.datacapture.extensions.validateLaunchContextExtensions import com.google.android.fhir.datacapture.extensions.zipByLinkId -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.detectExpressionCyclicDependency -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.evaluateCalculatedExpressions -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.evaluateExpression +import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import com.google.android.fhir.datacapture.validation.Invalid import com.google.android.fhir.datacapture.validation.NotValidated import com.google.android.fhir.datacapture.validation.QuestionnaireResponseItemValidator @@ -335,10 +333,19 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat modificationCount.update { it + 1 } } + private val expressionEvaluator: ExpressionEvaluator = + ExpressionEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) + private val answerOptionsEvaluator: EnabledAnswerOptionsEvaluator = EnabledAnswerOptionsEvaluator( questionnaire, - questionnaireLaunchContextMap, + questionnaireResponse, + expressionEvaluator, xFhirQueryResolver, externalValueSetResolver ) @@ -482,7 +489,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat .withIndex() .onEach { if (it.index == 0) { - detectExpressionCyclicDependency(questionnaire.item) + expressionEvaluator.detectExpressionCyclicDependency(questionnaire.item) questionnaire.item.flattened().forEach { qItem -> updateDependentQuestionnaireResponseItems( qItem, @@ -502,13 +509,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat updatedQuestionnaireItem: QuestionnaireItemComponent, updatedQuestionnaireResponseItem: QuestionnaireResponseItemComponent?, ) { - evaluateCalculatedExpressions( + expressionEvaluator + .evaluateCalculatedExpressions( updatedQuestionnaireItem, updatedQuestionnaireResponseItem, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) .forEach { (questionnaireItem, calculatedAnswers) -> // update all response item with updated values @@ -541,14 +545,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat if (!cqfExpression.isFhirPath) { throw UnsupportedOperationException("${cqfExpression.language} not supported yet") } - return evaluateExpression( - questionnaire, - questionnaireResponse, + return expressionEvaluator.evaluateExpression( questionnaireItem, questionnaireResponseItem, cqfExpression, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) } @@ -657,13 +657,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat // Hidden questions should not get QuestionnaireItemViewItem instances if (questionnaireItem.isHidden) return emptyList() val enabled = - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( questionnaireItem, questionnaireResponseItem, - questionnaire, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) // Disabled questions should not get QuestionnaireItemViewItem instances if (!enabled) { @@ -698,9 +695,6 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat answerOptionsEvaluator.evaluate( questionnaireItem, questionnaireResponseItem, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) if (disabledQuestionnaireResponseAnswers.isNotEmpty()) { removeDisabledAnswers( @@ -724,13 +718,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat enabledDisplayItems = questionnaireItem.item.filter { it.isDisplayItem && - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( it, questionnaireResponseItem, - questionnaire, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) }, questionViewTextConfiguration = @@ -808,7 +799,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireItemList: List, questionnaireResponseItemList: List, ): List { - val enablementEvaluator = EnablementEvaluator(questionnaireResponse) + val enablementEvaluator = EnablementEvaluator(questionnaireResponse, expressionEvaluator) val responseItemKeys = questionnaireResponseItemList.map { it.linkId } return questionnaireItemList .asSequence() @@ -818,9 +809,6 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat enablementEvaluator.evaluate( questionnaireItem, questionnaireResponseItem, - questionnaire, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ) } .map { (questionnaireItem, questionnaireResponseItem) -> @@ -849,13 +837,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat -> QuestionnairePage( index, - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( questionnaireItem, questionnaireResponseItem, - questionnaire, - questionnaireItemParentMap, - questionnaireLaunchContextMap, ), questionnaireItem.isHidden ) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 55f8158ce1..5800d92426 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -22,10 +22,8 @@ import com.google.android.fhir.datacapture.extensions.enableWhenExpression import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import com.google.android.fhir.datacapture.fhirpath.evaluateToBoolean import com.google.android.fhir.equals -import org.hl7.fhir.r4.model.Base import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse -import org.hl7.fhir.r4.model.Resource /** * Evaluator for the enablement status of a [Questionnaire.QuestionnaireItemComponent]. @@ -62,7 +60,10 @@ import org.hl7.fhir.r4.model.Resource * [Questionnaire.item.enableBehavior](https://www.hl7.org/fhir/questionnaire-definitions.html#Questionnaire.item.enableBehavior) * . */ -internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireResponse) { +internal class EnablementEvaluator( + private val questionnaireResponse: QuestionnaireResponse, + private val expressionEvaluator: ExpressionEvaluator, +) { /** * The pre-order traversal trace of the items in the [QuestionnaireResponse]. This essentially * represents the order in which all items are displayed in the UI. @@ -103,11 +104,6 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo fun evaluate( questionnaireItem: Questionnaire.QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, - questionnaire: Questionnaire = Questionnaire(), - questionnaireItemParentMap: - Map = - mapOf(), - launchContextMap: Map? = mapOf(), ): Boolean { val enableWhenList = questionnaireItem.enableWhen val enableWhenExpression = questionnaireItem.enableWhenExpression @@ -119,20 +115,10 @@ internal class EnablementEvaluator(val questionnaireResponse: QuestionnaireRespo // Evaluate `enableWhenExpression`. if (enableWhenExpression != null && enableWhenExpression.hasExpression()) { val contextMap = - mutableMapOf().apply { - ExpressionEvaluator.extractDependentVariables( - questionnaireItem.enableWhenExpression!!, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireItem, - this, - launchContextMap, - ) - if (launchContextMap != null) { - putAll(launchContextMap) - } - } + expressionEvaluator.extractDependentVariables( + questionnaireItem.enableWhenExpression!!, + questionnaireItem, + ) return evaluateToBoolean( questionnaireResponse, questionnaireResponseItem, diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index 2878b3c30a..4e7fc7885d 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -29,15 +29,15 @@ import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent import org.hl7.fhir.r4.model.QuestionnaireResponse -import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.ResourceType import org.hl7.fhir.r4.model.ValueSet internal class EnabledAnswerOptionsEvaluator( private val questionnaire: Questionnaire, - private val questionnaireLaunchContextMap: Map?, + private val questionnaireResponse: QuestionnaireResponse, + private val expressionEvaluator: ExpressionEvaluator, private val xFhirQueryResolver: XFhirQueryResolver?, - private val externalValueSetResolver: ExternalAnswerValueSetResolver? + private val externalValueSetResolver: ExternalAnswerValueSetResolver?, ) { private val answerValueSetMap = @@ -61,16 +61,12 @@ internal class EnabledAnswerOptionsEvaluator( internal suspend fun evaluate( questionnaireItem: QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map, - launchContextMap: Map? = mapOf(), ): Pair< List, List > { - val resolvedAnswerOptions = - answerOptions(questionnaireItem, questionnaireResponse, questionnaireItemParentMap) + val resolvedAnswerOptions = answerOptions(questionnaireItem) if (questionnaireItem.answerOptionsToggleExpressions.isEmpty()) return Pair(resolvedAnswerOptions, emptyList()) @@ -79,10 +75,7 @@ internal class EnabledAnswerOptionsEvaluator( evaluateAnswerOptionsToggleExpressions( questionnaireItem, questionnaireResponseItem, - questionnaireResponse, resolvedAnswerOptions, - questionnaireItemParentMap, - launchContextMap, ) val disabledAnswers = questionnaireResponseItem.answer @@ -109,19 +102,12 @@ internal class EnabledAnswerOptionsEvaluator( */ private suspend fun answerOptions( questionnaireItem: QuestionnaireItemComponent, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map ): List = when { questionnaireItem.answerOption.isNotEmpty() -> questionnaireItem.answerOption !questionnaireItem.answerValueSet.isNullOrEmpty() -> resolveAnswerValueSet(questionnaireItem.answerValueSet) - questionnaireItem.answerExpression != null -> - resolveAnswerExpression( - questionnaireItem, - questionnaireResponse, - questionnaireItemParentMap - ) + questionnaireItem.answerExpression != null -> resolveAnswerExpression(questionnaireItem) else -> emptyList() } @@ -168,8 +154,6 @@ internal class EnabledAnswerOptionsEvaluator( // https://build.fhir.org/ig/HL7/sdc/expressions.html#x-fhir-query-enhancements private suspend fun resolveAnswerExpression( item: QuestionnaireItemComponent, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map ): List { // Check cache first for database queries val answerExpression = item.answerExpression ?: return emptyList() @@ -178,13 +162,9 @@ internal class EnabledAnswerOptionsEvaluator( answerExpression.isXFhirQuery -> { xFhirQueryResolver?.let { xFhirQueryResolver -> val xFhirExpressionString = - ExpressionEvaluator.createXFhirQueryFromExpression( - questionnaire, - questionnaireResponse, + expressionEvaluator.createXFhirQueryFromExpression( item, - questionnaireItemParentMap, answerExpression, - questionnaireLaunchContextMap ) if (answerExpressionMap.containsKey(xFhirExpressionString)) { answerExpressionMap[xFhirExpressionString] @@ -214,10 +194,7 @@ internal class EnabledAnswerOptionsEvaluator( private fun evaluateAnswerOptionsToggleExpressions( item: QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, - questionnaireResponse: QuestionnaireResponse, answerOptions: List, - questionnaireItemParentMap: Map, - launchContextMap: Map?, ): List { val results = item.answerOptionsToggleExpressions @@ -226,14 +203,10 @@ internal class EnabledAnswerOptionsEvaluator( val evaluationResult = if (expression.isFhirPath) fhirPathEngine.convertToBoolean( - ExpressionEvaluator.evaluateExpression( - questionnaire, - questionnaireResponse, + expressionEvaluator.evaluateExpression( item, questionnaireResponseItem, expression, - questionnaireItemParentMap, - launchContextMap, ) ) else 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 bc3646f8d3..02ab244d54 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 @@ -16,6 +16,7 @@ package com.google.android.fhir.datacapture.fhirpath +import android.util.Log import com.google.android.fhir.datacapture.extensions.calculatedExpression import com.google.android.fhir.datacapture.extensions.findVariableExpression import com.google.android.fhir.datacapture.extensions.flattened @@ -40,7 +41,14 @@ import timber.log.Timber * [variable expression](http://hl7.org/fhir/R4/extension-variable.html) defined at either * questionnaire level or questionnaire item level. */ -object ExpressionEvaluator { +internal class ExpressionEvaluator( + private val questionnaire: Questionnaire, + private val questionnaireResponse: QuestionnaireResponse, + private val questionnaireItemParentMap: + Map = + mapOf(), + private val questionnaireLaunchContextMap: Map? = mapOf(), +) { private val reservedVariables = listOf("sct", "loinc", "ucum", "resource", "rootResource", "context", "map-codes") @@ -64,9 +72,7 @@ object ExpressionEvaluator { private val xFhirQueryEnhancementRegex = Regex("\\{\\{(.*?)\\}\\}") /** Detects if any item into list is referencing a dependent item in its calculated expression */ - internal fun detectExpressionCyclicDependency( - items: List - ) { + internal fun detectExpressionCyclicDependency(items: List) { items .flattened() .filter { it.calculatedExpression != null } @@ -92,26 +98,11 @@ object ExpressionEvaluator { * %resource = [QuestionnaireResponse] %context = [QuestionnaireResponseItemComponent] */ fun evaluateExpression( - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, questionnaireItem: QuestionnaireItemComponent, questionnaireResponseItem: QuestionnaireResponseItemComponent?, expression: Expression, - questionnaireItemParentMap: Map, - launchContextMap: Map? = mapOf(), ): List { - val appContext = - mutableMapOf().apply { - extractDependentVariables( - expression, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireItem, - this, - launchContextMap, - ) - } + val appContext = extractDependentVariables(expression, questionnaireItem) return fhirPathEngine.evaluate( appContext, questionnaireResponse, @@ -128,11 +119,6 @@ object ExpressionEvaluator { fun evaluateCalculatedExpressions( updatedQuestionnaireItem: QuestionnaireItemComponent, updatedQuestionnaireResponseItemComponent: QuestionnaireResponseItemComponent?, - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: Map = - mapOf(), - launchContextMap: Map? = mapOf(), ): List { return questionnaire.item .flattened() @@ -146,13 +132,9 @@ object ExpressionEvaluator { .map { questionnaireItem -> val updatedAnswer = evaluateExpression( - questionnaire, - questionnaireResponse, questionnaireItem, updatedQuestionnaireResponseItemComponent, questionnaireItem.calculatedExpression!!, - questionnaireItemParentMap, - launchContextMap, ) .map { it.castToType(it) } questionnaireItem to updatedAnswer @@ -184,13 +166,8 @@ object ExpressionEvaluator { */ internal fun evaluateQuestionnaireItemVariableExpression( expression: Expression, - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: - Map, - questionnaireItem: Questionnaire.QuestionnaireItemComponent, + questionnaireItem: QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? = mapOf(), ): Base? { require( questionnaireItem.variableExpressions.any { @@ -199,19 +176,13 @@ object ExpressionEvaluator { ) { "The expression should come from the same questionnaire item" } extractDependentVariables( expression, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, questionnaireItem, variablesMap, - launchContextMap, ) return evaluateVariable( expression, - questionnaireResponse, variablesMap, - launchContextMap, ) } @@ -230,27 +201,22 @@ object ExpressionEvaluator { */ internal fun extractDependentVariables( expression: Expression, - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: - Map, - questionnaireItem: Questionnaire.QuestionnaireItemComponent, + questionnaireItem: QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? = mapOf(), - ) = + ): MutableMap { findDependentVariables(expression).forEach { variableName -> if (variablesMap[variableName] == null) { findAndEvaluateVariable( variableName, questionnaireItem, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, variablesMap, - launchContextMap, ) } } + Log.d("FIKRI", questionnaireLaunchContextMap?.size.toString()) + questionnaireLaunchContextMap?.let { variablesMap.putAll(it) } + return variablesMap + } /** * Evaluates variable expression defined at questionnaire level and returns the evaluated result. @@ -271,10 +237,7 @@ object ExpressionEvaluator { */ internal fun evaluateQuestionnaireVariableExpression( expression: Expression, - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? = mapOf(), ): Base? { findDependentVariables(expression).forEach { variableName -> questionnaire.findVariableExpression(variableName)?.let { expression -> @@ -282,10 +245,7 @@ object ExpressionEvaluator { variablesMap[expression.name] = evaluateQuestionnaireVariableExpression( expression, - questionnaire, - questionnaireResponse, variablesMap, - launchContextMap, ) } } @@ -293,9 +253,7 @@ object ExpressionEvaluator { return evaluateVariable( expression, - questionnaireResponse, variablesMap, - launchContextMap, ) } @@ -304,35 +262,24 @@ object ExpressionEvaluator { * fhir-paths in the expression. */ internal fun createXFhirQueryFromExpression( - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, questionnaireItem: QuestionnaireItemComponent, - questionnaireItemParentMap: Map, expression: Expression, - launchContextMap: Map? = mapOf(), ): String { // get all dependent variables and their evaluated values val variablesEvaluatedPairs = - mutableMapOf() - .apply { - extractDependentVariables( - expression, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireItem, - this, - launchContextMap, - ) - } + extractDependentVariables( + expression, + questionnaireItem, + ) .filterKeys { expression.expression.contains("{{%$it}}") } .map { Pair("{{%${it.key}}}", it.value!!.primitiveValue()) } val fhirPathsEvaluatedPairs = - launchContextMap + questionnaireLaunchContextMap .takeIf { !it.isNullOrEmpty() } ?.let { evaluateXFhirEnhancement(expression, it) } ?: emptySequence() + return (fhirPathsEvaluatedPairs + variablesEvaluatedPairs).fold(expression.expression) { acc: String, pair: Pair -> @@ -347,7 +294,7 @@ object ExpressionEvaluator { * * @param expression x-fhir-query expression containing a FHIRpath, e.g. * Practitioner?active=true&{{Practitioner.name.family}} - * @param launchContextMap the launch context to evaluate the expression against + * @param questionnaireLaunchContextMap the launch context to evaluate the expression against */ private fun evaluateXFhirEnhancement( expression: Expression, @@ -409,46 +356,30 @@ object ExpressionEvaluator { */ private fun findAndEvaluateVariable( variableName: String, - questionnaireItem: Questionnaire.QuestionnaireItemComponent, - questionnaire: Questionnaire, - questionnaireResponse: QuestionnaireResponse, - questionnaireItemParentMap: - Map, + questionnaireItem: QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), - launchContextMap: Map? = mapOf(), ) { // First, check the questionnaire item itself val evaluatedValue = questionnaireItem.findVariableExpression(variableName)?.let { expression -> evaluateQuestionnaireItemVariableExpression( expression, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, questionnaireItem, variablesMap, - launchContextMap, ) } // Secondly, check the ancestors of the questionnaire item - ?: findVariableInAncestors(variableName, questionnaireItemParentMap, questionnaireItem) - ?.let { (questionnaireItem, expression) -> - evaluateQuestionnaireItemVariableExpression( - expression, - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - questionnaireItem, - variablesMap, - launchContextMap, - ) - } // Finally, check the variables defined on the questionnaire itself + ?: findVariableInAncestors(variableName, questionnaireItem)?.let { + (questionnaireItem, expression) -> + evaluateQuestionnaireItemVariableExpression( + expression, + questionnaireItem, + variablesMap, + ) + } // Finally, check the variables defined on the questionnaire itself ?: questionnaire.findVariableExpression(variableName)?.let { expression -> evaluateQuestionnaireVariableExpression( expression, - questionnaire, - questionnaireResponse, variablesMap, - launchContextMap, ) } @@ -468,10 +399,8 @@ object ExpressionEvaluator { */ private fun findVariableInAncestors( variableName: String, - questionnaireItemParentMap: - Map, - questionnaireItem: Questionnaire.QuestionnaireItemComponent - ): Pair? { + questionnaireItem: QuestionnaireItemComponent + ): Pair? { var parent = questionnaireItemParentMap[questionnaireItem] while (parent != null) { val expression = parent.findVariableExpression(variableName) @@ -493,9 +422,7 @@ object ExpressionEvaluator { */ private fun evaluateVariable( expression: Expression, - questionnaireResponse: QuestionnaireResponse, dependentVariables: Map = mapOf(), - launchContextMap: Map? = mapOf(), ) = try { require(expression.name?.isNotBlank() == true) { @@ -509,8 +436,8 @@ object ExpressionEvaluator { val contextMap = mutableMapOf().apply { putAll(dependentVariables) - if (launchContextMap != null) { - putAll(launchContextMap) + if (questionnaireLaunchContextMap != null) { + putAll(questionnaireLaunchContextMap) } } fhirPathEngine @@ -529,4 +456,4 @@ object ExpressionEvaluator { } /** Pair of a [Questionnaire.QuestionnaireItemComponent] with its evaluated answers */ -internal typealias ItemToAnswersPair = Pair> +internal typealias ItemToAnswersPair = Pair> diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index 8664239d69..9f7ac71706 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -19,6 +19,7 @@ package com.google.android.fhir.datacapture.validation import android.content.Context import com.google.android.fhir.datacapture.enablement.EnablementEvaluator import com.google.android.fhir.datacapture.extensions.packRepeatedGroups +import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse import org.hl7.fhir.r4.model.Resource @@ -72,15 +73,20 @@ object QuestionnaireResponseValidator { val linkIdToValidationResultMap = mutableMapOf>() + val expressionEvaluator = + ExpressionEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + launchContextMap + ) + validateQuestionnaireResponseItems( questionnaire.item, questionnaireResponse.item, context, - EnablementEvaluator(questionnaireResponse), + EnablementEvaluator(questionnaireResponse, expressionEvaluator), linkIdToValidationResultMap, - questionnaire, - questionnaireItemParentMap, - launchContextMap, ) return linkIdToValidationResultMap @@ -92,11 +98,6 @@ object QuestionnaireResponseValidator { context: Context, enablementEvaluator: EnablementEvaluator, linkIdToValidationResultMap: MutableMap>, - questionnaire: Questionnaire = Questionnaire(), - questionnaireItemParentMap: - Map = - mapOf(), - launchContextMap: Map? = mapOf(), ): Map> { val questionnaireItemListIterator = questionnaireItemList.iterator() val questionnaireResponseItemListIterator = questionnaireResponseItemList.iterator() @@ -115,9 +116,6 @@ object QuestionnaireResponseValidator { enablementEvaluator.evaluate( questionnaireItem, questionnaireResponseItem, - questionnaire, - questionnaireItemParentMap, - launchContextMap, ) if (enabled) { @@ -127,9 +125,6 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, - questionnaire, - questionnaireItemParentMap, - launchContextMap, ) } } @@ -142,11 +137,6 @@ object QuestionnaireResponseValidator { context: Context, enablementEvaluator: EnablementEvaluator, linkIdToValidationResultMap: MutableMap>, - questionnaire: Questionnaire = Questionnaire(), - questionnaireItemParentMap: - Map = - mapOf(), - launchContextMap: Map? = mapOf(), ): Map> { when (checkNotNull(questionnaireItem.type) { "Questionnaire item must have type" }) { @@ -161,9 +151,6 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, - questionnaire, - questionnaireItemParentMap, - launchContextMap, ) else -> { require(questionnaireItem.repeats || questionnaireResponseItem.answer.size <= 1) { @@ -177,9 +164,6 @@ object QuestionnaireResponseValidator { context, enablementEvaluator, linkIdToValidationResultMap, - questionnaire, - questionnaireItemParentMap, - launchContextMap, ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt index 97b33d7d89..39eed18823 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt @@ -19,6 +19,7 @@ package com.google.android.fhir.datacapture.enablement import android.os.Build import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.parser.IParser +import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import com.google.common.truth.BooleanSubject import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking @@ -53,11 +54,13 @@ class EnablementEvaluatorTest { type = Questionnaire.QuestionnaireItemType.BOOLEAN addEnableWhen(Questionnaire.QuestionnaireItemEnableWhenComponent().setQuestion("q2")) } + val questionnaire = Questionnaire().apply { addItem(questionnaireItem) } val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { linkId = "q1" } val questionnaireResponse = QuestionnaireResponse().apply { addItem(questionnaireResponseItem) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) assertThat( - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate(questionnaireItem, questionnaireResponseItem) ) .isFalse() @@ -158,7 +161,7 @@ class EnablementEvaluatorTest { "linkId": "2" } ] - } + } """.trimIndent() val questionnaire = @@ -172,8 +175,10 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + assertThat( - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( questionnaireItem, questionnaireResponse.item[1], @@ -238,7 +243,7 @@ class EnablementEvaluatorTest { "linkId": "2" } ] - } + } """.trimIndent() val questionnaire = @@ -251,8 +256,10 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + assertThat( - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( questionnaireItemComponent, questionnaireResponse.item[1], @@ -317,7 +324,7 @@ class EnablementEvaluatorTest { "linkId": "female" } ] - } + } """.trimIndent() val questionnaire = @@ -330,8 +337,10 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + assertThat( - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate( questionnaireItem, questionnaireResponse.item[1], @@ -759,6 +768,7 @@ class EnablementEvaluatorTest { behavior?.let { enableBehavior = it } type = Questionnaire.QuestionnaireItemType.BOOLEAN } + val questionnaire = Questionnaire().apply { addItem(questionnaireItem) } val questionnaireResponse = QuestionnaireResponse().apply { enableWhen.forEachIndexed { index, enableWhen -> @@ -775,8 +785,11 @@ class EnablementEvaluatorTest { QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { linkId = "target" } ) } + + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + return assertThat( - EnablementEvaluator(questionnaireResponse) + EnablementEvaluator(questionnaireResponse, expressionEvaluator) .evaluate(questionnaireItem, questionnaireResponse.item.last()) ) } diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 517cf136e1..3c04c7b2ea 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -22,8 +22,6 @@ import com.google.android.fhir.datacapture.extensions.EXTENSION_VARIABLE_URL import com.google.android.fhir.datacapture.extensions.answerExpression import com.google.android.fhir.datacapture.extensions.asStringValue import com.google.android.fhir.datacapture.extensions.variableExpressions -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.detectExpressionCyclicDependency -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.evaluateCalculatedExpressions import com.google.common.truth.Truth.assertThat import java.util.Calendar import java.util.Date @@ -63,11 +61,11 @@ class ExpressionEvaluatorTest { } } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), - questionnaire, - QuestionnaireResponse(), ) assertThat((result as Type).asStringValue()).isEqualTo("1") @@ -100,11 +98,11 @@ class ExpressionEvaluatorTest { } } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), - questionnaire, - QuestionnaireResponse(), ) assertThat((result as Type).asStringValue()).isEqualTo("2") @@ -152,12 +150,16 @@ class ExpressionEvaluatorTest { ) } - val result = - ExpressionEvaluator.evaluateQuestionnaireItemVariableExpression( - questionnaire.item[0].item[0].variableExpressions.last(), + val expressionEvaluator = + ExpressionEvaluator( questionnaire, QuestionnaireResponse(), - mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]) + ) + + val result = + expressionEvaluator.evaluateQuestionnaireItemVariableExpression( + questionnaire.item[0].item[0].variableExpressions.last(), questionnaire.item[0].item[0], ) @@ -201,11 +203,11 @@ class ExpressionEvaluatorTest { } } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), - questionnaire, - QuestionnaireResponse(), ) assertThat((result as Type).asStringValue()).isEqualTo("3") @@ -228,11 +230,11 @@ class ExpressionEvaluatorTest { } } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.last(), - questionnaire, - QuestionnaireResponse(), ) assertThat(result).isEqualTo(null) @@ -272,12 +274,11 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireItemVariableExpression( + expressionEvaluator.evaluateQuestionnaireItemVariableExpression( questionnaire.item[0].variableExpressions.last(), - questionnaire, - QuestionnaireResponse(), - mapOf(), questionnaire.item[0], ) @@ -308,12 +309,11 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val result = - ExpressionEvaluator.evaluateQuestionnaireItemVariableExpression( + expressionEvaluator.evaluateQuestionnaireItemVariableExpression( questionnaire.item[0].variableExpressions.last(), - questionnaire, - QuestionnaireResponse(), - mapOf(), questionnaire.item[0], ) @@ -338,10 +338,10 @@ class ExpressionEvaluatorTest { } } - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), - questionnaire, - QuestionnaireResponse(), ) } } @@ -365,10 +365,10 @@ class ExpressionEvaluatorTest { } } - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), - questionnaire, - QuestionnaireResponse(), ) } } @@ -393,10 +393,10 @@ class ExpressionEvaluatorTest { } } - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), - questionnaire, - QuestionnaireResponse(), ) } } @@ -420,10 +420,10 @@ class ExpressionEvaluatorTest { } } - ExpressionEvaluator.evaluateQuestionnaireVariableExpression( + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + + expressionEvaluator.evaluateQuestionnaireVariableExpression( questionnaire.variableExpressions.first(), - questionnaire, - QuestionnaireResponse(), ) } } @@ -477,12 +477,11 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + val result = - ExpressionEvaluator.evaluateQuestionnaireItemVariableExpression( + expressionEvaluator.evaluateQuestionnaireItemVariableExpression( questionnaire.item[0].variableExpressions.last(), - questionnaire, - questionnaireResponse, - mapOf(), questionnaire.item[0], ) @@ -538,12 +537,12 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + val result = - evaluateCalculatedExpressions( + expressionEvaluator.evaluateCalculatedExpressions( questionnaire.item.elementAt(1), questionnaireResponse.item.elementAt(1), - questionnaire, - questionnaireResponse, ) assertThat(result.first().second.first().asStringValue()) @@ -610,12 +609,12 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) + val result = - evaluateCalculatedExpressions( + expressionEvaluator.evaluateCalculatedExpressions( questionnaire.item.elementAt(1), questionnaireResponse.item.elementAt(1), - questionnaire, - questionnaireResponse, ) assertThat(result.first().second.first().asStringValue()) @@ -667,9 +666,11 @@ class ExpressionEvaluatorTest { ) } + val expressionEvaluator = ExpressionEvaluator(questionnaire, QuestionnaireResponse()) + val exception = assertThrows(null, IllegalStateException::class.java) { - detectExpressionCyclicDependency(questionnaire.item) + expressionEvaluator.detectExpressionCyclicDependency(questionnaire.item) } assertThat(exception.message) .isEqualTo("a-birthdate and a-age-years have cyclic dependency in expression based extension") @@ -684,14 +685,18 @@ class ExpressionEvaluatorTest { "Practitioner?var1={{random}}&var2={{ random }}&var3={{ random}}&var4={{random }}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), + mapOf(), + mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()) + ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( Questionnaire.QuestionnaireItemComponent(), - emptyMap(), expression, - mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()) ) assertThat(expressionsToEvaluate).isEqualTo("Practitioner?var1=&var2=&var3=&var4=") @@ -712,14 +717,18 @@ class ExpressionEvaluatorTest { this.expression = "Practitioner?gender={{Practitioner.gender}}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), + mapOf(), + mapOf(practitioner.resourceType.name to practitioner) + ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( Questionnaire.QuestionnaireItemComponent(), - emptyMap(), expression, - mapOf(practitioner.resourceType.name to practitioner) ) assertThat(expressionsToEvaluate).isEqualTo("Practitioner?gender=") } @@ -740,14 +749,18 @@ class ExpressionEvaluatorTest { this.expression = "Practitioner?gender={{Practitioner.gender}}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), + mapOf(), + mapOf(practitioner.resourceType.name.lowercase() to practitioner) + ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( Questionnaire.QuestionnaireItemComponent(), - emptyMap(), expression, - mapOf(practitioner.resourceType.name.lowercase() to practitioner) ) assertThat(expressionsToEvaluate).isEqualTo("Practitioner?gender=male") } @@ -768,14 +781,18 @@ class ExpressionEvaluatorTest { this.expression = "Practitioner?gender={{%patient.gender}}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), + mapOf(), + mapOf(practitioner.resourceType.name to practitioner) + ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( Questionnaire.QuestionnaireItemComponent(), - emptyMap(), expression, - mapOf(practitioner.resourceType.name to practitioner) ) assertThat(expressionsToEvaluate).isEqualTo("Practitioner?gender=") } @@ -796,14 +813,18 @@ class ExpressionEvaluatorTest { this.expression = "Patient?family={{%patient.name.family}}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), + mapOf(), + mapOf(patient.resourceType.name.lowercase() to patient) + ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( Questionnaire.QuestionnaireItemComponent(), - emptyMap(), expression, - mapOf(patient.resourceType.name.lowercase() to patient) ) assertThat(expressionsToEvaluate).isEqualTo("Patient?family=John") } @@ -838,23 +859,27 @@ class ExpressionEvaluatorTest { "Patient?family={{%patient.name.family}}&address-city={{%location.address.city}}" } - val expressionsToEvaluate = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - Questionnaire.QuestionnaireItemComponent(), - emptyMap(), - expression, + mapOf(), mapOf( patient.resourceType.name.lowercase() to patient, location.resourceType.name.lowercase() to location ) ) + + val expressionsToEvaluate = + expressionEvaluator.createXFhirQueryFromExpression( + Questionnaire.QuestionnaireItemComponent(), + expression, + ) assertThat(expressionsToEvaluate).isEqualTo("Patient?family=John&address-city=NAIROBI") } @Test - fun `createXFhirQueryFromExpression() should evaluate variables in answer expression`() { + fun `createXFhirQueryFromExpression() should evaluate variables in answer expression when launch context is null`() { val questionnaire = Questionnaire().apply { id = "a-questionnaire" @@ -903,14 +928,85 @@ class ExpressionEvaluatorTest { ) } - val result = - ExpressionEvaluator.createXFhirQueryFromExpression( + val expressionEvaluator = + ExpressionEvaluator( questionnaire, QuestionnaireResponse(), + mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + null + ) + + val result = + expressionEvaluator.createXFhirQueryFromExpression( questionnaire.item[0].item[0], + questionnaire.item[0].item[0].answerExpression!!, + ) + + assertThat(result).isEqualTo("Patient?address-city=1&gender=2") + } + + @Test + fun `createXFhirQueryFromExpression() should evaluate variables in answer expression when launch context in empty`() { + val questionnaire = + Questionnaire().apply { + id = "a-questionnaire" + addItem( + Questionnaire.QuestionnaireItemComponent().apply { + linkId = "a-group-item" + text = "a question" + type = Questionnaire.QuestionnaireItemType.GROUP + addExtension().apply { + url = EXTENSION_VARIABLE_URL + setValue( + Expression().apply { + name = "A" + language = "text/fhirpath" + expression = "1" + } + ) + } + addExtension().apply { + url = EXTENSION_VARIABLE_URL + setValue( + Expression().apply { + name = "B" + language = "text/fhirpath" + expression = "2" + } + ) + } + addItem( + Questionnaire.QuestionnaireItemComponent().apply { + linkId = "an-item" + text = "a question" + type = Questionnaire.QuestionnaireItemType.TEXT + addExtension().apply { + url = EXTENSION_ANSWER_EXPRESSION_URL + setValue( + Expression().apply { + language = "application/x-fhir-query" + expression = "Patient?address-city={{%A}}&gender={{%B}}" + } + ) + } + } + ) + } + ) + } + + val expressionEvaluator = + ExpressionEvaluator( + questionnaire, + QuestionnaireResponse(), mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + mapOf() + ) + + val result = + expressionEvaluator.createXFhirQueryFromExpression( + questionnaire.item[0].item[0], questionnaire.item[0].item[0].answerExpression!!, - null ) assertThat(result).isEqualTo("Patient?address-city=1&gender=2") From 035d173c844ce44fc5ea6a86f4f7a6b69f8daa47 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 09:45:29 +0700 Subject: [PATCH 12/40] Also tie enablementEvaluator lifecycle to viewmodel --- .../datacapture/QuestionnaireViewModel.kt | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) 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 d09281430d..5255eda8d7 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 @@ -341,6 +341,9 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireLaunchContextMap ) + private val enablementEvaluator: EnablementEvaluator = + EnablementEvaluator(questionnaireResponse, expressionEvaluator) + private val answerOptionsEvaluator: EnabledAnswerOptionsEvaluator = EnabledAnswerOptionsEvaluator( questionnaire, @@ -657,11 +660,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat // Hidden questions should not get QuestionnaireItemViewItem instances if (questionnaireItem.isHidden) return emptyList() val enabled = - EnablementEvaluator(questionnaireResponse, expressionEvaluator) - .evaluate( - questionnaireItem, - questionnaireResponseItem, - ) + enablementEvaluator.evaluate( + questionnaireItem, + questionnaireResponseItem, + ) // Disabled questions should not get QuestionnaireItemViewItem instances if (!enabled) { cacheDisabledQuestionnaireItemAnswers(questionnaireResponseItem) @@ -718,11 +720,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat enabledDisplayItems = questionnaireItem.item.filter { it.isDisplayItem && - EnablementEvaluator(questionnaireResponse, expressionEvaluator) - .evaluate( - it, - questionnaireResponseItem, - ) + enablementEvaluator.evaluate( + it, + questionnaireResponseItem, + ) }, questionViewTextConfiguration = QuestionTextConfiguration( @@ -799,7 +800,6 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireItemList: List, questionnaireResponseItemList: List, ): List { - val enablementEvaluator = EnablementEvaluator(questionnaireResponse, expressionEvaluator) val responseItemKeys = questionnaireResponseItemList.map { it.linkId } return questionnaireItemList .asSequence() @@ -837,11 +837,10 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat -> QuestionnairePage( index, - EnablementEvaluator(questionnaireResponse, expressionEvaluator) - .evaluate( - questionnaireItem, - questionnaireResponseItem, - ), + enablementEvaluator.evaluate( + questionnaireItem, + questionnaireResponseItem, + ), questionnaireItem.isHidden ) } From 0f321d68504047f5756298d03f977b11d5c3fea9 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 10:42:50 +0700 Subject: [PATCH 13/40] get latest questionnaire state to see calculated expression result in UI --- .../google/android/fhir/datacapture/QuestionnaireViewModel.kt | 1 + 1 file changed, 1 insertion(+) 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 5255eda8d7..a77a43cd9d 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 @@ -499,6 +499,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponse.allItems.find { qrItem -> qrItem.linkId == qItem.linkId } ) } + modificationCount.update { it + 1 } } } .map { it.value } From 518c279d6d714008554c40e10a3fa6fb23b1470f Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 10:43:01 +0700 Subject: [PATCH 14/40] Remove unused log --- .../android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt | 2 -- 1 file changed, 2 deletions(-) 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 02ab244d54..b38e5da99d 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 @@ -16,7 +16,6 @@ package com.google.android.fhir.datacapture.fhirpath -import android.util.Log import com.google.android.fhir.datacapture.extensions.calculatedExpression import com.google.android.fhir.datacapture.extensions.findVariableExpression import com.google.android.fhir.datacapture.extensions.flattened @@ -213,7 +212,6 @@ internal class ExpressionEvaluator( ) } } - Log.d("FIKRI", questionnaireLaunchContextMap?.size.toString()) questionnaireLaunchContextMap?.let { variablesMap.putAll(it) } return variablesMap } From 17370e3f8748975f5a52fd6458792dcb06d8d096 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 10:46:19 +0700 Subject: [PATCH 15/40] Fix quantity initial value not showing in catalog app Out of topic, my hands can't resist fixing this issue. --- .../behavior_calculated_expression.json | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/catalog/src/main/assets/behavior_calculated_expression.json b/catalog/src/main/assets/behavior_calculated_expression.json index e2fa4764d3..525399cda8 100644 --- a/catalog/src/main/assets/behavior_calculated_expression.json +++ b/catalog/src/main/assets/behavior_calculated_expression.json @@ -19,13 +19,26 @@ "linkId": "a-age-years", "text": "Age years", "type": "quantity", - "initial": [{ - "valueQuantity": { - "unit": "years", - "system": "http://unitsofmeasure.org", - "code": "years" + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption", + "valueCoding": { + "system": "http://unitsofmeasure.org", + "code": "years", + "display": "years" + } } - }] + ], + "initial": [ + { + "valueQuantity": { + "value": 0, + "unit": "years", + "system": "http://unitsofmeasure.org", + "code": "years" + } + } + ] } ] } \ No newline at end of file From e1cfd3fee6bbb513e2e84fc033b294b524455820 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 17:05:54 +0700 Subject: [PATCH 16/40] Update kdoc --- .../enablement/EnablementEvaluator.kt | 9 +++++-- .../EnabledAnswerOptionsEvaluator.kt | 12 +++++++++ .../fhirpath/ExpressionEvaluator.kt | 25 ++++++------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index 5800d92426..c4004878d7 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -51,8 +51,12 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse * is shown or hidden. However, it is also possible that only user interaction is enabled or * disabled (e.g. grayed out) with the [Questionnaire.QuestionnaireItemComponent] always shown. * - * The evaluator does not track the changes in the `questionnaire` and `questionnaireResponse`. - * Therefore, a new evaluator should be created if they were modified. + * The evaluator represents a session of [Questionnaire]. + * + * To ensure the safe and accurate tracking of changes of the [Questionnaire] and + * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or + * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator + * instance to manage its own lifecycle. * * For more information see * [Questionnaire.item.enableWhen](https://www.hl7.org/fhir/questionnaire-definitions.html#Questionnaire.item.enableWhen) @@ -99,6 +103,7 @@ internal class EnablementEvaluator( /** * Returns whether [questionnaireItem] should be enabled. * + * @param questionnaireItem the corresponding questionnaire item. * @param questionnaireResponseItem the corresponding questionnaire response item. */ fun evaluate( diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index 4e7fc7885d..4ba73abe78 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -32,6 +32,18 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse import org.hl7.fhir.r4.model.ResourceType import org.hl7.fhir.r4.model.ValueSet +/** + * Evaluates and manages answer options within a [Questionnaire] and its corresponding + * [QuestionnaireResponse]. It handles enablement, disablement, and presentation of options based on + * expressions and criteria. + * + * The evaluator represents a session of [Questionnaire]. + * + * To ensure the safe and accurate tracking of changes of the [Questionnaire] and + * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or + * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator + * instance to manage its own lifecycle. + */ internal class EnabledAnswerOptionsEvaluator( private val questionnaire: Questionnaire, private val questionnaireResponse: QuestionnaireResponse, 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 b38e5da99d..187ee4425d 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 @@ -35,6 +35,13 @@ import timber.log.Timber /** * Evaluates an expression and returns its result. * + * The evaluator represents a session of [Questionnaire]. + * + * To ensure the safe and accurate tracking of changes of the [Questionnaire] and + * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or + * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator + * instance to manage its own lifecycle. + * * Expressions can be defined at questionnaire level and questionnaire item level. This * [ExpressionEvaluator] supports evaluation of * [variable expression](http://hl7.org/fhir/R4/extension-variable.html) defined at either @@ -153,9 +160,6 @@ internal class ExpressionEvaluator( * expression being evaluated. * * @param expression the [Expression] Variable expression - * @param questionnaire the [Questionnaire] respective questionnaire - * @param questionnaireResponse the [QuestionnaireResponse] respective questionnaire response - * @param questionnaireItemParentMap the [Map] of child to parent * @param questionnaireItem the [Questionnaire.QuestionnaireItemComponent] where this expression * is defined, @@ -190,10 +194,6 @@ internal class ExpressionEvaluator( * values respecting the scope and hierarchy level * * @param expression the [Expression] expression to find variables applicable - * @param questionnaire the [Questionnaire] respective questionnaire - * @param questionnaireResponse the [QuestionnaireResponse] respective questionnaire response - * @param questionnaireItemParentMap the [Map] of child to parent * @param questionnaireItem the [Questionnaire.QuestionnaireItemComponent] where this expression * @param variablesMap the [Map] of variables, the default value is empty map is * defined @@ -227,8 +227,6 @@ internal class ExpressionEvaluator( * the evaluated values to the expression being evaluated. * * @param expression the [Expression] Variable expression - * @param questionnaire the [Questionnaire] respective questionnaire - * @param questionnaireResponse the [QuestionnaireResponse] respective questionnaire response * @param variablesMap the [Map] of variables, the default value is empty map * * @return [Base] the result of expression @@ -292,7 +290,7 @@ internal class ExpressionEvaluator( * * @param expression x-fhir-query expression containing a FHIRpath, e.g. * Practitioner?active=true&{{Practitioner.name.family}} - * @param questionnaireLaunchContextMap the launch context to evaluate the expression against + * @param launchContextMap the launch context to evaluate the expression against */ private fun evaluateXFhirEnhancement( expression: Expression, @@ -346,10 +344,6 @@ internal class ExpressionEvaluator( * @param variableName the [String] to match the variable in the ancestors * @param questionnaireItem the [Questionnaire.QuestionnaireItemComponent] from where we have to * track hierarchy up in the ancestors - * @param questionnaire the [Questionnaire] respective questionnaire - * @param questionnaireResponse the [QuestionnaireResponse] respective questionnaire response - * @param questionnaireItemParentMap the [Map] of child to parent * @param variablesMap the [Map] of variables */ private fun findAndEvaluateVariable( @@ -391,8 +385,6 @@ internal class ExpressionEvaluator( * @param variableName the [String] to match the variable in the ancestors * @param questionnaireItem the [Questionnaire.QuestionnaireItemComponent] whose ancestors we * visit - * @param questionnaireItemParentMap the [Map] of child to parent * @return [Pair] containing [Questionnaire.QuestionnaireItemComponent] and an [Expression] */ private fun findVariableInAncestors( @@ -413,7 +405,6 @@ internal class ExpressionEvaluator( * Evaluates the value of variable expression and returns its evaluated value * * @param expression the [Expression] the expression to evaluate - * @param questionnaireResponse the [QuestionnaireResponse] respective questionnaire response * @param dependentVariables the [Map] of variable names to their values * * @return [Base] the result of an expression From cc95c5d7857e7a5fbfd682afb6a57f311e531fb3 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Wed, 6 Sep 2023 17:06:06 +0700 Subject: [PATCH 17/40] Remove old evaluateToBoolean --- .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index b84fe9a961..04aff30392 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -60,15 +60,3 @@ internal fun evaluateToBoolean( expressionNode, ) } - -internal fun evaluateToBoolean( - questionnaireResponse: QuestionnaireResponse, - questionnaireResponseItemComponent: QuestionnaireResponseItemComponent, - expression: String -) = - fhirPathEngine.evaluateToBoolean( - questionnaireResponse, - null, - questionnaireResponseItemComponent, - expression - ) From c44e49b04354217ba50aed053e17cf446623731c Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Thu, 7 Sep 2023 23:08:43 +0700 Subject: [PATCH 18/40] Address review --- .../behavior_skip_logic_with_expression.json | 42 +++++++++++++++++- .../datacapture/QuestionnaireViewModel.kt | 18 +++++--- .../enablement/EnablementEvaluator.kt | 31 ++++++++++--- .../EnabledAnswerOptionsEvaluator.kt | 33 +++++++++++--- .../fhirpath/ExpressionEvaluator.kt | 44 +++++++++---------- .../QuestionnaireResponseValidator.kt | 16 +++---- ...alidationErrorMessageDialogFragmentTest.kt | 2 +- .../enablement/EnablementEvaluatorTest.kt | 20 +++------ 8 files changed, 135 insertions(+), 71 deletions(-) diff --git a/catalog/src/main/assets/behavior_skip_logic_with_expression.json b/catalog/src/main/assets/behavior_skip_logic_with_expression.json index da4d531d58..8151396ba9 100644 --- a/catalog/src/main/assets/behavior_skip_logic_with_expression.json +++ b/catalog/src/main/assets/behavior_skip_logic_with_expression.json @@ -14,7 +14,27 @@ { "linkId": "1", "type": "boolean", - "text": "Does patient has fever?" + "text": "Does patient has fever?", + "item": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-display-category", + "code": "instructions" + } + ] + } + } + ], + "linkId": "1.1", + "text": "Define the questionnaire variable 'has-fever' based on the answer to the question 'Does the patient have a fever?", + "type": "display" + } + ] }, { "linkId": "2", @@ -28,6 +48,26 @@ "expression": "%has-fever" } } + ], + "item": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-display-category", + "code": "instructions" + } + ] + } + } + ], + "linkId": "2.1", + "text": "Enabled if variable 'has-fever' evaluates to true", + "type": "display" + } ] } ] 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 a77a43cd9d..357ae7300c 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 @@ -342,15 +342,21 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat ) private val enablementEvaluator: EnablementEvaluator = - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) private val answerOptionsEvaluator: EnabledAnswerOptionsEvaluator = EnabledAnswerOptionsEvaluator( questionnaire, questionnaireResponse, - expressionEvaluator, xFhirQueryResolver, - externalValueSetResolver + externalValueSetResolver, + questionnaireItemParentMap, + questionnaireLaunchContextMap ) /** @@ -499,7 +505,7 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat questionnaireResponse.allItems.find { qrItem -> qrItem.linkId == qItem.linkId } ) } - modificationCount.update { it + 1 } + modificationCount.update { count -> count + 1 } } } .map { it.value } @@ -510,12 +516,12 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat ) private fun updateDependentQuestionnaireResponseItems( - updatedQuestionnaireItem: QuestionnaireItemComponent, + questionnaireItem: QuestionnaireItemComponent, updatedQuestionnaireResponseItem: QuestionnaireResponseItemComponent?, ) { expressionEvaluator .evaluateCalculatedExpressions( - updatedQuestionnaireItem, + questionnaireItem, updatedQuestionnaireResponseItem, ) .forEach { (questionnaireItem, calculatedAnswers) -> diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt index c4004878d7..0cbc02e96e 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluator.kt @@ -24,6 +24,7 @@ import com.google.android.fhir.datacapture.fhirpath.evaluateToBoolean import com.google.android.fhir.equals import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse +import org.hl7.fhir.r4.model.Resource /** * Evaluator for the enablement status of a [Questionnaire.QuestionnaireItemComponent]. @@ -51,23 +52,39 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse * is shown or hidden. However, it is also possible that only user interaction is enabled or * disabled (e.g. grayed out) with the [Questionnaire.QuestionnaireItemComponent] always shown. * - * The evaluator represents a session of [Questionnaire]. - * - * To ensure the safe and accurate tracking of changes of the [Questionnaire] and - * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or - * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator - * instance to manage its own lifecycle. + * The evaluator works in the context of a Questionnaire and the corresponding + * QuestionnaireResponse. It is the caller's responsibility to make sure to call the evaluator with + * QuestionnaireItems and QuestionnaireResponseItems that belong to the Questionnaire and the + * QuestionnaireResponse. * * For more information see * [Questionnaire.item.enableWhen](https://www.hl7.org/fhir/questionnaire-definitions.html#Questionnaire.item.enableWhen) * and * [Questionnaire.item.enableBehavior](https://www.hl7.org/fhir/questionnaire-definitions.html#Questionnaire.item.enableBehavior) * . + * + * @param questionnaire the [Questionnaire] where the expression belong to + * @param questionnaireResponse the [QuestionnaireResponse] related to the [Questionnaire] + * @param questionnaireItemParentMap the [Map] of items parent + * @param questionnaireLaunchContextMap the [Map] of launchContext names to their resource values */ internal class EnablementEvaluator( + private val questionnaire: Questionnaire, private val questionnaireResponse: QuestionnaireResponse, - private val expressionEvaluator: ExpressionEvaluator, + private val questionnaireItemParentMap: + Map = + emptyMap(), + private val questionnaireLaunchContextMap: Map? = emptyMap(), ) { + + private val expressionEvaluator = + ExpressionEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) + /** * The pre-order traversal trace of the items in the [QuestionnaireResponse]. This essentially * represents the order in which all items are displayed in the UI. diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt index 4ba73abe78..fa11cca5ab 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/expressions/EnabledAnswerOptionsEvaluator.kt @@ -29,6 +29,8 @@ import org.hl7.fhir.r4.model.Coding import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent import org.hl7.fhir.r4.model.QuestionnaireResponse +import org.hl7.fhir.r4.model.QuestionnaireResponse.QuestionnaireResponseItemComponent +import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.ResourceType import org.hl7.fhir.r4.model.ValueSet @@ -37,21 +39,38 @@ import org.hl7.fhir.r4.model.ValueSet * [QuestionnaireResponse]. It handles enablement, disablement, and presentation of options based on * expressions and criteria. * - * The evaluator represents a session of [Questionnaire]. + * The evaluator works in the context of a [Questionnaire] and the corresponding + * [QuestionnaireResponse]. It is the caller's responsibility to make sure to call the evaluator + * with [QuestionnaireItemComponent] and [QuestionnaireResponseItemComponent] that belong to the + * [Questionnaire] and the [QuestionnaireResponse]. * - * To ensure the safe and accurate tracking of changes of the [Questionnaire] and - * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or - * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator - * instance to manage its own lifecycle. + * @param questionnaire the [Questionnaire] where the expression belong to + * @param questionnaireResponse the [QuestionnaireResponse] related to the [Questionnaire] + * @param xFhirQueryResolver the [XFhirQueryResolver] to resolve resources based on the X-FHIR-Query + * @param externalValueSetResolver the [ExternalAnswerValueSetResolver] to resolve value sets + * externally/outside of the [Questionnaire] + * @param questionnaireItemParentMap the [Map] of items parent + * @param questionnaireLaunchContextMap the [Map] of launchContext names to their resource values */ internal class EnabledAnswerOptionsEvaluator( private val questionnaire: Questionnaire, private val questionnaireResponse: QuestionnaireResponse, - private val expressionEvaluator: ExpressionEvaluator, private val xFhirQueryResolver: XFhirQueryResolver?, private val externalValueSetResolver: ExternalAnswerValueSetResolver?, + private val questionnaireItemParentMap: + Map = + emptyMap(), + private val questionnaireLaunchContextMap: Map? = emptyMap(), ) { + private val expressionEvaluator = + ExpressionEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + questionnaireLaunchContextMap + ) + private val answerValueSetMap = mutableMapOf>() @@ -72,7 +91,7 @@ internal class EnabledAnswerOptionsEvaluator( */ internal suspend fun evaluate( questionnaireItem: QuestionnaireItemComponent, - questionnaireResponseItem: QuestionnaireResponse.QuestionnaireResponseItemComponent, + questionnaireResponseItem: QuestionnaireResponseItemComponent, ): Pair< List, List 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 187ee4425d..78c06d799f 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 @@ -35,25 +35,28 @@ import timber.log.Timber /** * Evaluates an expression and returns its result. * - * The evaluator represents a session of [Questionnaire]. - * - * To ensure the safe and accurate tracking of changes of the [Questionnaire] and - * [QuestionnaireResponse], it is crucial to associate the evaluator's lifecycle with a ViewModel or - * other lifecycle-aware class. If no lifecycle-aware class is available, create a new evaluator - * instance to manage its own lifecycle. + * The evaluator works in the context of a [Questionnaire] and the corresponding + * [QuestionnaireResponse]. It is the caller's responsibility to make sure to call the evaluator + * with [QuestionnaireItemComponent] and [QuestionnaireResponseItemComponent] that belong to the + * [Questionnaire] and the [QuestionnaireResponse]. * * Expressions can be defined at questionnaire level and questionnaire item level. This * [ExpressionEvaluator] supports evaluation of * [variable expression](http://hl7.org/fhir/R4/extension-variable.html) defined at either * questionnaire level or questionnaire item level. + * + * @param questionnaire the [Questionnaire] where the expression belong to + * @param questionnaireResponse the [QuestionnaireResponse] related to the [Questionnaire] + * @param questionnaireItemParentMap the [Map] of items parent + * @param questionnaireLaunchContextMap the [Map] of launchContext names to their resource values */ internal class ExpressionEvaluator( private val questionnaire: Questionnaire, private val questionnaireResponse: QuestionnaireResponse, private val questionnaireItemParentMap: Map = - mapOf(), - private val questionnaireLaunchContextMap: Map? = mapOf(), + emptyMap(), + private val questionnaireLaunchContextMap: Map? = emptyMap(), ) { private val reservedVariables = @@ -123,7 +126,7 @@ internal class ExpressionEvaluator( * calculated expression extension, which is dependent on value of updated response */ fun evaluateCalculatedExpressions( - updatedQuestionnaireItem: QuestionnaireItemComponent, + questionnaireItem: QuestionnaireItemComponent, updatedQuestionnaireResponseItemComponent: QuestionnaireResponseItemComponent?, ): List { return questionnaire.item @@ -132,18 +135,18 @@ internal class ExpressionEvaluator( // Condition 1. item is calculable // Condition 2. item answer depends on the updated item answer OR has a variable dependency item.calculatedExpression != null && - (updatedQuestionnaireItem.isReferencedBy(item) || + (questionnaireItem.isReferencedBy(item) || findDependentVariables(item.calculatedExpression!!).isNotEmpty()) } - .map { questionnaireItem -> + .map { item -> val updatedAnswer = evaluateExpression( - questionnaireItem, + item, updatedQuestionnaireResponseItemComponent, - questionnaireItem.calculatedExpression!!, + item.calculatedExpression!!, ) .map { it.castToType(it) } - questionnaireItem to updatedAnswer + item to updatedAnswer } } @@ -203,6 +206,7 @@ internal class ExpressionEvaluator( questionnaireItem: QuestionnaireItemComponent, variablesMap: MutableMap = mutableMapOf(), ): MutableMap { + questionnaireLaunchContextMap?.let { variablesMap.putAll(it) } findDependentVariables(expression).forEach { variableName -> if (variablesMap[variableName] == null) { findAndEvaluateVariable( @@ -212,7 +216,6 @@ internal class ExpressionEvaluator( ) } } - questionnaireLaunchContextMap?.let { variablesMap.putAll(it) } return variablesMap } @@ -411,7 +414,7 @@ internal class ExpressionEvaluator( */ private fun evaluateVariable( expression: Expression, - dependentVariables: Map = mapOf(), + dependentVariables: Map = emptyMap(), ) = try { require(expression.name?.isNotBlank() == true) { @@ -422,16 +425,9 @@ internal class ExpressionEvaluator( "Unsupported expression language, language should be text/fhirpath" } - val contextMap = - mutableMapOf().apply { - putAll(dependentVariables) - if (questionnaireLaunchContextMap != null) { - putAll(questionnaireLaunchContextMap) - } - } fhirPathEngine .evaluate( - contextMap, + dependentVariables, questionnaireResponse, null, null, diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt index 9f7ac71706..0073fc9c64 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/validation/QuestionnaireResponseValidator.kt @@ -19,7 +19,6 @@ package com.google.android.fhir.datacapture.validation import android.content.Context import com.google.android.fhir.datacapture.enablement.EnablementEvaluator import com.google.android.fhir.datacapture.extensions.packRepeatedGroups -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import org.hl7.fhir.r4.model.Questionnaire import org.hl7.fhir.r4.model.QuestionnaireResponse import org.hl7.fhir.r4.model.Resource @@ -73,19 +72,16 @@ object QuestionnaireResponseValidator { val linkIdToValidationResultMap = mutableMapOf>() - val expressionEvaluator = - ExpressionEvaluator( - questionnaire, - questionnaireResponse, - questionnaireItemParentMap, - launchContextMap - ) - validateQuestionnaireResponseItems( questionnaire.item, questionnaireResponse.item, context, - EnablementEvaluator(questionnaireResponse, expressionEvaluator), + EnablementEvaluator( + questionnaire, + questionnaireResponse, + questionnaireItemParentMap, + launchContextMap + ), linkIdToValidationResultMap, ) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt index 2a0c881b24..54841ee570 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/QuestionnaireValidationErrorMessageDialogFragmentTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt index 39eed18823..f848cbec88 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/enablement/EnablementEvaluatorTest.kt @@ -19,7 +19,6 @@ package com.google.android.fhir.datacapture.enablement import android.os.Build import ca.uhn.fhir.context.FhirContext import ca.uhn.fhir.parser.IParser -import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator import com.google.common.truth.BooleanSubject import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking @@ -58,9 +57,8 @@ class EnablementEvaluatorTest { val questionnaireResponseItem = QuestionnaireResponse.QuestionnaireResponseItemComponent().apply { linkId = "q1" } val questionnaireResponse = QuestionnaireResponse().apply { addItem(questionnaireResponseItem) } - val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) assertThat( - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator(questionnaire, questionnaireResponse) .evaluate(questionnaireItem, questionnaireResponseItem) ) .isFalse() @@ -175,10 +173,8 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse - val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) - assertThat( - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator(questionnaire, questionnaireResponse) .evaluate( questionnaireItem, questionnaireResponse.item[1], @@ -256,10 +252,8 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse - val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) - assertThat( - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator(questionnaire, questionnaireResponse) .evaluate( questionnaireItemComponent, questionnaireResponse.item[1], @@ -337,10 +331,8 @@ class EnablementEvaluatorTest { iParser.parseResource(QuestionnaireResponse::class.java, questionnaireResponseJson) as QuestionnaireResponse - val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) - assertThat( - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator(questionnaire, questionnaireResponse) .evaluate( questionnaireItem, questionnaireResponse.item[1], @@ -786,10 +778,8 @@ class EnablementEvaluatorTest { ) } - val expressionEvaluator = ExpressionEvaluator(questionnaire, questionnaireResponse) - return assertThat( - EnablementEvaluator(questionnaireResponse, expressionEvaluator) + EnablementEvaluator(questionnaire, questionnaireResponse) .evaluate(questionnaireItem, questionnaireResponse.item.last()) ) } From fb044215982888138da68d88757d0deae9335a0c Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Fri, 8 Sep 2023 15:16:17 +0700 Subject: [PATCH 19/40] Revert behavior_calculated_expression.json Should be fixed in other PR, there is more issue w Date picker widget format that doesn't work properly because declared in the bind() function. --- .../behavior_calculated_expression.json | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/catalog/src/main/assets/behavior_calculated_expression.json b/catalog/src/main/assets/behavior_calculated_expression.json index 525399cda8..e2fa4764d3 100644 --- a/catalog/src/main/assets/behavior_calculated_expression.json +++ b/catalog/src/main/assets/behavior_calculated_expression.json @@ -19,26 +19,13 @@ "linkId": "a-age-years", "text": "Age years", "type": "quantity", - "extension": [ - { - "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-unitOption", - "valueCoding": { - "system": "http://unitsofmeasure.org", - "code": "years", - "display": "years" - } + "initial": [{ + "valueQuantity": { + "unit": "years", + "system": "http://unitsofmeasure.org", + "code": "years" } - ], - "initial": [ - { - "valueQuantity": { - "value": 0, - "unit": "years", - "system": "http://unitsofmeasure.org", - "code": "years" - } - } - ] + }] } ] } \ No newline at end of file From bd0a687138e58d3a7fd90fe9ea556716071d1b84 Mon Sep 17 00:00:00 2001 From: fikrimilano Date: Mon, 11 Sep 2023 15:34:27 +0700 Subject: [PATCH 20/40] Add named parameter comment --- .../fhirpath/ExpressionEvaluator.kt | 30 +++++++++---------- .../fhir/datacapture/fhirpath/FhirPathUtil.kt | 10 +++---- 2 files changed, 20 insertions(+), 20 deletions(-) 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 78c06d799f..c921a54981 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 @@ -113,11 +113,11 @@ internal class ExpressionEvaluator( ): List { val appContext = extractDependentVariables(expression, questionnaireItem) return fhirPathEngine.evaluate( - appContext, - questionnaireResponse, - null, - questionnaireResponseItem, - expression.expression + /* */ appContext, + /* */ questionnaireResponse, + /* */ null, + /* */ questionnaireResponseItem, + /* */ expression.expression ) } @@ -311,11 +311,11 @@ internal class ExpressionEvaluator( ?: expressionNode.name?.lowercase() val evaluatedResult = fhirPathEngine.evaluateToString( - launchContextMap, - null, - null, - launchContextMap[resourceType], - expressionNode + /* */ launchContextMap, + /* */ null, + /* */ null, + /* */ launchContextMap[resourceType], + /* */ expressionNode ) // If the result of evaluating the FHIRPath expressions is an invalid query, it returns @@ -427,11 +427,11 @@ internal class ExpressionEvaluator( fhirPathEngine .evaluate( - dependentVariables, - questionnaireResponse, - null, - null, - expression.expression, + /* */ dependentVariables, + /* */ questionnaireResponse, + /* */ null, + /* */ null, + /* */ expression.expression, ) .firstOrNull() } catch (exception: FHIRException) { diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index 04aff30392..dcec046ef1 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -53,10 +53,10 @@ internal fun evaluateToBoolean( ): Boolean { val expressionNode = fhirPathEngine.parse(expression) return fhirPathEngine.evaluateToBoolean( - contextMap, - questionnaireResponse, - null, - questionnaireResponseItemComponent, - expressionNode, + /* */ contextMap, + /* */ questionnaireResponse, + /* */ null, + /* */ questionnaireResponseItemComponent, + /* */ expressionNode, ) } From b5a69ef28883df25764216219839051b197fa892 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:39:49 +0100 Subject: [PATCH 21/40] Update datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt --- .../android/fhir/datacapture/fhirpath/FhirPathUtil.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt index dcec046ef1..9504262cdf 100644 --- a/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt +++ b/datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/FhirPathUtil.kt @@ -53,10 +53,10 @@ internal fun evaluateToBoolean( ): Boolean { val expressionNode = fhirPathEngine.parse(expression) return fhirPathEngine.evaluateToBoolean( - /* */ contextMap, - /* */ questionnaireResponse, - /* */ null, - /* */ questionnaireResponseItemComponent, - /* */ expressionNode, + /* appInfo= */ contextMap, + /* focusResource= */ questionnaireResponse, + /* rootResource= */ null, + /* base= */ questionnaireResponseItemComponent, + /* node= */ expressionNode, ) } From 1b52e6903a7e5956b58f91de12dccc690f8243a6 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:40:02 +0100 Subject: [PATCH 22/40] Update datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluator.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 c921a54981..7f821962a8 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 @@ -113,11 +113,11 @@ internal class ExpressionEvaluator( ): List { val appContext = extractDependentVariables(expression, questionnaireItem) return fhirPathEngine.evaluate( - /* */ appContext, - /* */ questionnaireResponse, - /* */ null, - /* */ questionnaireResponseItem, - /* */ expression.expression + /* appContext= */ appContext, + /* focusResource= */ questionnaireResponse, + /* rootResource= */ null, + /* base= */ questionnaireResponseItem, + /* path= */ expression.expression ) } From 81de124a6efc5d205be0004aadb663d9af70558d Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:40:13 +0100 Subject: [PATCH 23/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 3c04c7b2ea..0d98b70a42 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -817,7 +817,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), mapOf(patient.resourceType.name.lowercase() to patient) ) From bd67a3cfceb46c6ec4cfa1779ed288d0e9765899 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:40:36 +0100 Subject: [PATCH 24/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 0d98b70a42..fc34f99aeb 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -785,7 +785,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), mapOf(practitioner.resourceType.name to practitioner) ) From e53ee153cc39122acbe3392dae03c3f2f8cc034d Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:40:43 +0100 Subject: [PATCH 25/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index fc34f99aeb..9ba2806f39 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -863,7 +863,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), mapOf( patient.resourceType.name.lowercase() to patient, location.resourceType.name.lowercase() to location From 59f24346b1c6a9b8d2bb796ed2cd5f19294a24b3 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:40:54 +0100 Subject: [PATCH 26/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 9ba2806f39..2b7ddecf00 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -932,7 +932,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( questionnaire, QuestionnaireResponse(), - mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + /* questionnaireItemParentMap= */ mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), null ) From 5e39c56505b81eedeff094455b6f7b02dfaa6848 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:06 +0100 Subject: [PATCH 27/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 2b7ddecf00..d5234577ad 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -999,7 +999,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( questionnaire, QuestionnaireResponse(), - mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + /* questionnaireItemParentMap= */ mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), mapOf() ) From c572eed1e6fac0ad9fcdbbd17fb73d77b35c004d Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:13 +0100 Subject: [PATCH 28/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index d5234577ad..8f28d24921 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -754,7 +754,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), mapOf(), - mapOf(practitioner.resourceType.name.lowercase() to practitioner) + /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name.lowercase() to practitioner), ) val expressionsToEvaluate = From 3b24375914ad500ccefdbf67fc1fd7ea77e53b83 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:26 +0100 Subject: [PATCH 29/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 8f28d24921..ba8abe54f0 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -753,7 +753,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name.lowercase() to practitioner), ) From 1ed2ba098dab652c7753a43c04a9c51ccfb3dc51 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:33 +0100 Subject: [PATCH 30/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index ba8abe54f0..22048044df 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -933,7 +933,7 @@ class ExpressionEvaluatorTest { questionnaire, QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), - null + /* questionnaireLaunchContextMap= */ null, ) val result = From af9a2f6de92cebd9c9f2d44e04bba11e06231f45 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:39 +0100 Subject: [PATCH 31/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 22048044df..06b807c267 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -864,7 +864,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(), - mapOf( + /* questionnaireLaunchContextMap= */ mapOf( patient.resourceType.name.lowercase() to patient, location.resourceType.name.lowercase() to location ) From 66fa9fe23b5db41224be45f714cd201e1b59c605 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:45 +0100 Subject: [PATCH 32/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 06b807c267..9218d73078 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -818,7 +818,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(), - mapOf(patient.resourceType.name.lowercase() to patient) + /* questionnaireLaunchContextMap= */ mapOf(patient.resourceType.name.lowercase() to patient), ) val expressionsToEvaluate = From 36ea59eeed682cf43a0b88b7efbefc962ce62511 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:41:52 +0100 Subject: [PATCH 33/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 9218d73078..a1dd0b3eef 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -786,7 +786,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(), - mapOf(practitioner.resourceType.name to practitioner) + /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name to practitioner), ) val expressionsToEvaluate = From cba10f7bd72d098ba9e5bb5efc3ac2e973e73556 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:02 +0100 Subject: [PATCH 34/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index a1dd0b3eef..95722605e8 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -721,7 +721,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), mapOf(practitioner.resourceType.name to practitioner) ) From 183e8ede246bf4fcb05d94a4efa823df657eb2c4 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:15 +0100 Subject: [PATCH 35/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 95722605e8..5956c0dbb1 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -689,7 +689,7 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - mapOf(), + /* questionnaireItemParentMap= */ mapOf(), mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()) ) From 6051a587e1da3978e4cf008231da83103038e494 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:25 +0100 Subject: [PATCH 36/40] Update datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluator.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 7f821962a8..04f79f7c1f 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 @@ -427,11 +427,11 @@ internal class ExpressionEvaluator( fhirPathEngine .evaluate( - /* */ dependentVariables, - /* */ questionnaireResponse, - /* */ null, - /* */ null, - /* */ expression.expression, + /* appContext= */ dependentVariables, + /* focusResource= */ questionnaireResponse, + /* rootResource= */ null, + /* base= */ null, + /* path= */ expression.expression, ) .firstOrNull() } catch (exception: FHIRException) { From 92ffe98553912076accb3a596a84ae28cde8a932 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:36 +0100 Subject: [PATCH 37/40] Update datacapture/src/main/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluator.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluator.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 04f79f7c1f..cc0bc79d99 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 @@ -311,11 +311,11 @@ internal class ExpressionEvaluator( ?: expressionNode.name?.lowercase() val evaluatedResult = fhirPathEngine.evaluateToString( - /* */ launchContextMap, - /* */ null, - /* */ null, - /* */ launchContextMap[resourceType], - /* */ expressionNode + /* appInfo= */ launchContextMap, + /* focusResource= */ null, + /* rootResource= */ null, + /* base= */ launchContextMap[resourceType], + /* node= */ expressionNode ) // If the result of evaluating the FHIRPath expressions is an invalid query, it returns From 70159533ba405cd9cd519a0f16841208ace616a8 Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:45 +0100 Subject: [PATCH 38/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 5956c0dbb1..91e52239f2 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -690,7 +690,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(), - mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()) + /* questionnaireLaunchContextMap= */ mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()), ) val expressionsToEvaluate = From bc8b853b078c248e93f30d7bab0cc642f0a1ba1a Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:42:55 +0100 Subject: [PATCH 39/40] Update datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt --- .../fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 91e52239f2..460e8bd491 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -722,7 +722,7 @@ class ExpressionEvaluatorTest { Questionnaire(), QuestionnaireResponse(), /* questionnaireItemParentMap= */ mapOf(), - mapOf(practitioner.resourceType.name to practitioner) + /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name to practitioner), ) val expressionsToEvaluate = From 70d2112d7cbd7d783c900032bbf89cbccdca594e Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Mon, 11 Sep 2023 15:51:10 +0100 Subject: [PATCH 40/40] Spotless --- .../fhirpath/ExpressionEvaluator.kt | 4 +- .../fhirpath/ExpressionEvaluatorTest.kt | 41 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) 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 cc0bc79d99..9736bf6c30 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 @@ -117,7 +117,7 @@ internal class ExpressionEvaluator( /* focusResource= */ questionnaireResponse, /* rootResource= */ null, /* base= */ questionnaireResponseItem, - /* path= */ expression.expression + /* path= */ expression.expression, ) } @@ -315,7 +315,7 @@ internal class ExpressionEvaluator( /* focusResource= */ null, /* rootResource= */ null, /* base= */ launchContextMap[resourceType], - /* node= */ expressionNode + /* node= */ expressionNode, ) // If the result of evaluating the FHIRPath expressions is an invalid query, it returns diff --git a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt index 460e8bd491..2d223b3568 100644 --- a/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt +++ b/datacapture/src/test/java/com/google/android/fhir/datacapture/fhirpath/ExpressionEvaluatorTest.kt @@ -689,8 +689,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()), + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = + mapOf(Practitioner().resourceType.name.lowercase() to Practitioner()), ) val expressionsToEvaluate = @@ -721,8 +722,8 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name to practitioner), + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = mapOf(practitioner.resourceType.name to practitioner), ) val expressionsToEvaluate = @@ -753,8 +754,9 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name.lowercase() to practitioner), + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = + mapOf(practitioner.resourceType.name.lowercase() to practitioner), ) val expressionsToEvaluate = @@ -785,8 +787,8 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf(practitioner.resourceType.name to practitioner), + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = mapOf(practitioner.resourceType.name to practitioner), ) val expressionsToEvaluate = @@ -817,8 +819,8 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf(patient.resourceType.name.lowercase() to patient), + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = mapOf(patient.resourceType.name.lowercase() to patient), ) val expressionsToEvaluate = @@ -863,11 +865,12 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( Questionnaire(), QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(), - /* questionnaireLaunchContextMap= */ mapOf( - patient.resourceType.name.lowercase() to patient, - location.resourceType.name.lowercase() to location - ) + questionnaireItemParentMap = emptyMap(), + questionnaireLaunchContextMap = + mapOf( + patient.resourceType.name.lowercase() to patient, + location.resourceType.name.lowercase() to location + ) ) val expressionsToEvaluate = @@ -932,8 +935,8 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( questionnaire, QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), - /* questionnaireLaunchContextMap= */ null, + questionnaireItemParentMap = mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + questionnaireLaunchContextMap = null, ) val result = @@ -999,8 +1002,8 @@ class ExpressionEvaluatorTest { ExpressionEvaluator( questionnaire, QuestionnaireResponse(), - /* questionnaireItemParentMap= */ mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), - mapOf() + questionnaireItemParentMap = mapOf(questionnaire.item[0].item[0] to questionnaire.item[0]), + questionnaireLaunchContextMap = emptyMap(), ) val result =