Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement inequality operators (<, >, <=, >=) in the enable when statement #848

Merged
merged 20 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
api(Dependencies.HapiFhir.structuresR4)

implementation(Dependencies.fhirUcum)
implementation(Dependencies.Kotlin.kotlinTestJunit)

testImplementation(Dependencies.AndroidxTest.core)
testImplementation(Dependencies.junit)
Expand Down
13 changes: 13 additions & 0 deletions common/src/main/java/com/google/android/fhir/MoreTypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.android.fhir
import java.util.Calendar
import java.util.Date
import org.hl7.fhir.r4.model.Coding
import org.hl7.fhir.r4.model.Quantity
import org.hl7.fhir.r4.model.Type

/**
Expand Down Expand Up @@ -62,6 +63,18 @@ operator fun Type.compareTo(value: Type?): Int {
this.fhirType().equals("dateTime") -> {
return this.dateTimeValue().value.compareTo(value.dateTimeValue().value)
}
this.fhirType().equals("Quantity") -> {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
val quantity =
UnitConverter.getCanonicalForm(UcumValue((this as Quantity).code, this.value))
val anotherQuantity =
UnitConverter.getCanonicalForm(UcumValue((value as Quantity).code, value.value))
if (quantity.code != anotherQuantity.code) {
throw IllegalArgumentException(
"Cannot compare different quantity codes: ${quantity.code} and ${anotherQuantity.code}"
)
}
return quantity.value.compareTo(anotherQuantity.value)
}
else -> {
throw NotImplementedError()
}
Expand Down
34 changes: 34 additions & 0 deletions common/src/test/java/com/google/android/fhir/MoreTypesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.google.android.fhir
import android.os.Build
import com.google.common.truth.Truth.assertThat
import java.util.Calendar
import kotlin.test.assertFailsWith
import org.hl7.fhir.r4.model.Attachment
import org.hl7.fhir.r4.model.BooleanType
import org.hl7.fhir.r4.model.Coding
Expand Down Expand Up @@ -204,4 +205,37 @@ class MoreTypesTest {
assertThat(exception.message)
.isEqualTo("Cannot compare different data types: decimal and integer")
}

@Test
fun compareTo_quantityType_shouldReturnPositiveValue() {
val value = Quantity().setCode("h").setValue(10)
val otherValue = Quantity().setCode("h").setValue(5)

assertThat(value.compareTo(otherValue)).isEqualTo(1)
}

@Test
fun compareTo_quantityType_shouldReturnZero() {
val value = Quantity().setCode("h").setValue(10)
val otherValue = Quantity().setCode("h").setValue(10)

assertThat(value.compareTo(otherValue)).isEqualTo(0)
}

@Test
fun compareTo_quantityType_shouldReturnNegativeValue() {
val value = Quantity().setCode("h").setValue(10)
val otherValue = Quantity().setCode("h").setValue(20)

assertThat(value.compareTo(otherValue)).isEqualTo(-1)
}

@Test
fun compareTo_quantityWithDifferentCodes_shouldFail() {
assertFailsWith<IllegalArgumentException> {
val value = Quantity().setCode("h").setValue(10)
val otherValue = Quantity().setCode("kg").setValue(5)
value.compareTo(otherValue)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
import com.google.common.truth.Truth.assertThat
import java.math.BigDecimal
import kotlin.test.assertFailsWith
import org.hl7.fhir.r4.model.Quantity
import org.hl7.fhir.r4.model.Questionnaire
import org.hl7.fhir.r4.model.QuestionnaireResponse
Expand Down Expand Up @@ -189,34 +188,6 @@ class QuestionnaireItemEditTextQuantityViewHolderFactoryInstrumentedTest {
assertThat(questionnaireItemViewItem.questionnaireResponseItem.answer.size).isEqualTo(0)
}

@Test
@UiThreadTest
fun displayValidationResult_shouldThrowNotImplementedError() {
assertFailsWith<NotImplementedError> {
viewHolder.bind(
QuestionnaireItemViewItem(
Questionnaire.QuestionnaireItemComponent().apply {
addExtension().apply {
url = "https://hl7.org/fhir/StructureDefinition/minValue"
setValue(Quantity(2.2))
}
addExtension().apply {
url = "https://hl7.org/fhir/StructureDefinition/maxValue"
setValue(Quantity(4.4))
}
},
QuestionnaireResponse.QuestionnaireResponseItemComponent().apply {
addAnswer(
QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent().apply {
value = Quantity(3.3)
}
)
}
) {}
)
}
}

@Test
@UiThreadTest
fun displayValidationResult_error_shouldShowErrorMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

package com.google.android.fhir.datacapture.enablement

import com.google.android.fhir.compareTo
import com.google.android.fhir.equals
import java.lang.IllegalStateException
import org.hl7.fhir.r4.model.Questionnaire
import org.hl7.fhir.r4.model.QuestionnaireResponse

Expand Down Expand Up @@ -127,6 +127,18 @@ private val Questionnaire.QuestionnaireItemEnableWhenComponent.predicate:
Questionnaire.QuestionnaireItemOperator.NOT_EQUAL -> {
!equals(it.value, answer)
}
Questionnaire.QuestionnaireItemOperator.GREATER_THAN -> {
it.value > answer
}
Questionnaire.QuestionnaireItemOperator.GREATER_OR_EQUAL -> {
it.value >= answer
}
Questionnaire.QuestionnaireItemOperator.LESS_THAN -> {
it.value < answer
}
Questionnaire.QuestionnaireItemOperator.LESS_OR_EQUAL -> {
it.value <= answer
}
else -> throw NotImplementedError("Enable when operator $operator is not implemented.")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,110 @@ class EnablementEvaluatorTest {
.isFalse()
}

@Test
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
fun evaluate_greaterThan_answersGreaterThanEnableWhenAnswer_shouldReturnTrue() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.GREATER_THAN,
expected = IntegerType(10),
actual = listOf(IntegerType(20))
)
)
.isTrue()
}

@Test
fun evaluate_greaterThan_noAnswersGreaterThanEnableWhenAnswer_shouldReturnFalse() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.GREATER_THAN,
expected = IntegerType(10),
actual = listOf(IntegerType(5))
)
)
.isFalse()
}

@Test
fun evaluate_greaterOrEqual_answersGreaterOrEqualEnableWhenAnswer_shouldReturnTrue() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.GREATER_OR_EQUAL,
expected = IntegerType(10),
actual = listOf(IntegerType(10))
)
)
.isTrue()
}

@Test
fun evaluate_greaterOrEqual_noAnswersGreaterOrEqualEnableWhenAnswer_shouldReturnFalse() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.GREATER_OR_EQUAL,
expected = IntegerType(10),
actual = listOf(IntegerType(5))
)
)
.isFalse()
}

@Test
fun evaluate_lessThan_answersLessThanEnableWhenAnswer_shouldReturnTrue() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.LESS_THAN,
expected = IntegerType(10),
actual = listOf(IntegerType(5))
)
)
.isTrue()
}

@Test
fun evaluate_lessThan_noAnswersLessThanEnableWhenAnswer_shouldReturnFalse() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.LESS_THAN,
expected = IntegerType(10),
actual = listOf(IntegerType(20))
)
)
.isFalse()
}

@Test
fun evaluate_lessOrEqual_answerLessOrEqualEnableWhenAnswer_shouldReturnTrue() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.LESS_OR_EQUAL,
expected = IntegerType(10),
actual = listOf(IntegerType(10))
)
)
.isTrue()
}

@Test
fun evaluate_lessOrEqual_noAnswerLessOrEqualEnableWhenAnswer_shouldReturnFalse() {
santosh-pingle marked this conversation as resolved.
Show resolved Hide resolved
evaluateEnableWhen(
behavior = null,
EnableWhen(
operator = Questionnaire.QuestionnaireItemOperator.LESS_OR_EQUAL,
expected = IntegerType(10),
actual = listOf(IntegerType(20))
)
)
.isFalse()
}

/**
* Evaluates multiple `enableWhen` constraints according to the `behavior` (any or all).
*
Expand Down