From 7c3e48926affea452b135d81bcce64c94b6a888d Mon Sep 17 00:00:00 2001 From: Matthias Urhahn <matthias.urhahn@sap.com> Date: Tue, 13 Apr 2021 14:58:56 +0200 Subject: [PATCH] Skeletons for new test result architecture (EXPOSUREAPP-6007) (#2818) * Skeletons for new test result architecture, Draft1 * Add missing property. * Fix LINTs * Address PR comments. --- .../coronatest/CoronaTestModule.kt | 6 +++ .../coronatest/CoronaTestRepository.kt | 50 +++++++++++++++++++ .../coronatest/qrcode/CoronaTestQRCode.kt | 30 +++++++++++ .../qrcode/CoronaTestQRCodeValidation.kt | 12 +++++ .../coronatest/server/CoronaTestServer.kt | 7 +++ .../coronatest/storage/CoronaTestStorage.kt | 23 +++++++++ .../coronatest/type/CoronaTest.kt | 23 +++++++++ .../type/antigen/RapidAntigenCoronaTest.kt | 26 ++++++++++ .../coronatest/type/pcr/PCRCoronaTest.kt | 25 ++++++++++ .../util/di/ApplicationComponent.kt | 2 + 10 files changed, 204 insertions(+) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestModule.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestRepository.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidation.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/server/CoronaTestServer.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/storage/CoronaTestStorage.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/CoronaTest.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/antigen/RapidAntigenCoronaTest.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRCoronaTest.kt diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestModule.kt new file mode 100644 index 000000000..1a6c81a94 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestModule.kt @@ -0,0 +1,6 @@ +package de.rki.coronawarnapp.coronatest + +import dagger.Module + +@Module +class CoronaTestModule diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestRepository.kt new file mode 100644 index 000000000..832198cf3 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/CoronaTestRepository.kt @@ -0,0 +1,50 @@ +package de.rki.coronawarnapp.coronatest + +import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestGUID +import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestQRCode +import de.rki.coronawarnapp.coronatest.server.CoronaTestServer +import de.rki.coronawarnapp.coronatest.storage.CoronaTestStorage +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import timber.log.Timber +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CoronaTestRepository @Inject constructor( + private val storage: CoronaTestStorage, + private val server: CoronaTestServer, +) { + + val coronaTests: Flow<Set<CoronaTest>> = emptyFlow() + + /** + * When this returns and there was no exception, the test was registered and a valid registrationToken obtained. + * Your new test should be available via **coronaTests**. + */ + suspend fun registerTest(request: CoronaTestQRCode) { + Timber.tag(TAG).i("registerTest(request=%s)", request) + } + + suspend fun removeTest(guid: CoronaTestGUID): CoronaTest { + Timber.tag(TAG).i("removeTest(guid=%s)", guid) + + throw NotImplementedError() + } + + suspend fun markAsSubmitted(guid: CoronaTestGUID) { + Timber.tag(TAG).i("markAsSubmitted(guid=%s)", guid) + } + + /** + * Passing **null** will refresh all test types. + */ + fun refresh(type: CoronaTest.Type? = null) { + Timber.tag(TAG).d("refresh(type=%s)", type) + } + + companion object { + const val TAG = "CoronaTestRepo" + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt new file mode 100644 index 000000000..36eda1768 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCode.kt @@ -0,0 +1,30 @@ +package de.rki.coronawarnapp.coronatest.qrcode + +import android.os.Parcelable +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import kotlinx.parcelize.Parcelize +import org.joda.time.Instant + +sealed class CoronaTestQRCode : Parcelable { + + abstract val type: CoronaTest.Type + abstract val guid: CoronaTestGUID + + @Parcelize + data class PCR( + override val type: CoronaTest.Type, + override val guid: CoronaTestGUID, + ) : CoronaTestQRCode() + + @Parcelize + data class RapidAntigen( + override val type: CoronaTest.Type, + override val guid: CoronaTestGUID, + val createdAt: Instant, + val firstName: String?, + val lastName: String?, + val dateOfBirth: String?, + ) : CoronaTestQRCode() +} + +typealias CoronaTestGUID = String diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidation.kt new file mode 100644 index 000000000..717aaf783 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidation.kt @@ -0,0 +1,12 @@ +package de.rki.coronawarnapp.coronatest.qrcode + +import dagger.Reusable +import javax.inject.Inject + +@Reusable +class CoronaTestQRCodeValidation @Inject constructor() { + + suspend fun validate(qrCode: String): CoronaTestQRCode { + throw NotImplementedError() + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/server/CoronaTestServer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/server/CoronaTestServer.kt new file mode 100644 index 000000000..7319755a4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/server/CoronaTestServer.kt @@ -0,0 +1,7 @@ +package de.rki.coronawarnapp.coronatest.server + +import dagger.Reusable +import javax.inject.Inject + +@Reusable +class CoronaTestServer @Inject constructor() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/storage/CoronaTestStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/storage/CoronaTestStorage.kt new file mode 100644 index 000000000..771397027 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/storage/CoronaTestStorage.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.coronatest.storage + +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import timber.log.Timber +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CoronaTestStorage @Inject constructor() { + + suspend fun load(): Set<CoronaTest> { + Timber.tag(TAG).d("load()") + throw NotImplementedError() + } + + suspend fun save(tests: Set<CoronaTest>) { + Timber.tag(TAG).d("save(tests=%s)", tests) + } + + companion object { + private const val TAG = "CoronaTestStorage" + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/CoronaTest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/CoronaTest.kt new file mode 100644 index 000000000..08041c76e --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/CoronaTest.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.coronatest.type + +import com.google.gson.annotations.SerializedName +import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestGUID + +interface CoronaTest { + val testGUID: CoronaTestGUID + val registrationToken: RegistrationToken + val type: Type + val isRefreshing: Boolean + val isSubmissionAllowed: Boolean + val isSubmitted: Boolean + + enum class Type { + @SerializedName("PCR") + PCR, + + @SerializedName("RAPID_ANTIGEN") + RAPID_ANTIGEN, + } +} + +typealias RegistrationToken = String diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/antigen/RapidAntigenCoronaTest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/antigen/RapidAntigenCoronaTest.kt new file mode 100644 index 000000000..654a4cdb5 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/antigen/RapidAntigenCoronaTest.kt @@ -0,0 +1,26 @@ +package de.rki.coronawarnapp.coronatest.type.antigen + +import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestGUID +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import de.rki.coronawarnapp.coronatest.type.RegistrationToken + +data class RapidAntigenCoronaTest( + override val testGUID: CoronaTestGUID, + override val registrationToken: RegistrationToken, + override val isRefreshing: Boolean, + override val isSubmissionAllowed: Boolean, + override val isSubmitted: Boolean, + val state: State, +) : CoronaTest { + + override val type: CoronaTest.Type = CoronaTest.Type.RAPID_ANTIGEN + + enum class State { + PENDING, + INVALID, + POSITIVE, + NEGATIVE, + REDEEMED, + OUTDATED, + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRCoronaTest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRCoronaTest.kt new file mode 100644 index 000000000..9d4030826 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/type/pcr/PCRCoronaTest.kt @@ -0,0 +1,25 @@ +package de.rki.coronawarnapp.coronatest.type.pcr + +import de.rki.coronawarnapp.coronatest.qrcode.CoronaTestGUID +import de.rki.coronawarnapp.coronatest.type.CoronaTest +import de.rki.coronawarnapp.coronatest.type.RegistrationToken + +data class PCRCoronaTest( + override val testGUID: CoronaTestGUID, + override val registrationToken: RegistrationToken, + override val isRefreshing: Boolean, + override val isSubmissionAllowed: Boolean, + override val isSubmitted: Boolean, + val state: State, +) : CoronaTest { + + override val type: CoronaTest.Type = CoronaTest.Type.PCR + + enum class State { + PENDING, + INVALID, + POSITIVE, + NEGATIVE, + REDEEMED, + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt index dbc57fbeb..98551b212 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt @@ -11,6 +11,7 @@ import de.rki.coronawarnapp.bugreporting.BugReporter import de.rki.coronawarnapp.bugreporting.BugReportingModule import de.rki.coronawarnapp.bugreporting.BugReportingSharedModule import de.rki.coronawarnapp.bugreporting.debuglog.DebugLogger +import de.rki.coronawarnapp.coronatest.CoronaTestModule import de.rki.coronawarnapp.datadonation.DataDonationModule import de.rki.coronawarnapp.diagnosiskeys.DiagnosisKeysModule import de.rki.coronawarnapp.diagnosiskeys.DownloadDiagnosisKeysTaskModule @@ -77,6 +78,7 @@ import javax.inject.Singleton DataDonationModule::class, SecurityModule::class, EventRegistrationModule::class, + CoronaTestModule::class, ] ) interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> { -- GitLab