Skip to content

Commit 292dc8b

Browse files
committed
Add config Composition section to support custom search parameters
1 parent 9ffbae4 commit 292dc8b

File tree

13 files changed

+410
-149
lines changed

13 files changed

+410
-149
lines changed

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/ConfigurationRegistry.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ import org.smartregister.fhircore.engine.util.extension.extractLogicalIdUuid
7171
import org.smartregister.fhircore.engine.util.extension.fileExtension
7272
import org.smartregister.fhircore.engine.util.extension.generateMissingId
7373
import org.smartregister.fhircore.engine.util.extension.interpolate
74-
import org.smartregister.fhircore.engine.util.extension.retrieveCompositionSections
74+
import org.smartregister.fhircore.engine.util.extension.retrieveCompositionSectionsExcludingCustomSearchParameters
7575
import org.smartregister.fhircore.engine.util.extension.retrieveRelatedEntitySyncLocationState
7676
import org.smartregister.fhircore.engine.util.extension.searchCompositionByIdentifier
7777
import org.smartregister.fhircore.engine.util.extension.updateLastUpdated
@@ -264,7 +264,7 @@ constructor(
264264

265265
localCompositionResource.run {
266266
val iconConfigs =
267-
retrieveCompositionSections().filter {
267+
retrieveCompositionSectionsExcludingCustomSearchParameters().filter {
268268
it.focus.hasIdentifier() && isIconConfig(it.focus.identifier.value)
269269
}
270270
if (iconConfigs.isNotEmpty()) {
@@ -335,7 +335,8 @@ constructor(
335335
}
336336
}
337337
} else {
338-
composition.retrieveCompositionSections().forEach { sectionComponent ->
338+
composition.retrieveCompositionSectionsExcludingCustomSearchParameters().forEach {
339+
sectionComponent ->
339340
if (sectionComponent.hasFocus()) {
340341
addBinaryToConfigsJsonMap(
341342
sectionComponent.focus,
@@ -432,7 +433,8 @@ constructor(
432433
val parsedAppId = appId.substringBefore(TYPE_REFERENCE_DELIMITER).trim()
433434
val compositionResource = fetchRemoteCompositionByAppId(parsedAppId)
434435
compositionResource?.let { composition ->
435-
val compositionSections = composition.retrieveCompositionSections()
436+
val compositionSections =
437+
composition.retrieveCompositionSectionsExcludingCustomSearchParameters()
436438
val sectionComponentMap = mutableMapOf<String, MutableList<Composition.SectionComponent>>()
437439
compositionSections.forEach { sectionComponent ->
438440
if (sectionComponent.hasFocus() && sectionComponent.focus.hasReferenceElement()) {

android/engine/src/main/java/org/smartregister/fhircore/engine/configuration/app/ConfigService.kt

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
package org.smartregister.fhircore.engine.configuration.app
1818

1919
import org.hl7.fhir.r4.model.Coding
20-
import org.hl7.fhir.r4.model.Enumerations
2120
import org.hl7.fhir.r4.model.ResourceType
22-
import org.hl7.fhir.r4.model.SearchParameter
2321
import org.smartregister.fhircore.engine.sync.ResourceTag
2422
import org.smartregister.fhircore.engine.util.SharedPreferenceKey
2523
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
@@ -73,70 +71,7 @@ interface ConfigService {
7371
return tags
7472
}
7573

76-
/**
77-
* Provide a list of custom search parameters.
78-
*
79-
* @return list of predefined custom search parameters.
80-
*/
81-
fun provideCustomSearchParameters(): List<SearchParameter> {
82-
val activeGroupSearchParameter =
83-
SearchParameter().apply {
84-
url = "http://smartregister.org/SearchParameter/group-active"
85-
addBase("Group")
86-
name = ACTIVE_SEARCH_PARAM
87-
code = ACTIVE_SEARCH_PARAM
88-
type = Enumerations.SearchParamType.TOKEN
89-
expression = "Group.active"
90-
description = "Search the active field"
91-
}
92-
93-
val flagStatusSearchParameter =
94-
SearchParameter().apply {
95-
url = "http://smartregister.org/SearchParameter/flag-status"
96-
addBase("Flag")
97-
name = STATUS_SEARCH_PARAM
98-
code = STATUS_SEARCH_PARAM
99-
type = Enumerations.SearchParamType.TOKEN
100-
expression = "Flag.status"
101-
description = "Search the status field"
102-
}
103-
104-
val medicationSortSearchParameter =
105-
SearchParameter().apply {
106-
url = MEDICATION_SORT_URL
107-
addBase("Medication")
108-
name = SORT_SEARCH_PARAM
109-
code = SORT_SEARCH_PARAM
110-
type = Enumerations.SearchParamType.NUMBER
111-
expression = "Medication.extension.where(url = '$MEDICATION_SORT_URL').value"
112-
description = "Search the sort field"
113-
}
114-
115-
val patientSearchParameter =
116-
SearchParameter().apply {
117-
url = "http://smartregister.org/SearchParameter/patient-search"
118-
addBase("Patient")
119-
name = SEARCH_PARAM
120-
code = SEARCH_PARAM
121-
type = Enumerations.SearchParamType.STRING
122-
expression = "Patient.name.text | Patient.identifier.value"
123-
description = "Search patients by name and identifier fields"
124-
}
125-
126-
return listOf(
127-
activeGroupSearchParameter,
128-
flagStatusSearchParameter,
129-
medicationSortSearchParameter,
130-
patientSearchParameter,
131-
)
132-
}
133-
13474
companion object {
135-
const val ACTIVE_SEARCH_PARAM = "active"
13675
const val APP_VERSION = "AppVersion"
137-
const val STATUS_SEARCH_PARAM = "status"
138-
const val SORT_SEARCH_PARAM = "sort"
139-
const val SEARCH_PARAM = "search"
140-
const val MEDICATION_SORT_URL = "http://smartregister.org/SearchParameter/medication-sort"
14176
}
14277
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2021-2024 Ona Systems, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.smartregister.fhircore.engine.configuration.customsearch
18+
19+
import org.hl7.fhir.r4.model.Bundle
20+
21+
interface ISearchParametersConfigStore {
22+
23+
suspend fun write(bundle: Bundle)
24+
25+
fun read(): Bundle?
26+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2021-2024 Ona Systems, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.smartregister.fhircore.engine.configuration.customsearch
18+
19+
import org.hl7.fhir.r4.model.Bundle
20+
import org.hl7.fhir.r4.model.Enumerations
21+
import org.hl7.fhir.r4.model.ResourceType
22+
import org.hl7.fhir.r4.model.SearchParameter
23+
24+
class SearchParametersConfigService(
25+
private val store: ISearchParametersConfigStore,
26+
) {
27+
28+
fun getCustomSearchParameters(): List<SearchParameter> {
29+
return predefinedCustomSearchParameters + readSavedSearchParameters()
30+
}
31+
32+
private fun readSavedSearchParameters(): List<SearchParameter> {
33+
val searchParametersBundle = store.read() ?: return emptyList()
34+
35+
return searchParametersBundle.entry
36+
.filter { it.resource.resourceType == ResourceType.SearchParameter }
37+
.mapNotNull { it.resource as? SearchParameter }
38+
}
39+
40+
suspend fun saveBundle(bundle: Bundle) {
41+
store.write(bundle)
42+
}
43+
44+
/** List of predefined custom search parameters. */
45+
private val predefinedCustomSearchParameters: List<SearchParameter>
46+
get() {
47+
val activeGroupSearchParameter =
48+
SearchParameter().apply {
49+
url = "http://smartregister.org/SearchParameter/group-active"
50+
addBase("Group")
51+
name = ACTIVE_SEARCH_PARAM
52+
code = ACTIVE_SEARCH_PARAM
53+
type = Enumerations.SearchParamType.TOKEN
54+
expression = "Group.active"
55+
description = "Search the active field"
56+
}
57+
58+
val flagStatusSearchParameter =
59+
SearchParameter().apply {
60+
url = "http://smartregister.org/SearchParameter/flag-status"
61+
addBase("Flag")
62+
name = STATUS_SEARCH_PARAM
63+
code = STATUS_SEARCH_PARAM
64+
type = Enumerations.SearchParamType.TOKEN
65+
expression = "Flag.status"
66+
description = "Search the status field"
67+
}
68+
69+
val medicationSortSearchParameter =
70+
SearchParameter().apply {
71+
url = MEDICATION_SORT_URL
72+
addBase("Medication")
73+
name = SORT_SEARCH_PARAM
74+
code = SORT_SEARCH_PARAM
75+
type = Enumerations.SearchParamType.NUMBER
76+
expression = "Medication.extension.where(url = '$MEDICATION_SORT_URL').value"
77+
description = "Search the sort field"
78+
}
79+
80+
val patientSearchParameter =
81+
SearchParameter().apply {
82+
url = "http://smartregister.org/SearchParameter/patient-search"
83+
addBase("Patient")
84+
name = SEARCH_PARAM
85+
code = SEARCH_PARAM
86+
type = Enumerations.SearchParamType.STRING
87+
expression = "Patient.name.text | Patient.identifier.value"
88+
description = "Search patients by name and identifier fields"
89+
}
90+
91+
return listOf(
92+
activeGroupSearchParameter,
93+
flagStatusSearchParameter,
94+
medicationSortSearchParameter,
95+
patientSearchParameter,
96+
)
97+
}
98+
99+
companion object {
100+
private const val ACTIVE_SEARCH_PARAM = "active"
101+
private const val STATUS_SEARCH_PARAM = "status"
102+
private const val SORT_SEARCH_PARAM = "sort"
103+
private const val SEARCH_PARAM = "search"
104+
private const val MEDICATION_SORT_URL =
105+
"http://smartregister.org/SearchParameter/medication-sort"
106+
}
107+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2021-2024 Ona Systems, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.smartregister.fhircore.engine.di
18+
19+
import android.content.Context
20+
import ca.uhn.fhir.parser.IParser
21+
import dagger.Module
22+
import dagger.Provides
23+
import dagger.hilt.InstallIn
24+
import dagger.hilt.android.qualifiers.ApplicationContext
25+
import dagger.hilt.components.SingletonComponent
26+
import java.io.File
27+
import java.io.FileInputStream
28+
import java.io.FileOutputStream
29+
import javax.inject.Singleton
30+
import kotlinx.coroutines.withContext
31+
import org.hl7.fhir.r4.model.Bundle
32+
import org.smartregister.fhircore.engine.configuration.customsearch.ISearchParametersConfigStore
33+
import org.smartregister.fhircore.engine.configuration.customsearch.SearchParametersConfigService
34+
import org.smartregister.fhircore.engine.util.DispatcherProvider
35+
36+
@InstallIn(SingletonComponent::class)
37+
@Module
38+
class CustomSearchModule {
39+
40+
@Singleton
41+
@Provides
42+
@SearchParametersFileStore
43+
fun provideCustomSearchParameterConfigStore(
44+
@ApplicationContext context: Context,
45+
parser: IParser,
46+
dispatcherProvider: DispatcherProvider,
47+
): ISearchParametersConfigStore {
48+
val searchParametersFileName = "customSearchParameters.json"
49+
val searchParametersFile = File(context.filesDir, searchParametersFileName)
50+
51+
return object : ISearchParametersConfigStore {
52+
override suspend fun write(bundle: Bundle) {
53+
withContext(dispatcherProvider.io()) {
54+
FileOutputStream(searchParametersFile).use {
55+
it.write(parser.encodeResourceToString(bundle).toByteArray())
56+
}
57+
}
58+
}
59+
60+
override fun read(): Bundle? {
61+
if (!searchParametersFile.exists()) return null
62+
return FileInputStream(searchParametersFile).bufferedReader().use {
63+
parser.parseResource(Bundle::class.java, it)
64+
}
65+
}
66+
}
67+
}
68+
69+
@Singleton
70+
@Provides
71+
fun provideCustomSearchParameterService(
72+
@SearchParametersFileStore searchParametersStore: ISearchParametersConfigStore,
73+
): SearchParametersConfigService {
74+
return SearchParametersConfigService(searchParametersStore)
75+
}
76+
}

android/engine/src/main/java/org/smartregister/fhircore/engine/di/FhirEngineModule.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import dagger.hilt.components.SingletonComponent
3232
import javax.inject.Singleton
3333
import org.smartregister.fhircore.engine.BuildConfig
3434
import org.smartregister.fhircore.engine.configuration.app.ConfigService
35+
import org.smartregister.fhircore.engine.configuration.customsearch.SearchParametersConfigService
3536
import org.smartregister.fhircore.engine.data.remote.shared.TokenAuthenticator
3637
import org.smartregister.fhircore.engine.di.NetworkModule.Companion.AUTHORIZATION
3738
import org.smartregister.fhircore.engine.di.NetworkModule.Companion.COOKIE
@@ -51,6 +52,7 @@ class FhirEngineModule {
5152
@ApplicationContext context: Context,
5253
tokenAuthenticator: TokenAuthenticator,
5354
configService: ConfigService,
55+
customSearchParameterService: SearchParametersConfigService,
5456
): FhirEngine {
5557
FhirEngineProvider.init(
5658
FhirEngineConfiguration(
@@ -76,7 +78,7 @@ class FhirEngineModule {
7678
Timber.tag(QUEST_OKHTTP_CLIENT_TAG).d(it)
7779
},
7880
),
79-
customSearchParameters = configService.provideCustomSearchParameters(),
81+
customSearchParameters = customSearchParameterService.getCustomSearchParameters(),
8082
),
8183
)
8284
return FhirEngineProvider.getInstance(context)

android/engine/src/main/java/org/smartregister/fhircore/engine/di/Qualifiers.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,8 @@ annotation class KeycloakRetrofit
4343
@Qualifier
4444
@Retention(AnnotationRetention.BINARY)
4545
annotation class RegularRetrofit
46+
47+
@ExcludeFromJacocoGeneratedReport
48+
@Qualifier
49+
@Retention(AnnotationRetention.BINARY)
50+
annotation class SearchParametersFileStore

0 commit comments

Comments
 (0)