Skip to content

Commit

Permalink
Follow up code health fixes of PR 1442 (google#1631)
Browse files Browse the repository at this point in the history
* WIP PR feedback

* spotless ran

* added test cases for validation util

* used fhirpathengine instance from fhir path expression evaluator

* updated test cases name and convention

* updated test cases name and their convention to look consistent

Co-authored-by: Jing Tang <jingtang@google.com>
  • Loading branch information
2 people authored and ktarasenko committed Nov 11, 2022
1 parent 0e463fc commit dbf1a41
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ object ExpressionEvaluator {
*/
private val variableRegex = Regex("[%]([A-Za-z0-9\\-]{1,64})")

private val fhirPathEngine: FHIRPathEngine =
internal val fhirPathEngine: FHIRPathEngine =
with(FhirContext.forCached(FhirVersionEnum.R4)) {
FHIRPathEngine(HapiWorkerContext(this, this.validationSupport)).apply {
hostServices = FHIRPathEngineHostServices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse
import org.hl7.fhir.r4.model.Type

internal const val MAX_VALUE_EXTENSION_URL = "http://hl7.org/fhir/StructureDefinition/maxValue"

/** A validator to check if the value of an answer exceeded the permitted value. */
internal object MaxValueConstraintValidator :
ValueConstraintExtensionValidator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,22 @@

package com.google.android.fhir.datacapture.validation

import ca.uhn.fhir.context.FhirContext
import ca.uhn.fhir.context.FhirVersionEnum
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport
import com.google.android.fhir.datacapture.EXTENSION_CQF_CALCULATED_VALUE_URL
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext
import com.google.android.fhir.datacapture.fhirpath.ExpressionEvaluator.fhirPathEngine
import org.hl7.fhir.r4.model.Expression
import org.hl7.fhir.r4.model.Type
import org.hl7.fhir.r4.utils.FHIRPathEngine

internal const val CQF_CALCULATED_EXPRESSION_URL: String =
"http://hl7.org/fhir/StructureDefinition/cqf-calculatedValue"

fun Type.valueOrCalculateValue(): Type? {
return if (this.hasExtension()) {
this.extension
.firstOrNull { it.url == EXTENSION_CQF_CALCULATED_VALUE_URL }
.firstOrNull { it.url == CQF_CALCULATED_EXPRESSION_URL }
?.let {
val expression = (it.value as Expression).expression
fhirPathEngine.evaluate(this, expression).firstOrNull()?.let { it as Type }
fhirPathEngine.evaluate(this, expression).singleOrNull()?.let { it as Type }
}
} else {
this
}
}

private val fhirPathEngine: FHIRPathEngine =
with(FhirContext.forCached(FhirVersionEnum.R4)) {
FHIRPathEngine(HapiWorkerContext(this, DefaultProfileValidationSupport(this)))
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ package com.google.android.fhir.datacapture.validation
import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import com.google.android.fhir.datacapture.EXTENSION_CQF_CALCULATED_VALUE_URL
import com.google.common.truth.Truth.assertThat
import java.text.SimpleDateFormat
import java.time.LocalDate
import kotlin.test.assertTrue
import org.hl7.fhir.r4.model.DateType
import org.hl7.fhir.r4.model.Expression
import org.hl7.fhir.r4.model.Extension
Expand All @@ -48,7 +46,7 @@ class MaxValueConstraintValidatorTest {
}

@Test
fun shouldReturnInvalidResult() {
fun `should return invalid result when entered value is greater than maxValue`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -72,7 +70,7 @@ class MaxValueConstraintValidatorTest {
}

@Test
fun shouldReturnValidResult() {
fun `should return valid result when entered value is less than maxValue`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -96,61 +94,7 @@ class MaxValueConstraintValidatorTest {
}

@Test
fun minValueFhirExpressionForDateType_shouldReturnDateType() {
val today = LocalDate.now().toString()
val questionItem =
listOf(
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Extension().apply {
url = MIN_VALUE_EXTENSION_URL
this.setValue(
DateType().apply {
extension =
listOf(
Extension(
EXTENSION_CQF_CALCULATED_VALUE_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today()"
}
)
)
}
)
}
)
}
)
assertTrue(
(MinValueConstraintValidator.getMinValue(questionItem.first()) as? DateType)
?.valueAsString.equals(today) == true
)
}

@Test
fun minValueExpressionForDateType_shouldReturnDateType() {
val dateType = DateType(SimpleDateFormat("yyyy-MM-dd").parse("2021-06-01"))
val questionItem =
listOf(
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Extension().apply {
url = MIN_VALUE_EXTENSION_URL
this.setValue(dateType)
}
)
}
)

assertTrue(
(MinValueConstraintValidator.getMinValue(questionItem.first()) as? DateType)
?.value?.equals(dateType.value) == true
)
}

@Test
fun maxValueExpressionForDateType_shouldReturnDateType() {
fun `should return maxValue date`() {
val dateType = DateType(SimpleDateFormat("yyyy-MM-dd").parse("2023-06-01"))
val questionItem =
listOf(
Expand All @@ -164,14 +108,12 @@ class MaxValueConstraintValidatorTest {
}
)

assertTrue(
(MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)
?.value?.equals(dateType.value) == true
)
assertThat((MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)?.value)
.isEqualTo(dateType.value)
}

@Test
fun maxValueFhirExpressionForDateType_shouldReturnTodaysDateType() {
fun `should return today's date when expression evaluates to today`() {
val today = LocalDate.now().toString()
val questionItem =
listOf(
Expand All @@ -184,7 +126,7 @@ class MaxValueConstraintValidatorTest {
extension =
listOf(
Extension(
EXTENSION_CQF_CALCULATED_VALUE_URL,
CQF_CALCULATED_EXPRESSION_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today()"
Expand All @@ -198,14 +140,14 @@ class MaxValueConstraintValidatorTest {
}
)

assertTrue(
(MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)
?.valueAsString?.equals(today) == true
)
assertThat(
(MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)?.valueAsString
)
.isEqualTo(today)
}

@Test
fun maxValueFhirExpressionForDateType_shouldReturnFutureDateType() {
fun `should return future's date when expression evaluates`() {
val fiveDaysAhead = LocalDate.now().plusDays(5).toString()
val questionItem =
listOf(
Expand All @@ -218,7 +160,7 @@ class MaxValueConstraintValidatorTest {
extension =
listOf(
Extension(
EXTENSION_CQF_CALCULATED_VALUE_URL,
CQF_CALCULATED_EXPRESSION_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today() + 5 'days' "
Expand All @@ -232,9 +174,9 @@ class MaxValueConstraintValidatorTest {
}
)

assertTrue(
(MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)
?.valueAsString?.equals(fiveDaysAhead) == true
)
assertThat(
(MaxValueConstraintValidator.getMaxValue(questionItem.first()) as? DateType)?.valueAsString
)
.isEqualTo(fiveDaysAhead)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.google.android.fhir.datacapture.EXTENSION_CQF_CALCULATED_VALUE_URL
import com.google.common.truth.Truth.assertThat
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.util.Calendar
import java.util.Date
import org.hl7.fhir.r4.model.DateTimeType
Expand Down Expand Up @@ -50,7 +50,7 @@ class MinValueConstraintValidatorTest {
}

@Test
fun shouldReturnInvalidResult() {
fun `should return invalid result when entered value is less than minValue`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -75,7 +75,7 @@ class MinValueConstraintValidatorTest {
}

@Test
fun shouldReturnValidResult() {
fun `should return valid result when entered value is greater than minValue`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -100,7 +100,7 @@ class MinValueConstraintValidatorTest {
}

@Test
fun shouldReturnInvalidResultWhenUsingExpressionForMinValue() {
fun `should return invalid result when entered value is less than minValue for cqf calculated expression`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -111,7 +111,7 @@ class MinValueConstraintValidatorTest {
extension =
listOf(
Extension(
EXTENSION_CQF_CALCULATED_VALUE_URL,
CQF_CALCULATED_EXPRESSION_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today() - 1 'days'"
Expand Down Expand Up @@ -150,7 +150,7 @@ class MinValueConstraintValidatorTest {
}

@Test
fun shouldReturnValidResultWhenUsingExpressionForMinValue() {
fun `should return valid result when entered value is greater than minValue for cqf calculated expression`() {
val questionnaireItem =
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Expand All @@ -161,7 +161,7 @@ class MinValueConstraintValidatorTest {
extension =
listOf(
Extension(
EXTENSION_CQF_CALCULATED_VALUE_URL,
CQF_CALCULATED_EXPRESSION_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today() - 1 'days'"
Expand All @@ -187,4 +187,56 @@ class MinValueConstraintValidatorTest {
assertThat(validationResult.isValid).isTrue()
assertThat(validationResult.message.isNullOrBlank()).isTrue()
}

@Test
fun `should return today's date when expression evaluates to today`() {
val today = LocalDate.now().toString()
val questionItem =
listOf(
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Extension().apply {
url = MIN_VALUE_EXTENSION_URL
this.setValue(
DateType().apply {
extension =
listOf(
Extension(
CQF_CALCULATED_EXPRESSION_URL,
Expression().apply {
language = "text/fhirpath"
expression = "today()"
}
)
)
}
)
}
)
}
)
assertThat(
(MinValueConstraintValidator.getMinValue(questionItem.first()) as? DateType)?.valueAsString
)
.isEqualTo(today)
}

@Test
fun `should return minValue date`() {
val dateType = DateType(SimpleDateFormat("yyyy-MM-dd").parse("2021-06-01"))
val questionItem =
listOf(
Questionnaire.QuestionnaireItemComponent().apply {
addExtension(
Extension().apply {
url = MIN_VALUE_EXTENSION_URL
this.setValue(dateType)
}
)
}
)

assertThat((MinValueConstraintValidator.getMinValue(questionItem.first()) as? DateType)?.value)
.isEqualTo(dateType.value)
}
}
Loading

0 comments on commit dbf1a41

Please sign in to comment.