Skip to content

Commit

Permalink
Add config Composition section to support custom search parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
LZRS committed Jan 22, 2025
1 parent 9ffbae4 commit 292dc8b
Show file tree
Hide file tree
Showing 13 changed files with 410 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid
import org.smartregister.fhircore.engine.util.extension.fileExtension
import org.smartregister.fhircore.engine.util.extension.generateMissingId
import org.smartregister.fhircore.engine.util.extension.interpolate
import org.smartregister.fhircore.engine.util.extension.retrieveCompositionSections
import org.smartregister.fhircore.engine.util.extension.retrieveCompositionSectionsExcludingCustomSearchParameters
import org.smartregister.fhircore.engine.util.extension.retrieveRelatedEntitySyncLocationState
import org.smartregister.fhircore.engine.util.extension.searchCompositionByIdentifier
import org.smartregister.fhircore.engine.util.extension.updateLastUpdated
Expand Down Expand Up @@ -264,7 +264,7 @@ constructor(

localCompositionResource.run {
val iconConfigs =
retrieveCompositionSections().filter {
retrieveCompositionSectionsExcludingCustomSearchParameters().filter {
it.focus.hasIdentifier() && isIconConfig(it.focus.identifier.value)
}
if (iconConfigs.isNotEmpty()) {
Expand Down Expand Up @@ -335,7 +335,8 @@ constructor(
}
}
} else {
composition.retrieveCompositionSections().forEach { sectionComponent ->
composition.retrieveCompositionSectionsExcludingCustomSearchParameters().forEach {
sectionComponent ->
if (sectionComponent.hasFocus()) {
addBinaryToConfigsJsonMap(
sectionComponent.focus,
Expand Down Expand Up @@ -432,7 +433,8 @@ constructor(
val parsedAppId = appId.substringBefore(TYPE_REFERENCE_DELIMITER).trim()
val compositionResource = fetchRemoteCompositionByAppId(parsedAppId)
compositionResource?.let { composition ->
val compositionSections = composition.retrieveCompositionSections()
val compositionSections =
composition.retrieveCompositionSectionsExcludingCustomSearchParameters()
val sectionComponentMap = mutableMapOf<String, MutableList<Composition.SectionComponent>>()
compositionSections.forEach { sectionComponent ->
if (sectionComponent.hasFocus() && sectionComponent.focus.hasReferenceElement()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
package org.smartregister.fhircore.engine.configuration.app

import org.hl7.fhir.r4.model.Coding
import org.hl7.fhir.r4.model.Enumerations
import org.hl7.fhir.r4.model.ResourceType
import org.hl7.fhir.r4.model.SearchParameter
import org.smartregister.fhircore.engine.sync.ResourceTag
import org.smartregister.fhircore.engine.util.SharedPreferenceKey
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
Expand Down Expand Up @@ -73,70 +71,7 @@ interface ConfigService {
return tags
}

/**
* Provide a list of custom search parameters.
*
* @return list of predefined custom search parameters.
*/
fun provideCustomSearchParameters(): List<SearchParameter> {
val activeGroupSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/group-active"
addBase("Group")
name = ACTIVE_SEARCH_PARAM
code = ACTIVE_SEARCH_PARAM
type = Enumerations.SearchParamType.TOKEN
expression = "Group.active"
description = "Search the active field"
}

val flagStatusSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/flag-status"
addBase("Flag")
name = STATUS_SEARCH_PARAM
code = STATUS_SEARCH_PARAM
type = Enumerations.SearchParamType.TOKEN
expression = "Flag.status"
description = "Search the status field"
}

val medicationSortSearchParameter =
SearchParameter().apply {
url = MEDICATION_SORT_URL
addBase("Medication")
name = SORT_SEARCH_PARAM
code = SORT_SEARCH_PARAM
type = Enumerations.SearchParamType.NUMBER
expression = "Medication.extension.where(url = '$MEDICATION_SORT_URL').value"
description = "Search the sort field"
}

val patientSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/patient-search"
addBase("Patient")
name = SEARCH_PARAM
code = SEARCH_PARAM
type = Enumerations.SearchParamType.STRING
expression = "Patient.name.text | Patient.identifier.value"
description = "Search patients by name and identifier fields"
}

return listOf(
activeGroupSearchParameter,
flagStatusSearchParameter,
medicationSortSearchParameter,
patientSearchParameter,
)
}

companion object {
const val ACTIVE_SEARCH_PARAM = "active"
const val APP_VERSION = "AppVersion"
const val STATUS_SEARCH_PARAM = "status"
const val SORT_SEARCH_PARAM = "sort"
const val SEARCH_PARAM = "search"
const val MEDICATION_SORT_URL = "http://smartregister.org/SearchParameter/medication-sort"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2021-2024 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.engine.configuration.customsearch

import org.hl7.fhir.r4.model.Bundle

interface ISearchParametersConfigStore {

suspend fun write(bundle: Bundle)

fun read(): Bundle?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright 2021-2024 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.engine.configuration.customsearch

import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Enumerations
import org.hl7.fhir.r4.model.ResourceType
import org.hl7.fhir.r4.model.SearchParameter

class SearchParametersConfigService(
private val store: ISearchParametersConfigStore,

Check warning on line 25 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L24-L25

Added lines #L24 - L25 were not covered by tests
) {

fun getCustomSearchParameters(): List<SearchParameter> {
return predefinedCustomSearchParameters + readSavedSearchParameters()

Check warning on line 29 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L29

Added line #L29 was not covered by tests
}

private fun readSavedSearchParameters(): List<SearchParameter> {
val searchParametersBundle = store.read() ?: return emptyList()

return searchParametersBundle.entry

Check warning on line 35 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L35

Added line #L35 was not covered by tests
.filter { it.resource.resourceType == ResourceType.SearchParameter }
.mapNotNull { it.resource as? SearchParameter }
}

suspend fun saveBundle(bundle: Bundle) {
store.write(bundle)

Check warning on line 41 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L41

Added line #L41 was not covered by tests
}

/** List of predefined custom search parameters. */
private val predefinedCustomSearchParameters: List<SearchParameter>
get() {
val activeGroupSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/group-active"
addBase("Group")
name = ACTIVE_SEARCH_PARAM
code = ACTIVE_SEARCH_PARAM
type = Enumerations.SearchParamType.TOKEN
expression = "Group.active"
description = "Search the active field"

Check warning on line 55 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L47-L55

Added lines #L47 - L55 were not covered by tests
}

val flagStatusSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/flag-status"
addBase("Flag")
name = STATUS_SEARCH_PARAM
code = STATUS_SEARCH_PARAM
type = Enumerations.SearchParamType.TOKEN
expression = "Flag.status"
description = "Search the status field"

Check warning on line 66 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L58-L66

Added lines #L58 - L66 were not covered by tests
}

val medicationSortSearchParameter =
SearchParameter().apply {
url = MEDICATION_SORT_URL
addBase("Medication")
name = SORT_SEARCH_PARAM
code = SORT_SEARCH_PARAM
type = Enumerations.SearchParamType.NUMBER
expression = "Medication.extension.where(url = '$MEDICATION_SORT_URL').value"
description = "Search the sort field"

Check warning on line 77 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L69-L77

Added lines #L69 - L77 were not covered by tests
}

val patientSearchParameter =
SearchParameter().apply {
url = "http://smartregister.org/SearchParameter/patient-search"
addBase("Patient")
name = SEARCH_PARAM
code = SEARCH_PARAM
type = Enumerations.SearchParamType.STRING
expression = "Patient.name.text | Patient.identifier.value"
description = "Search patients by name and identifier fields"

Check warning on line 88 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L80-L88

Added lines #L80 - L88 were not covered by tests
}

return listOf(
activeGroupSearchParameter,
flagStatusSearchParameter,
medicationSortSearchParameter,
patientSearchParameter,

Check warning on line 95 in android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt

View check run for this annotation

Codecov / codecov/patch

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/customsearch/SearchParametersConfigService.kt#L91-L95

Added lines #L91 - L95 were not covered by tests
)
}

companion object {
private const val ACTIVE_SEARCH_PARAM = "active"
private const val STATUS_SEARCH_PARAM = "status"
private const val SORT_SEARCH_PARAM = "sort"
private const val SEARCH_PARAM = "search"
private const val MEDICATION_SORT_URL =
"http://smartregister.org/SearchParameter/medication-sort"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2021-2024 Ona Systems, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.smartregister.fhircore.engine.di

import android.content.Context
import ca.uhn.fhir.parser.IParser
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import javax.inject.Singleton
import kotlinx.coroutines.withContext
import org.hl7.fhir.r4.model.Bundle
import org.smartregister.fhircore.engine.configuration.customsearch.ISearchParametersConfigStore
import org.smartregister.fhircore.engine.configuration.customsearch.SearchParametersConfigService
import org.smartregister.fhircore.engine.util.DispatcherProvider

@InstallIn(SingletonComponent::class)
@Module
class CustomSearchModule {

@Singleton
@Provides
@SearchParametersFileStore
fun provideCustomSearchParameterConfigStore(
@ApplicationContext context: Context,
parser: IParser,
dispatcherProvider: DispatcherProvider,
): ISearchParametersConfigStore {
val searchParametersFileName = "customSearchParameters.json"
val searchParametersFile = File(context.filesDir, searchParametersFileName)

return object : ISearchParametersConfigStore {
override suspend fun write(bundle: Bundle) {
withContext(dispatcherProvider.io()) {
FileOutputStream(searchParametersFile).use {
it.write(parser.encodeResourceToString(bundle).toByteArray())
}
}
}

override fun read(): Bundle? {
if (!searchParametersFile.exists()) return null
return FileInputStream(searchParametersFile).bufferedReader().use {
parser.parseResource(Bundle::class.java, it)
}
}
}
}

@Singleton
@Provides
fun provideCustomSearchParameterService(
@SearchParametersFileStore searchParametersStore: ISearchParametersConfigStore,
): SearchParametersConfigService {
return SearchParametersConfigService(searchParametersStore)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.smartregister.fhircore.engine.BuildConfig
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.configuration.customsearch.SearchParametersConfigService
import org.smartregister.fhircore.engine.data.remote.shared.TokenAuthenticator
import org.smartregister.fhircore.engine.di.NetworkModule.Companion.AUTHORIZATION
import org.smartregister.fhircore.engine.di.NetworkModule.Companion.COOKIE
Expand All @@ -51,6 +52,7 @@ class FhirEngineModule {
@ApplicationContext context: Context,
tokenAuthenticator: TokenAuthenticator,
configService: ConfigService,
customSearchParameterService: SearchParametersConfigService,
): FhirEngine {
FhirEngineProvider.init(
FhirEngineConfiguration(
Expand All @@ -76,7 +78,7 @@ class FhirEngineModule {
Timber.tag(QUEST_OKHTTP_CLIENT_TAG).d(it)
},
),
customSearchParameters = configService.provideCustomSearchParameters(),
customSearchParameters = customSearchParameterService.getCustomSearchParameters(),
),
)
return FhirEngineProvider.getInstance(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ annotation class KeycloakRetrofit
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class RegularRetrofit

@ExcludeFromJacocoGeneratedReport
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class SearchParametersFileStore
Loading

0 comments on commit 292dc8b

Please sign in to comment.