From eadd84a10bf6e24585f854509fcac40420510918 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 14 Nov 2023 13:28:06 +0100 Subject: [PATCH] [ANDROSDK-1786] Implement support for ExperimentalFeature --- ...gsObjectRepositoryMockIntegrationShould.kt | 60 +++++++++++++++++++ core/src/main/assets/migrations/153.sql | 3 + core/src/main/assets/snapshots/snapshot.sql | 2 +- .../access/internal/BaseDatabaseOpenHelper.kt | 2 +- .../core/settings/ExperimentalFeature.kt} | 31 +++------- .../GeneralSettingObjectRepository.kt | 17 ++++++ .../settings/GeneralSettingTableInfo.java | 4 +- .../core/settings/GeneralSettings.java | 8 +++ .../internal/GeneralSettingStoreImpl.kt | 8 ++- ...Samples.java => GeneralSettingsSamples.kt} | 37 ++++++------ .../settings/general_settings_v2.json | 5 +- .../settings/GeneralSettingsV2Should.java | 2 + 12 files changed, 130 insertions(+), 49 deletions(-) create mode 100644 core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.kt create mode 100644 core/src/main/assets/migrations/153.sql rename core/src/{androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java => main/java/org/hisp/dhis/android/core/settings/ExperimentalFeature.kt} (63%) rename core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/{GeneralSettingsSamples.java => GeneralSettingsSamples.kt} (71%) diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.kt b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.kt new file mode 100644 index 0000000000..578451e4f4 --- /dev/null +++ b/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004-2022, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.android.testapp.settings + +import com.google.common.truth.Truth.assertThat +import org.hisp.dhis.android.core.settings.DataSyncPeriod +import org.hisp.dhis.android.core.settings.ExperimentalFeature +import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher +import org.hisp.dhis.android.core.utils.runner.D2JunitRunner +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(D2JunitRunner::class) +class GeneralSettingsObjectRepositoryMockIntegrationShould : BaseMockIntegrationTestFullDispatcher() { + @Test + fun find_android_setting() { + val generalSettings = d2.settingModule().generalSetting().blockingGet() + assertThat(generalSettings!!.dataSync()).isEqualTo(DataSyncPeriod.EVERY_24_HOURS) + } + + @Test + fun find_experimental_feature() { + assertThat( + d2.settingModule().generalSetting().blockingHasExperimentalFeature(ExperimentalFeature.NewFormLayout), + ).isTrue() + + assertThat( + d2.settingModule().generalSetting().blockingHasExperimentalFeature("newFormLayout"), + ).isTrue() + + assertThat( + d2.settingModule().generalSetting().blockingHasExperimentalFeature("nonExistingFeature"), + ).isFalse() + } +} diff --git a/core/src/main/assets/migrations/153.sql b/core/src/main/assets/migrations/153.sql new file mode 100644 index 0000000000..4a506f78f7 --- /dev/null +++ b/core/src/main/assets/migrations/153.sql @@ -0,0 +1,3 @@ +# Add experimentalFeatures in GeneralSetting (ANDROSDK-1786) + +ALTER TABLE GeneralSetting ADD COLUMN experimentalFeatures TEXT; diff --git a/core/src/main/assets/snapshots/snapshot.sql b/core/src/main/assets/snapshots/snapshot.sql index e186f46bdd..3da3373589 100644 --- a/core/src/main/assets/snapshots/snapshot.sql +++ b/core/src/main/assets/snapshots/snapshot.sql @@ -79,7 +79,7 @@ CREATE TABLE SectionGreyedFieldsLink (_id INTEGER PRIMARY KEY AUTOINCREMENT, sec CREATE TABLE AuthenticatedUser (_id INTEGER PRIMARY KEY AUTOINCREMENT, user TEXT NOT NULL UNIQUE, hash TEXT, FOREIGN KEY (user) REFERENCES User (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE UNIQUE INDEX event_data_element ON TrackedEntityDataValue(event, dataElement); CREATE UNIQUE INDEX tracked_entity_instance_attribute ON TrackedEntityAttributeValue(trackedEntityInstance, trackedEntityAttribute); -CREATE TABLE GeneralSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, encryptDB INTEGER, lastUpdated TEXT, reservedValues INTEGER, smsGateway TEXT, smsResultSender TEXT, matomoID INTEGER, matomoURL TEXT, allowScreenCapture INTEGER, messageOfTheDay TEXT); +CREATE TABLE GeneralSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, encryptDB INTEGER, lastUpdated TEXT, reservedValues INTEGER, smsGateway TEXT, smsResultSender TEXT, matomoID INTEGER, matomoURL TEXT, allowScreenCapture INTEGER, messageOfTheDay TEXT, experimentalFeatures TEXT); CREATE TABLE DataSetSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE, name TEXT, lastUpdated TEXT, periodDSDownload INTEGER, periodDSDBTrimming INTEGER, FOREIGN KEY (uid) REFERENCES DataSet (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE ProgramSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE, name TEXT, lastUpdated TEXT, teiDownload INTEGER, teiDBTrimming INTEGER, eventsDownload INTEGER, eventsDBTrimming INTEGER, updateDownload TEXT, updateDBTrimming TEXT, settingDownload TEXT, settingDBTrimming TEXT, enrollmentDownload TEXT, enrollmentDBTrimming TEXT, eventDateDownload TEXT, eventDateDBTrimming TEXT, enrollmentDateDownload TEXT, enrollmentDateDBTrimming TEXT, FOREIGN KEY (uid) REFERENCES Program (uid) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED); CREATE TABLE SynchronizationSetting (_id INTEGER PRIMARY KEY AUTOINCREMENT, dataSync TEXT, metadataSync TEXT, trackerImporterVersion TEXT, trackerExporterVersion TEXT, fileMaxLengthBytes INTEGER); diff --git a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.kt b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.kt index 0d14633ef0..1110228ca1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/arch/db/access/internal/BaseDatabaseOpenHelper.kt @@ -59,6 +59,6 @@ internal class BaseDatabaseOpenHelper(context: Context, targetVersion: Int) { } companion object { - const val VERSION = 152 + const val VERSION = 153 } } diff --git a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java b/core/src/main/java/org/hisp/dhis/android/core/settings/ExperimentalFeature.kt similarity index 63% rename from core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java rename to core/src/main/java/org/hisp/dhis/android/core/settings/ExperimentalFeature.kt index 85ecf61c79..5c6e76a2db 100644 --- a/core/src/androidTest/java/org/hisp/dhis/android/testapp/settings/GeneralSettingsObjectRepositoryMockIntegrationShould.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/ExperimentalFeature.kt @@ -1,19 +1,19 @@ /* - * Copyright (c) 2004-2022, University of Oslo + * Copyright (c) 2004-2023, University of Oslo * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * Neither the name of the HISP project nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -26,23 +26,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.hisp.dhis.android.testapp.settings; +package org.hisp.dhis.android.core.settings -import org.hisp.dhis.android.core.settings.DataSyncPeriod; -import org.hisp.dhis.android.core.settings.GeneralSettings; -import org.hisp.dhis.android.core.utils.integration.mock.BaseMockIntegrationTestFullDispatcher; -import org.hisp.dhis.android.core.utils.runner.D2JunitRunner; -import org.junit.Test; -import org.junit.runner.RunWith; - -import static com.google.common.truth.Truth.assertThat; - -@RunWith(D2JunitRunner.class) -public class GeneralSettingsObjectRepositoryMockIntegrationShould extends BaseMockIntegrationTestFullDispatcher { - - @Test - public void find_android_setting() { - GeneralSettings generalSettings = d2.settingModule().generalSetting().blockingGet(); - assertThat(generalSettings.dataSync()).isEqualTo(DataSyncPeriod.EVERY_24_HOURS); - } -} \ No newline at end of file +enum class ExperimentalFeature(val jsonName: String) { + NewFormLayout("newFormLayout"), +} diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingObjectRepository.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingObjectRepository.kt index 0191b460c9..34e61ba2f4 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingObjectRepository.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingObjectRepository.kt @@ -27,6 +27,7 @@ */ package org.hisp.dhis.android.core.settings +import io.reactivex.Single import org.hisp.dhis.android.core.arch.repositories.collection.ReadOnlyWithDownloadObjectRepository import org.hisp.dhis.android.core.arch.repositories.`object`.internal.ReadOnlyAnyObjectWithDownloadRepositoryImpl import org.hisp.dhis.android.core.settings.internal.GeneralSettingCall @@ -66,4 +67,20 @@ class GeneralSettingObjectRepository internal constructor( .build() } } + + fun blockingHasExperimentalFeature(featureName: String): Boolean { + return blockingGet()?.experimentalFeatures()?.contains(featureName) ?: false + } + + fun hasExperimentalFeature(featureName: String): Single { + return Single.fromCallable { blockingHasExperimentalFeature(featureName) } + } + + fun blockingHasExperimentalFeature(feature: ExperimentalFeature): Boolean { + return blockingGet()?.experimentalFeatures()?.contains(feature.jsonName) ?: false + } + + fun hasExperimentalFeature(feature: ExperimentalFeature): Single { + return Single.fromCallable { blockingHasExperimentalFeature(feature) } + } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingTableInfo.java b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingTableInfo.java index b8270771ea..0baa3ce83d 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingTableInfo.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettingTableInfo.java @@ -60,6 +60,7 @@ public static class Columns extends CoreColumns { public static final String MATOMO_URL = "matomoURL"; public static final String ALLOW_SCREEN_CAPTURE = "allowScreenCapture"; public static final String MESSAGE_OF_THE_DAY = "messageOfTheDay"; + public static final String EXPERIMENTAL_FEATURES = "experimentalFeatures"; @Override public String[] all() { @@ -72,7 +73,8 @@ public String[] all() { MATOMO_ID, MATOMO_URL, ALLOW_SCREEN_CAPTURE, - MESSAGE_OF_THE_DAY + MESSAGE_OF_THE_DAY, + EXPERIMENTAL_FEATURES ); } } diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettings.java b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettings.java index f3202f9d4d..2acd5b1f5a 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettings.java +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/GeneralSettings.java @@ -39,11 +39,13 @@ import com.google.auto.value.AutoValue; import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.DbDateColumnAdapter; +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreDataSyncPeriodColumnAdapter; import org.hisp.dhis.android.core.arch.db.adapters.ignore.internal.IgnoreMetadataSyncPeriodColumnAdapter; import org.hisp.dhis.android.core.common.CoreObject; import java.util.Date; +import java.util.List; @AutoValue @JsonDeserialize(builder = $$AutoValue_GeneralSettings.Builder.class) @@ -110,6 +112,10 @@ public String numberSmsConfirmation() { @Nullable public abstract String messageOfTheDay(); + @Nullable + @ColumnAdapter(StringListColumnAdapter.class) + public abstract List experimentalFeatures(); + public static GeneralSettings create(Cursor cursor) { return $AutoValue_GeneralSettings.createFromCursor(cursor); } @@ -150,6 +156,8 @@ public abstract static class Builder { public abstract Builder messageOfTheDay(String messageOfTheDay); + public abstract Builder experimentalFeatures(List experimentalFeatures); + public abstract GeneralSettings build(); } } \ No newline at end of file diff --git a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/GeneralSettingStoreImpl.kt b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/GeneralSettingStoreImpl.kt index eb8a838c75..0328bd1ac1 100644 --- a/core/src/main/java/org/hisp/dhis/android/core/settings/internal/GeneralSettingStoreImpl.kt +++ b/core/src/main/java/org/hisp/dhis/android/core/settings/internal/GeneralSettingStoreImpl.kt @@ -29,6 +29,7 @@ package org.hisp.dhis.android.core.settings.internal import android.database.Cursor import org.hisp.dhis.android.core.arch.db.access.DatabaseAdapter +import org.hisp.dhis.android.core.arch.db.adapters.custom.internal.StringListColumnAdapter import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementBinder import org.hisp.dhis.android.core.arch.db.stores.binders.internal.StatementWrapper import org.hisp.dhis.android.core.arch.db.stores.binders.internal.WhereStatementBinder @@ -52,7 +53,7 @@ internal class GeneralSettingStoreImpl( ) { companion object { - private val BINDER = StatementBinder { o: GeneralSettings, w: StatementWrapper -> + private val BINDER = StatementBinder { o: GeneralSettings, w: StatementWrapper -> w.bind(1, o.encryptDB()) w.bind(2, o.lastUpdated()) w.bind(3, o.reservedValues()) @@ -62,13 +63,14 @@ internal class GeneralSettingStoreImpl( w.bind(7, o.matomoURL()) w.bind(8, o.allowScreenCapture()) w.bind(9, o.messageOfTheDay()) + w.bind(10, StringListColumnAdapter.serialize(o.experimentalFeatures())) } - private val WHERE_UPDATE_BINDER = WhereStatementBinder { + private val WHERE_UPDATE_BINDER = WhereStatementBinder { _: GeneralSettings, _: StatementWrapper -> } - private val WHERE_DELETE_BINDER = WhereStatementBinder { + private val WHERE_DELETE_BINDER = WhereStatementBinder { _: GeneralSettings, _: StatementWrapper -> } } diff --git a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.java b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.kt similarity index 71% rename from core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.java rename to core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.kt index 9085cde3be..802de20ade 100644 --- a/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.java +++ b/core/src/sharedTest/java/org/hisp/dhis/android/core/data/settings/GeneralSettingsSamples.kt @@ -25,26 +25,25 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +package org.hisp.dhis.android.core.data.settings -package org.hisp.dhis.android.core.data.settings; +import org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils +import org.hisp.dhis.android.core.settings.GeneralSettings -import org.hisp.dhis.android.core.data.utils.FillPropertiesTestUtils; -import org.hisp.dhis.android.core.settings.GeneralSettings; - -public class GeneralSettingsSamples { - - public static GeneralSettings getGeneralSettings() { +object GeneralSettingsSamples { + fun getGeneralSettings(): GeneralSettings { return GeneralSettings.builder() - .id(1L) - .encryptDB(true) - .lastUpdated(FillPropertiesTestUtils.LAST_UPDATED) - .reservedValues(100) - .smsGateway("+34678456123") - .smsResultSender("+34654321456") - .matomoID(123) - .matomoURL("https://www.matomo.org") - .allowScreenCapture(true) - .messageOfTheDay("Message of the day") - .build(); + .id(1L) + .encryptDB(true) + .lastUpdated(FillPropertiesTestUtils.LAST_UPDATED) + .reservedValues(100) + .smsGateway("+34678456123") + .smsResultSender("+34654321456") + .matomoID(123) + .matomoURL("https://www.matomo.org") + .allowScreenCapture(true) + .messageOfTheDay("Message of the day") + .experimentalFeatures(listOf("newFormLayout")) + .build() } -} \ No newline at end of file +} diff --git a/core/src/sharedTest/resources/settings/general_settings_v2.json b/core/src/sharedTest/resources/settings/general_settings_v2.json index b7d1d893de..d66244b75b 100644 --- a/core/src/sharedTest/resources/settings/general_settings_v2.json +++ b/core/src/sharedTest/resources/settings/general_settings_v2.json @@ -6,5 +6,8 @@ "reservedValues": 40, "smsResultSender": "+9456498778", "allowScreenCapture": true, - "messageOfTheDay": "Message of the day" + "messageOfTheDay": "Message of the day", + "experimentalFeatures": [ + "newFormLayout" + ] } \ No newline at end of file diff --git a/core/src/test/java/org/hisp/dhis/android/core/settings/GeneralSettingsV2Should.java b/core/src/test/java/org/hisp/dhis/android/core/settings/GeneralSettingsV2Should.java index 13d6c7f1c0..6eaad1f740 100644 --- a/core/src/test/java/org/hisp/dhis/android/core/settings/GeneralSettingsV2Should.java +++ b/core/src/test/java/org/hisp/dhis/android/core/settings/GeneralSettingsV2Should.java @@ -61,5 +61,7 @@ public void map_from_json_string() throws IOException, ParseException { assertThat(generalSettings.matomoURL()).isEqualTo("https://www.matomo.org"); assertThat(generalSettings.allowScreenCapture()).isTrue(); assertThat(generalSettings.messageOfTheDay()).isEqualTo("Message of the day"); + assertThat(generalSettings.experimentalFeatures().size()).isEqualTo(1); + assertThat(generalSettings.experimentalFeatures().get(0)).isEqualTo("newFormLayout"); } }