Skip to content

Commit

Permalink
Definition Based Extraction: Extract repeating order elements properl…
Browse files Browse the repository at this point in the history
…y. (#1703)

* Updated updateField to use separate method for adding value to list

* Review comments updates
  • Loading branch information
aditya-07 committed Nov 15, 2022
1 parent 8ebba46 commit 0744364
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import ca.uhn.fhir.context.FhirVersionEnum
import com.google.android.fhir.datacapture.DataCapture
import com.google.android.fhir.datacapture.createQuestionnaireResponseItem
import com.google.android.fhir.datacapture.targetStructureMap
import com.google.android.fhir.datacapture.utilities.fhirPathEngine
import com.google.android.fhir.datacapture.utilities.toCodeType
import com.google.android.fhir.datacapture.utilities.toCoding
import com.google.android.fhir.datacapture.utilities.toIdType
Expand Down Expand Up @@ -536,6 +535,22 @@ private fun updateFieldWithEnum(base: Base, field: Field, value: Base) {
.invoke(base, fromCodeMethod.invoke(dataTypeClass, stringValue))
}

/**
* The api's used to updateField with answers are:
*
* * For Parameterized list of primitive type e.g HumanName.given of type List<StringType>
* ```
* addGiven(String) - adds a new StringType to the list.
* ```
* * For any primitive value e.g for Patient.active which is of BooleanType
* ```
* setActiveElement(BooleanType)
* ```
* * In case they fail,
* ```
* setName(List<HumanName>) - replaces old list if any with the new list.
* ```
*/
private fun updateField(
base: Base,
field: Field,
Expand All @@ -545,19 +560,32 @@ private fun updateField(
answers.map { wrapAnswerInFieldType(it.value, field) }.toCollection(mutableListOf())

try {
updateFieldWithAnswer(base, field, answersOfFieldType.first())
if (field.isParameterized && field.isList) {
addAnswerToListField(base, field, answersOfFieldType)
} else {
setFieldElementValue(base, field, answersOfFieldType.first())
}
} catch (e: NoSuchMethodException) {
// some set methods expect a list of objects
updateListFieldWithAnswer(base, field, answersOfFieldType)
}
}

private fun updateFieldWithAnswer(base: Base, field: Field, answerValue: Base) {
private fun setFieldElementValue(base: Base, field: Field, answerValue: Base) {
base.javaClass
.getMethod("set${field.name.capitalize(Locale.ROOT)}Element", field.type)
.invoke(base, answerValue)
}

private fun addAnswerToListField(base: Base, field: Field, answerValue: List<Base>) {
base.javaClass
.getMethod(
"add${field.name.capitalize(Locale.ROOT)}",
answerValue.first().primitiveValue().javaClass
)
.let { method -> answerValue.forEach { method.invoke(base, it.primitiveValue()) } }
}

private fun updateListFieldWithAnswer(base: Base, field: Field, answerValue: List<Base>) {
base.javaClass
.getMethod("set${field.name.capitalize(Locale.ROOT)}", field.type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,93 @@ class ResourceMapperTest {
.isEqualTo("TestName")
}

@Test
fun `extract() definition based extraction should extract multiple values of a list field in a group`():
Unit = runBlocking {
@Language("JSON")
val questionnaire =
"""
{
"resourceType": "Questionnaire",
"subjectType": [
"Patient"
],
"extension": [
{
"url": "http:https://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext",
"valueExpression": {
"language": "application/x-fhir-query",
"expression": "Patient",
"name": "patient"
}
}
],
"item": [
{
"linkId": "PR-name",
"type": "group",
"definition": "http:https://hl7.org/fhir/StructureDefinition/Patient#Patient.name",
"item": [
{
"linkId": "PR-name-text",
"definition": "http:https://hl7.org/fhir/StructureDefinition/Patient#Patient.name.given",
"type": "string",
"text": "First Name"
},
{
"linkId": "PR-name-middle",
"definition": "http:https://hl7.org/fhir/StructureDefinition/datatypes#Patient.name.given",
"type": "string",
"text": "Middle Name"
}
]
}
]
}
""".trimIndent()

@Language("JSON")
val response =
"""
{
"resourceType": "QuestionnaireResponse",
"item": [
{
"linkId": "PR-name",
"item": [
{
"linkId": "PR-name-text",
"answer": [
{
"valueString": "TestName-First"
}
]
},{
"linkId": "PR-name-middle",
"answer": [
{
"valueString": "TestName-Middle"
}
]
}
]
}
]
}
""".trimIndent()
val iParser: IParser = FhirContext.forR4().newJsonParser()
val questionnaireObj =
iParser.parseResource(Questionnaire::class.java, questionnaire) as Questionnaire
val temperatureQuestionnaireResponse =
iParser.parseResource(QuestionnaireResponse::class.java, response) as QuestionnaireResponse
val bundle = ResourceMapper.extract(questionnaireObj, temperatureQuestionnaireResponse)
val patient = bundle.entry.single().resource as Patient

assertThat(patient).isNotNull()
assertThat(patient.name.first().given.map { it.value })
.containsExactly("TestName-First", "TestName-Middle")
}

private fun String.toDateFromFormatYyyyMmDd(): Date? = SimpleDateFormat("yyyy-MM-dd").parse(this)

class TransformSupportServices(private val outputs: MutableList<Base>) :
Expand Down

0 comments on commit 0744364

Please sign in to comment.