Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal class ConfirmIdentifyRequestBuilder(
userId = extractor.getUserId().asTokenizableRaw(),
sessionId = extractor.getSessionId(),
selectedGuid = extractor.getSelectedGuid(),
metadata = extractor.getMetadata(),
unknownExtras = extractor.getUnknownExtras(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal object ConfirmIdentityActionFactory : RequestActionFactory() {
userId = MOCK_USER_ID.asTokenizableRaw(),
sessionId = MOCK_SESSION_ID,
selectedGuid = MOCK_SELECTED_GUID,
metadata = MOCK_METADATA,
unknownExtras = emptyMap()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ internal object ActionFactory {
userId = MOCK_USER_ID,
sessionId = "sessionId",
selectedGuid = "selectedGuid",
metadata = "",
unknownExtras = emptyMap()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ internal class BuildMatcherSubjectQueryUseCase @Inject constructor() {
actionRequest: ActionRequest,
) = when (projectConfiguration.identification.poolType) {
IdentificationConfiguration.PoolType.PROJECT -> SubjectQuery(
projectId = actionRequest.projectId
projectId = actionRequest.projectId,
metadata = actionRequest.metadata,
)

IdentificationConfiguration.PoolType.USER -> SubjectQuery(
projectId = actionRequest.projectId,
attendantId = actionRequest.userId.value
attendantId = actionRequest.userId.value,
metadata = actionRequest.metadata,
)

IdentificationConfiguration.PoolType.MODULE -> SubjectQuery(
projectId = actionRequest.projectId,
moduleId = (actionRequest as ActionRequest.FlowAction).moduleId.value
moduleId = (actionRequest as ActionRequest.FlowAction).moduleId.value,
metadata = actionRequest.metadata,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ShouldCreatePersonUseCaseTest {
userId = "".asTokenizableRaw(),
sessionId = "",
selectedGuid = "",
metadata = "",
unknownExtras = emptyMap(),
), modalities = emptySet(), results = emptyList()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.simprints.infra.enrolment.records.store.commcare

import android.content.Context
import android.database.Cursor
import android.net.Uri
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.module.SimpleModule
Expand All @@ -23,6 +24,7 @@ import com.simprints.infra.events.event.domain.models.subject.FingerprintReferen
import com.simprints.infra.logging.Simber
import com.simprints.libsimprints.Constants.SIMPRINTS_COSYNC_SUBJECT_ACTIONS
import dagger.hilt.android.qualifiers.ApplicationContext
import org.json.JSONException
import javax.inject.Inject

internal class CommCareIdentityDataSource @Inject constructor(
Expand All @@ -36,6 +38,8 @@ internal class CommCareIdentityDataSource @Inject constructor(
const val COLUMN_CASE_ID = "case_id"
const val COLUMN_DATUM_ID = "datum_id"
const val COLUMN_VALUE = "value"

const val ARG_CASE_ID = "caseId"
}

private fun getCaseMetadataUri(packageName: String): Uri =
Expand All @@ -48,7 +52,7 @@ internal class CommCareIdentityDataSource @Inject constructor(
query: SubjectQuery,
range: IntRange,
dataSource: BiometricDataSource,
): List<FingerprintIdentity> = loadEnrolmentRecordCreationEvents(range, dataSource.callerPackageName())
): List<FingerprintIdentity> = loadEnrolmentRecordCreationEvents(range, dataSource.callerPackageName(), query)
.filter { erce -> erce.payload.biometricReferences.any { it is FingerprintReference } }
.map {
FingerprintIdentity(
Expand All @@ -70,32 +74,48 @@ internal class CommCareIdentityDataSource @Inject constructor(
private fun loadEnrolmentRecordCreationEvents(
range: IntRange,
callerPackageName: String,
query: SubjectQuery,
): List<EnrolmentRecordCreationEvent> {
val enrolmentRecordCreationEvents: MutableList<EnrolmentRecordCreationEvent> = mutableListOf()

try {
val caseId = attemptExtractingCaseId(query.metadata)
if (caseId != null) {
return loadEnrolmentRecordCreationEvents(caseId, callerPackageName, query)
}

context.contentResolver.query(
getCaseMetadataUri(callerPackageName), null, null, null, null)?.use { caseMetadataCursor ->
if (caseMetadataCursor.moveToPosition(range.first)) {
do {
caseMetadataCursor.getString(caseMetadataCursor.getColumnIndexOrThrow(COLUMN_CASE_ID))?.let { caseId ->
enrolmentRecordCreationEvents.addAll(loadEnrolmentRecordCreationEvents(caseId, callerPackageName))
}
} while (caseMetadataCursor.moveToNext() && caseMetadataCursor.position < range.last)
}
getCaseMetadataUri(callerPackageName), null, null, null, null
)?.use { caseMetadataCursor ->
if (caseMetadataCursor.moveToPosition(range.first)) {
do {
caseMetadataCursor.getString(caseMetadataCursor.getColumnIndexOrThrow(COLUMN_CASE_ID))?.let { caseId ->
enrolmentRecordCreationEvents.addAll(loadEnrolmentRecordCreationEvents(caseId, callerPackageName, query))
}
} while (caseMetadataCursor.moveToNext() && caseMetadataCursor.position < range.last)
}
}
} catch (e: Exception) {
Simber.e("Error while querying CommCare", e)
}

return enrolmentRecordCreationEvents
}

private fun attemptExtractingCaseId(metadata: String?) = metadata
?.takeUnless { it.isEmpty() }
?.let {
try {
JsonHelper.fromJson<Map<String, Any>>(it)[ARG_CASE_ID] as? String
} catch (_: JSONException) {
null
}
}

override suspend fun loadFaceIdentities(
query: SubjectQuery,
range: IntRange,
dataSource: BiometricDataSource,
): List<FaceIdentity> = loadEnrolmentRecordCreationEvents(range, dataSource.callerPackageName())
): List<FaceIdentity> = loadEnrolmentRecordCreationEvents(range, dataSource.callerPackageName(), query)
.filter { erce -> erce.payload.biometricReferences.any { it is FaceReference } }
.map {
FaceIdentity(
Expand All @@ -115,55 +135,58 @@ internal class CommCareIdentityDataSource @Inject constructor(
private fun loadEnrolmentRecordCreationEvents(
caseId: String,
callerPackageName: String,
query: SubjectQuery,
): List<EnrolmentRecordCreationEvent> {
val caseEnrolmentRecordCreationEvents: MutableList<EnrolmentRecordCreationEvent> =
mutableListOf()

//Access Case Data Listing for the caseId
val caseDataUri = getCaseDataUri(callerPackageName).buildUpon().appendPath(caseId).build()
context.contentResolver.query(caseDataUri, null, null, null, null)?.use { caseDataCursor ->
var subjectActions = ""
while (caseDataCursor.moveToNext()) {
val key =
caseDataCursor.getString(caseDataCursor.getColumnIndexOrThrow(COLUMN_DATUM_ID))
if (key == SIMPRINTS_COSYNC_SUBJECT_ACTIONS) {
subjectActions =
caseDataCursor.getString(caseDataCursor.getColumnIndexOrThrow(COLUMN_VALUE))
break
}
}

val coSyncEnrolmentRecordEvents = subjectActions.takeIf(String::isNotEmpty)?.let {
try {
val coSyncSerializationModule = SimpleModule().apply {
addSerializer(
TokenizableString::class.java,
TokenizationClassNameSerializer()
)
addDeserializer(
TokenizableString::class.java,
TokenizationClassNameDeserializer()
)
}
jsonHelper.fromJson<CoSyncEnrolmentRecordEvents>(
json = it,
module = coSyncSerializationModule,
type = object : TypeReference<CoSyncEnrolmentRecordEvents>() {}
)
} catch (e: Exception) {
Simber.e("Error while parsing subjectActions", e)
null
return context.contentResolver.query(caseDataUri, null, null, null, null)?.use { caseDataCursor ->
var subjectActions = getSubjectActionsValue(caseDataCursor)
Simber.d(subjectActions)
val coSyncEnrolmentRecordEvents = parseRecordEvents(subjectActions)

coSyncEnrolmentRecordEvents?.events
?.filterIsInstance<EnrolmentRecordCreationEvent>()
?.filterNot { event ->
(query.subjectId != null && query.subjectId != event.payload.subjectId)
|| (query.attendantId != null && query.attendantId != event.payload.attendantId.value)
|| (query.moduleId != null && query.moduleId != event.payload.moduleId.value)
}
}.orEmpty()
}

private fun getSubjectActionsValue(caseDataCursor: Cursor): String {
while (caseDataCursor.moveToNext()) {
val key = caseDataCursor.getString(caseDataCursor.getColumnIndexOrThrow(COLUMN_DATUM_ID))
if (key == SIMPRINTS_COSYNC_SUBJECT_ACTIONS) {
return caseDataCursor.getString(caseDataCursor.getColumnIndexOrThrow(COLUMN_VALUE))
}
coSyncEnrolmentRecordEvents?.events?.filterIsInstance<EnrolmentRecordCreationEvent>()
?.let { events ->
caseEnrolmentRecordCreationEvents.addAll(events)
}
}
return ""
}

Simber.d(subjectActions)
private fun parseRecordEvents(subjectActions: String) = subjectActions.takeIf(String::isNotEmpty)?.let {
try {
jsonHelper.fromJson<CoSyncEnrolmentRecordEvents>(
json = it,
module = coSyncSerializationModule,
type = object : TypeReference<CoSyncEnrolmentRecordEvents>() {}
)
} catch (e: Exception) {
Simber.e("Error while parsing subjectActions", e)
null
}
}

return caseEnrolmentRecordCreationEvents
private val coSyncSerializationModule = SimpleModule().apply {
addSerializer(
TokenizableString::class.java,
TokenizationClassNameSerializer()
)
addDeserializer(
TokenizableString::class.java,
TokenizationClassNameDeserializer()
)
}

override suspend fun count(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ data class SubjectQuery(
val hasUntokenizedFields: Boolean? = null,
val moduleId: String? = null,
val sort: Boolean = false,
val afterSubjectId: String? = null
val afterSubjectId: String? = null,
val metadata: String? = null,
) : Serializable
Loading