Skip to content

Commit

Permalink
Merge branch 'master' into jt/common-release-update
Browse files Browse the repository at this point in the history
  • Loading branch information
jingtang10 authored May 3, 2022
2 parents 0cab77d + 2d80744 commit 3c01feb
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,26 @@ open class QuestionnaireFragment : Fragment() {
* If this and [EXTRA_QUESTIONNAIRE_JSON_STRING] are provided, this extra takes precedence.
*/
const val EXTRA_QUESTIONNAIRE_JSON_URI = "questionnaire-uri"
/** A JSON encoded string extra for a prefilled questionnaire response. */
/**
* A JSON encoded string extra for a prefilled questionnaire response. This should only be used
* for questionnaire response with size at most 512KB. For large questionnaire response, use
* [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI].
*
* This is required unless [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI] is provided.
*
* If this and [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI] are provided,
* [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI] takes precedence.
*/
const val EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING = "questionnaire-response"
/**
* A [Uri] extra for streaming a JSON encoded questionnaire response.
*
* This is required unless [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING] is provided.
*
* If this and [EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING] are provided, this extra takes
* precedence.
*/
const val EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI = "questionnaire-response-uri"
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import ca.uhn.fhir.context.FhirContext
import ca.uhn.fhir.context.FhirVersionEnum
import ca.uhn.fhir.parser.IParser
import com.google.android.fhir.datacapture.enablement.EnablementEvaluator
import com.google.android.fhir.datacapture.validation.QuestionnaireResponseValidator.checkQuestionnaireResponse
import com.google.android.fhir.datacapture.views.QuestionnaireItemViewItem
Expand All @@ -41,6 +42,9 @@ import timber.log.Timber

internal class QuestionnaireViewModel(application: Application, state: SavedStateHandle) :
AndroidViewModel(application) {

private val parser: IParser by lazy { FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() }

/** The current questionnaire as questions are being answered. */
internal val questionnaire: Questionnaire

Expand All @@ -55,18 +59,12 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat
)
}
val uri: Uri = state[QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_URI]!!
FhirContext.forCached(FhirVersionEnum.R4)
.newJsonParser()
.parseResource(application.contentResolver.openInputStream(uri)) as
Questionnaire
parser.parseResource(application.contentResolver.openInputStream(uri)) as Questionnaire
}
state.contains(QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_STRING) -> {
val questionnaireJson: String =
state[QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_STRING]!!
FhirContext.forCached(FhirVersionEnum.R4)
.newJsonParser()
.parseResource(questionnaireJson) as
Questionnaire
parser.parseResource(questionnaireJson) as Questionnaire
}
else ->
error("Neither EXTRA_QUESTIONNAIRE_URI nor EXTRA_JSON_ENCODED_QUESTIONNAIRE is supplied.")
Expand All @@ -77,24 +75,37 @@ internal class QuestionnaireViewModel(application: Application, state: SavedStat
private val questionnaireResponse: QuestionnaireResponse

init {
val questionnaireJsonResponseString: String? =
state[QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING]
if (questionnaireJsonResponseString != null) {
questionnaireResponse =
FhirContext.forCached(FhirVersionEnum.R4)
.newJsonParser()
.parseResource(questionnaireJsonResponseString) as
QuestionnaireResponse
checkQuestionnaireResponse(questionnaire, questionnaireResponse)
} else {
questionnaireResponse =
QuestionnaireResponse().apply {
questionnaire = this@QuestionnaireViewModel.questionnaire.url
when {
state.contains(QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI) -> {
if (state.contains(QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING)) {
Timber.w(
"Both EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI & EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING are provided. " +
"EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI takes precedence."
)
}
val uri: Uri = state[QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI]!!
questionnaireResponse =
parser.parseResource(application.contentResolver.openInputStream(uri)) as
QuestionnaireResponse
checkQuestionnaireResponse(questionnaire, questionnaireResponse)
}
state.contains(QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING) -> {
val questionnaireResponseJson: String =
state[QuestionnaireFragment.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING]!!
questionnaireResponse =
parser.parseResource(questionnaireResponseJson) as QuestionnaireResponse
checkQuestionnaireResponse(questionnaire, questionnaireResponse)
}
else -> {
questionnaireResponse =
QuestionnaireResponse().apply {
questionnaire = this@QuestionnaireViewModel.questionnaire.url
}
// Retain the hierarchy and order of items within the questionnaire as specified in the
// standard. See https://www.hl7.org/fhir/questionnaireresponse.html#notes.
questionnaire.item.forEach {
questionnaireResponse.addItem(it.createQuestionnaireResponseItem())
}
// Retain the hierarchy and order of items within the questionnaire as specified in the
// standard. See https://www.hl7.org/fhir/questionnaireresponse.html#notes.
questionnaire.item.forEach {
questionnaireResponse.addItem(it.createQuestionnaireResponseItem())
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import ca.uhn.fhir.parser.IParser
import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_JSON_STRING
import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_JSON_URI
import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING
import com.google.android.fhir.datacapture.QuestionnaireFragment.Companion.EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI
import com.google.android.fhir.datacapture.testing.DataCaptureTestApplication
import com.google.common.truth.Truth.assertThat
import java.io.File
Expand Down Expand Up @@ -53,7 +54,10 @@ import org.robolectric.util.ReflectionHelpers

@RunWith(ParameterizedRobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.P], application = DataCaptureTestApplication::class)
class QuestionnaireViewModelTest(private val questionnaireSource: QuestionnaireSource) {
class QuestionnaireViewModelTest(
private val questionnaireSource: QuestionnaireSource,
private val questionnaireResponseSource: QuestionnaireResponseSource
) {
private lateinit var state: SavedStateHandle
private val context = ApplicationProvider.getApplicationContext<Application>()

Expand Down Expand Up @@ -1424,7 +1428,7 @@ class QuestionnaireViewModelTest(private val questionnaireSource: QuestionnaireS

private fun createQuestionnaireViewModel(
questionnaire: Questionnaire,
response: QuestionnaireResponse? = null
questionnaireResponse: QuestionnaireResponse? = null
): QuestionnaireViewModel {
if (questionnaireSource == QuestionnaireSource.STRING) {
state.set(EXTRA_QUESTIONNAIRE_JSON_STRING, printer.encodeResourceToString(questionnaire))
Expand All @@ -1438,9 +1442,25 @@ class QuestionnaireViewModelTest(private val questionnaireSource: QuestionnaireS
shadowOf(context.contentResolver)
.registerInputStream(questionnaireUri, questionnaireFile.inputStream())
}
response?.let {
state.set(EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING, printer.encodeResourceToString(it))

questionnaireResponse?.let {
if (questionnaireResponseSource == QuestionnaireResponseSource.STRING) {
state.set(
EXTRA_QUESTIONNAIRE_RESPONSE_JSON_STRING,
printer.encodeResourceToString(questionnaireResponse)
)
} else if (questionnaireResponseSource == QuestionnaireResponseSource.URI) {
val questionnaireResponseFile = File(context.cacheDir, "test_questionnaire_response")
questionnaireResponseFile.outputStream().bufferedWriter().use {
printer.encodeResourceToWriter(questionnaireResponse, it)
}
val questionnaireResponseUri = Uri.fromFile(questionnaireResponseFile)
state.set(EXTRA_QUESTIONNAIRE_RESPONSE_JSON_URI, questionnaireResponseUri)
shadowOf(context.contentResolver)
.registerInputStream(questionnaireResponseUri, questionnaireResponseFile.inputStream())
}
}

return QuestionnaireViewModel(context, state)
}

Expand All @@ -1457,8 +1477,14 @@ class QuestionnaireViewModelTest(private val questionnaireSource: QuestionnaireS
}

@JvmStatic
@Parameters(name = "questionnaireSource={0}")
fun parameters() = listOf(QuestionnaireSource.STRING, QuestionnaireSource.URI)
@Parameters
fun parameters() =
listOf(
arrayOf(QuestionnaireSource.URI, QuestionnaireResponseSource.URI),
arrayOf(QuestionnaireSource.URI, QuestionnaireResponseSource.STRING),
arrayOf(QuestionnaireSource.STRING, QuestionnaireResponseSource.URI),
arrayOf(QuestionnaireSource.STRING, QuestionnaireResponseSource.STRING)
)
}
}

Expand All @@ -1467,3 +1493,9 @@ enum class QuestionnaireSource {
STRING,
URI
}

/** The source of questionnaire-response. */
enum class QuestionnaireResponseSource {
STRING,
URI
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import kotlinx.coroutines.test.runBlockingTest
import org.hl7.fhir.r4.model.Bundle
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
Expand Down Expand Up @@ -212,6 +213,7 @@ class SyncJobTest {
}

@Test
@Ignore("https://github.com/google/android-fhir/issues/1357")
fun `sync time should update on every sync call`() = runBlockingTest {
val worker1 = PeriodicWorkRequestBuilder<TestSyncWorker>(15, TimeUnit.MINUTES).build()

Expand Down

0 comments on commit 3c01feb

Please sign in to comment.